私は SWI Prolog の実装に関する大学の試験のために Prolog を勉強しています。
順列を使用して問題を解決するこのバージョンの 8 クイーン問題がどのように機能するかについて、私は疑問を持っています。
solution(Queens) :-
permutation([1,2,3,4,5,6,7,8], Queens),
safe(Queens).
permutation([],[]).
permutation([Head|Tail],PermList) :-
permutation(Tail,PermTail),
del(Head,PermList,PermTail).
del(Item,[Item|List],List).
del(Item,[First|List],[First|List1]) :-
del(Item,List,List1).
safe([]).
safe([Queen|Others]) :-
safe(Others),
noattack(Queen,Others,1).
noattack(_,[],_).
noattack(Y,[Y1|Ylist],Xdist) :-
Y1-Y=\=Xdist,
Y-Y1=\=Xdist,
Dist1 is Xdist + 1,
noattack(Y,Ylist,Dist1).
以前の解決策では、次のソリューション テンプレートを使用しました: [1\Y1、2\Y2、3\Y3、4\Y4、5\Y5、6\Y6、7\Y7、8\Y8] これは、すべての女王が異なる行にある場合、X 値が制限される可能性があります。
このバージョンのプログラムでは、垂直方向の攻撃を防ぐためにすべてのクイーンが異なる行にある必要があることがわかります。そのため、各行にクイーンがあります。
したがって、情報を失うことなく、解決策はリストの順列になると言えます: [1,2,3,4,5,6,7,8]で、すべての要素が女王の Y 座標を表します。
したがって、この場合、私はその Y 座標 (その行インデックス) だけでクイーンの位置を rappresenting しています。
したがって、Queensが元のリスト[1,2,3,4,5,6,7,8]の前置突然変異であり、この順列が安全な場合(すべてのQueensこの順列リストは、他のクイーンを攻撃しません)。
OK、これは明らかです...これで安全な関係が定義されました。
リストが空の場合、攻撃がないため安全であるという基本的なケースがあります。
また、リストが空でない一般的なケースがあります。リストが空でない場合は、 [Queen|Others]に分割できます。ここで、Queenはリストの最初のクイーンで、 Othersは残りのサブリストです...したがって、サブリスト Others の場合、元のリスト[Queen|Others]は安全です。それ自体が解決策であり (安全であれば、Others に攻撃がない場合)、最初のアイテムのQueenが Othersサブリストの他の Queen を攻撃しない場合...
わかりました...今までは、私には明らかだと思います...
今、noattack関係の定義に問題があります!!!
問題は、私がクイーンの位置を Y 座標と X 座標だけで明示的に表現していないことです。
私は、ラププレゼンテーションのこの制限を回避するために、次の一般化があることを理解しています (よく理解できていることを願っています...よくわかりません...): ** また、各列に女王がいなければならないことも知っていますしたがって、リストの最初のクイーン (Queen) とサブリスト Others からの X 距離は 1** でなければなりません
最初の項目 Queen とサブリスト Others からの距離は、最初の項目 Queen とそれに最も近い Queen からの X 距離です。
したがって、クイーンが異なる列にある場合、 noattack関係は TRUE であり (コンストラクションでは常に true)、クイーンと Others サブリストの最も近いクイーンからの X 距離が 1 であると言って、別の行にある必要があることを表現できます。
しかし、私の推論が真実であれば、コードのこの部分でこのことをどのように表現するかを理解しようとすると、多くの問題が発生します。
noattack(Y,[Y1|Ylist],Xdist) :-
Y1-Y=\=Xdist,
Y-Y1=\=Xdist,
Dist1 is Xdist + 1,
noattack(Y,Ylist,Dist1).