私がやりたかったことは、特定のリストから要素のすべての組み合わせを生成することでした。例: [a,b,c] から、次のことが必要になる場合があります。
[]
[a]
[b]
[c]
[a,a]
[a,b]
[a,c]
[b,a]
...
等々。おそらく、これを行う魔法のプロローグワンライナーがあります。もしそうなら、私はそれを聞いてみたいです。
ただし、私の質問は、この特定の問題を解決することではなく、Prolog の検索アルゴリズムの微妙な点を誰かに説明してほしいということです。
したがって、上記の問題を解決するために最初に行ったことは次のとおりです。
members([], _).
members([X|Xs], List) :-
member(X,List),
members(Xs, List).
これはうまく機能しますが、可能なすべての結果を返しますが、適切な順序ではありません。
[]
[a]
[a,a]
[a,a,a]
問題ありません。私は本当に特定の長さまでのすべての組み合わせが欲しいだけです。そこで、最初に正確に特定の長さのものを取得することにしました。
membersWithLength(Members, List, Bound) :-
L = Bound,
length(Members, L), members(Members, List).
これは、たとえば長さ 2 の場合にうまく機能します。
[a,a]
[a,b]
[a,c]
...
等々。clpfd を使用して上記の関数を利用して、特定の長さまでのすべてのリストを取得しようとした私の試みはうまくいきませんでした:
:- use_module(library(clpfd)).
membersLessThan(Members, List, Bound) :-
L in 0..Bound, % I also tried L #=< Bound
membersWithLength(Members, List, L).
作品の種類。正しい結果 (長さが Bound 未満のリスト) を見つけます。しかし、それらが見つかった後、さらに結果を探して継続的にループします。たとえば、長さ 2 の場合:
[]
[a]
[b]
[c]
[a,a]
[a,b]
...
[c,c]
Hangs looking for more solutions.
これが私の質問の核心だと思います。(トレースによると) prolog が可能な解決策としてますます大きなリストをチェックし続ける理由を誰かが説明できますか? そして、プロローグがこの運命の旅を避けるのを助ける方法があるかどうか誰か教えてもらえますか?
最終的には次のコードを使用して問題を解決しましたが、clpfd の整数制約を使用してリストのサイズを制限する方法がわからなくてがっかりしました。
membersLessThan_(Members, List, Bound) :-
numlist(0,Bound,ZeroToBound),
member(L, ZeroToBound),
membersWithLength(Members, List, L).
SWISH に関連するすべてのコードは次のとおりです: http://swish.swi-prolog.org/p/allcombos.pl