1

私のIAの任務は、アインシュタイン問題を解決することです。

PrologのCSPモデルを使用して解決する必要があります。モデルは与えられていませんが、問題といくつかの入力データだけが与えられています。私の解決策は一般的なものでなければなりません。つまり、一部の入力データについては、解決策を提供する必要があります。問題の次元はNです。たとえば、Nは5(5つの家があります)の場合がありますが、変動する可能性があります。

インターネットで見つけた多くのソリューションは、制約をコードに直接配置しますが、入力データを使用して制約を生成する必要があります。この問題は、MAC(Maintain Arc-Consistency)アルゴリズムを使用して解決する必要があります。

私はそれについてたくさん読んだ(アインシュタインのなぞなぞ)。問題を実装するには、問題の表現が必要です。

問題は、Prologで問題を表現する方法が正確にわからないことです(基本的なPrologを知っている、追加のライブラリを使用していない、clpfdライブラリ(prolog clpソルバー)を使用することは許可されていません)。

入力(14の手がかり)から制約を作成する必要があることはわかっています+同じグループ(国籍など)のすべての変数が異なる必要があるという制約は、次のように述語を実装できます。

my_all_different(like all_different/1 offered by clpfd).

例えば:

Attributes = ['Color', 'Nationality', 'Drink', 'Smoke', 'Pet'].

Values = [['Blue', 'Green', 'Ivory', 'Red', 'Yellow'],
['Englishman', 'Japanese', 'Norwegian', 'Spaniard', 'Ukrainian'],
['Coffee', 'Milk', 'Orange juice', 'Tea', 'Water'],
['Chesterfield', 'Kools', 'Lucky Strike', 'Old Gold', 'Parliament'],
['Dog', 'Fox', 'Horse', 'Snails', 'Zebra']
]).

Statements = 'The Englishman lives in the red house',
'The Spaniard owns the dog',
'Coffee is drunk in the green house',
'The Ukrainian drinks tea',
'The green house is immediately to the right of the ivory house',
'The Old Gold smoker owns snails',
'Kools are smoked in the yellow house',
'Milk is drunk in the middle house',
'The Norwegian lives in the first house',
'The man who smokes Chesterfield lives in the house next to the man with the fox',
'Kools are smoked in the house next to the house where the horse is kept',
'The Lucky Strike smoker drinks orange juice',
'The Japanese smokes Parliament',
'The Norwegian lives next to the blue house'
]).

Question = 'Who owns a zebra'?

今、私はこの入力を解析し、リストのリストを取得することができました:

R = [[red,englishman]
[spaniard,dog]
[green,coffee]
[ukrainian,tea]
[green,ivory,right]
[old,snails]
[yellow,kools]
[milk,middle]
[norwegian,first]
[chesterfield,fox,next]
[kools,horse,next]
[orange,lucky]
[japanese,parliament]
[blue,norwegian,next]].

今、私はこの生成された情報を使用していくつかの制約を構築する必要があると思います、私が読んだことから、バイナリ制約(私が思う述語として表される)を使用するのは良い考えですが、私はいくつかの単項制約も持っているので、どうすればよいですか?それらすべてを含めるための制約を表しますか?

もう1つの問題は、リストを検索して変更する必要がないように、変数(計算データがある場所)をどのように表現するかです(プロローグでは、命令型言語のようにリストを変更できないため)。

そこで、変数のリストを使用することを考えました。各変数/要素は3タプルで表されます:( var, domain, attrV)、varには変数の現在の値が含まれ、ドメインは次のようなリストです:[1、2、3、4、 ..、N]であり、attrVは、対応する属性(たとえば赤)の(Nの)1つの値です。1つの要素は次のようになります(C, [1, 2, 3, 4, 5], red)

その他の問題:タプルのキューがあり、制約が満たされない場合はこのキューが変更されるため、プロローグ(AC-3アルゴリズムを使用)にMACアルゴリズムを実装するにはどうすればよいですか?これは変数リストを変更することを意味します、そして再び、Prologのリストをどのように変更すればよいですか。

どんな助けでもいただければ幸いです!


上記のリンクからCSPソルバーを使用して問題の特定のバージョンを解決しようとしましたが、それでも解決策を見つけることができません。この方法で解決策を知ることができるので、解決策を取得したいと思います。一般バージョンの制約を正しく表します。

追加されたコード:

% Computational Intelligence: a logical approach.
% Prolog Code.
% A CSP solver using arc consistency (Figure 4.8)
% Copyright (c) 1998, Poole, Mackworth, Goebel and Oxford University Press.

% csp(Domains, Relations) means that each variable has
% an instantiation to one of the values in its Domain
% such that all the Relations are satisfied.
% Domains represented as list of
% [dom(V,[c1,...,cn]),...]
% Relations represented as [rel([X,Y],r(X,Y)),...]
%  for some r
csp(Doms,Relns) :-
   write('CSP Level'), nl,
   ac(Doms,Relns).

% ac(Dom,Relns) is true if the domain constrants
% specified in Dom and the binary relations
% constraints specified in Relns are satisfied.
ac(Doms,Relns) :-
   make_arcs(Relns,A),
   consistent(Doms,[],A,A),
   write('Final Doms '), write(Doms), nl, %test
   write('Final Arcs '), write(A), nl. %test

% make_arcs(Relns, Arcs) makes arcs Arcs corresponding to
% relations Relns. There are acrs for each ordering of
% variables in a relations.
make_arcs([],[]).
make_arcs([rel([X,Y],R)|O],
          [rel([X,Y],R),rel([Y,X],R)|OA]) :-
   make_arcs(O,OA).

% consistent(Doms,CA,TDA,A) is true if
% Doms is a set of domains
% CA is a set of consistent arcs,
% TDA is a list of arcs to do
% A is a list of all arcs
consistent(Doms,CA,TDA,A) :-
   consider(Doms,RedDoms,CA,TDA),
   write('Consistent Doms '), write(RedDoms), nl, %test
   solutions(RedDoms,A),
   write('Consistent Doms '), write(RedDoms), nl, %test
   write('Consistent Arcs '), write(A), nl. %test

% consider(D0,D1,CA,TDA)
% D0 is the set of inital domains
% D1 is the set of reduced domains
% CA = consistent arcs,
% TDA = to do arcs
consider(D,D,_,[]).
consider(D0,D3,CA,[rel([X,Y],R)|TDA]) :-
   choose(dom(XV,DX),D0,D1),X==XV,
  % write('D0 '), write(D0),
  % write('D1 '), write(D1), nl,
   choose(dom(YV,DY),D1,_),Y==YV, !,
   prune(X,DX,Y,DY,R,NDX),
   ( NDX = DX
   ->
     consider(D0,D3,[rel([X,Y],R)|CA],TDA)
   ; acc_todo(X,Y,CA,CA1,TDA,TDA1),
     consider([dom(X,NDX)|D1],D3,
              [rel([X,Y],R)|CA1],TDA1)).

% prune(X,DX,Y,DY,R,NDX)
% variable X had domain DX
% variable Y has domain DY
% R is a relation on X and Y
% NDX = {X in DX | exists Y such that R(X,Y) is true}
prune(_,[],_,_,_,[]).
prune(X,[V|XD],Y,YD,R,XD1):-
   \+ (X=V,member(Y,YD),R),!,
   prune(X,XD,Y,YD,R,XD1).
prune(X,[V|XD],Y,YD,R,[V|XD1]):-
   prune(X,XD,Y,YD,R,XD1).

% acc_todo(X,Y,CA,CA1,TDA,TDA1)
% given variables X and Y,
% updates consistent arcs from CA to CA1 and
% to do arcs from TDA to TDA1
acc_todo(_,_,[],[],TDA,TDA).
acc_todo(X,Y,[rel([U,V],R)|CA0],
         [rel([U,V],R)|CA1],TDA0,TDA1) :-
   ( X \== V
   ; X == V,
     Y == U),
   acc_todo(X,Y,CA0,CA1,TDA0,TDA1).
acc_todo(X,Y,[rel([U,V],R)|CA0],
         CA1,TDA0,[rel([U,V],R)|TDA1]) :-
   X == V,
   Y \== U,
   acc_todo(X,Y,CA0,CA1,TDA0,TDA1).

% solutions(Doms,Arcs) given a reduced set of
% domains, Dome, and arcs Arcs, solves the CSP.
solutions(Doms,_) :-
   solve_singletons(Doms),
   write('Single Doms '), write(Doms), nl. %test
solutions(Doms,A) :-
   my_select(dom(X,[XV1,XV2|XVs]),Doms,ODoms),
   split([XV1,XV2|XVs],DX1,DX2),
   acc_todo(X,_,A,CA,[],TDA),
   ( consistent([dom(X,DX1)|ODoms],CA,TDA,A)
   ; consistent([dom(X,DX2)|ODoms],CA,TDA,A)).

% solve_singletons(Doms) is true if Doms is a
% set of singletom domains, with the variables
% assigned to the unique values in the domain
solve_singletons([]).
solve_singletons([dom(X,[X])|Doms]) :-
   solve_singletons(Doms).

% select(E,L,L1) selects the first element of
% L that matches E, with L1 being the remaining
% elements.
my_select(D,Doms,ODoms) :-
   select(D,Doms,ODoms), !.

% choose(E,L,L1) chooses an element of
% L that matches E, with L1 being the remaining
% elements.
choose(D,Doms,ODoms) :-
   select(D,Doms,ODoms).

% split(L,L1,L2) splits list L into two lists L1 and L2
% with the about same number of elements in each list.
split([],[],[]).
split([A],[A],[]).
split([A,B|R],[A|R1],[B|R2]) :-
   split(R,R1,R2).

/* -------------------------------------------------------------------*/


cs1(V, V). %A1 = A2
cs2(V1, V2) :- (V1 is V2 - 1; V2 is V1 - 1). %next
cs3(V1, V2) :- V1 is V2 + 1. %right


zebra(English,Spaniard,Ukrainian,Norwegian,Japanese,
       Red,Green,Ivory,Yellow,Blue,
       Dog,Snails,Fox,Horse,Zebra,
       Coffee,Tea,Milk,Orange_Juice,Water,
       Old_Gold,Kools,Chesterfields,Lucky_Strike,Parliaments) :-

 csp([dom(English, [1, 2, 3, 4, 5]),
     dom(Spaniard, [1, 2, 3, 4, 5]),
     dom(Ukrainian, [1, 2, 3, 4, 5]),
     dom(Norwegian, [1, 2, 3, 4, 5]),
     dom(Japanese, [1, 2, 3, 4, 5]),
     dom(Red, [1, 2, 3, 4, 5]),
     dom(Green, [1, 2, 3, 4, 5]),
     dom(Ivory, [1, 2, 3, 4, 5]),
     dom(Yellow, [1, 2, 3, 4, 5]),
     dom(Blue, [1, 2, 3, 4, 5]),
     dom(Dog, [1, 2, 3, 4, 5]),
     dom(Snails, [1, 2, 3, 4, 5]),
     dom(Fox, [1, 2, 3, 4, 5]),
     dom(Horse, [1, 2, 3, 4, 5]),
     dom(Zebra, [1, 2, 3, 4, 5]),
     dom(Coffee, [1, 2, 3, 4, 5]),
     dom(Tea, [1, 2, 3, 4, 5]),
     dom(Milk, [1, 2, 3, 4, 5]),
     dom(Orange_Juice, [1, 2, 3, 4, 5]),
     dom(Water, [1, 2, 3, 4, 5]),
     dom(Old_Gold, [1, 2, 3, 4, 5]),
     dom(Kools, [1, 2, 3, 4, 5]),
     dom(Chesterfields, [1, 2, 3, 4, 5]),
     dom(Lucky_Strike, [1, 2, 3, 4, 5]),
     dom(Parliaments, [1, 2, 3, 4, 5])],
     [rel([English, Red], cs1(English,Red)),
     rel([Spaniard, Dog], cs1(Spaniard,Dog)),
     rel([Coffee, Green], cs1(Coffee,Green)),
     rel([Ukrainian, Tea], cs1(Ukrainian,Tea)),
     rel([Green, Ivory], cs3(Green,Ivory)),
     rel([Old_Gold, Snails], cs1(Old_Gold,Snails)),
     rel([Kools, Yellow], cs1(Kools,Yellow)),
     rel([Milk, Milk], Milk = 3),
     rel([Norwegian, Norwegian], Norwegian = 1), %here is the problem
     rel([Chesterfields, Fox], cs2(Chesterfields,Fox)),
     rel([Kools, Horse], cs2(Kools,Horse)),
     rel([Lucky_Strike, Orange_juice], cs1(Lucky_Strike,Orange_juice)),
     rel([Japanese, Parliaments], cs1(Japanese,Parliaments)),
     rel([Norwegian, Blue], cs2(Norwegian,Blue))]).
4

1 に答える 1

2

いくつかの検索を行った後、サンプルデータのアーク整合性を使用して制約の満足度について 読むことをお勧めします

これまでの取り組みをここでもう一度編集します。残念ながら、最後の制約を追加すると結果が無効になります。明日は理由を理解しようとします

朗報!! next/2でばかげたバグを見つけました

:- include(csp).

next(V1, V2) :-
    succ(V1, V2) ; succ(V2, V1).

dom(I, O, D) :-
    maplist(dom, I, O),
    alldiff(I, [], D).
dom(V, dom(V, [1,2,3,4,5])).

alldiff([], D, D).
alldiff([V|Vs], S, D) :-
    maplist(rdiff(V), Vs, Ds),
    append(S, Ds, As),
    alldiff(Vs, As, D).

rdiff(A, B, D) :- rel(A \= B, D).

rel(R, rel([A, B], R)) :- R =.. [_, A, B].

zebra :-
    People = [English, Spaniard, Ukrainian, Norwegian, Japanese],
    Color = [Red, Green, Ivory, Yellow, Blue],
    Pet = [Dog, Snails, Fox, Horse, Zebra],
    Drink = [Coffee, Tea, Milk, Orange_Juice, _Water],
    Smoke = [Old_Gold, Kools, Chesterfields, Lucky_Strike, Parliaments],
    maplist(dom, [People, Color, Pet, Drink, Smoke], DomT, DiffPair),
    flatten(DomT, Doms),
    maplist(rel,
        [English = Red % The Englishman lives in the red house
        ,Spaniard = Dog % The Spaniard owns the dog
        ,Ukrainian = Tea % The Ukrainian drinks tea
        ,Coffee = Green % Coffee is drunk in the green house
        ,succ(Ivory, Green) % The green house is immediately to the right of the ivory house
        ,Old_Gold = Snails % The Old Gold smoker owns snails
        ,Kools = Yellow % Kools are smoked in the yellow house
        ,Milk = H3 % Milk is drunk in the middle house
        ,Norwegian = H1 % The Norwegian lives in the first house
        ,next(Chesterfields, Fox) % The man who smokes Chesterfield lives in the house next to the man with the fox
        ,next(Kools, Horse) % Kools are smoked in the house next to the house where the horse is kept
        ,Lucky_Strike = Orange_Juice % The Lucky Strike smoker drinks orange juice
        ,Japanese = Parliaments % The Japanese smokes Parliament
        ,next(Norwegian, Blue) % The Norwegian lives next to the blue house
        ], ConstrS),
    flatten([DiffPair, ConstrS], Rels),
    csp([dom(H1, [1]), dom(H3, [3])|Doms], Rels),
    maplist(writeln,
        [people:[English, Spaniard, Ukrainian, Norwegian, Japanese],
         color:[Red, Green, Ivory, Yellow, Blue],
         pet:[Dog, Snails, Fox, Horse, Zebra],
         drink:[Coffee, Tea, Milk, Orange_Juice, _Water],
         smoke:[Old_Gold, Kools, Chesterfields, Lucky_Strike, Parliaments]
        ]).

SWI-Prologに適合したcsp.plを分離しました。ここにあります

% Computational Intelligence: a logical approach.
% Prolog Code.
% A CSP solver using arc consistency (Figure 4.8)
% Copyright (c) 1998, Poole, Mackworth, Goebel and Oxford University Press.

% csp(Domains, Relations) means that each variable has
% an instantiation to one of the values in its Domain
% such that all the Relations are satisfied.
% Domains represented as list of
% [dom(V,[c1,...,cn]),...]
% Relations represented as [rel([X,Y],r(X,Y)),...]
%  for some r
csp(Doms,Relns) :-
   ac(Doms,Relns).

% ac(Dom,Relns) is true if the domain constrants
% specified in Dom and the binary relations
% constraints specified in Relns are satisfied.
ac(Doms,Relns) :-
   make_arcs(Relns,A),
   consistent(Doms,[],A,A).

% make_arcs(Relns, Arcs) makes arcs Arcs corresponding to
% relations Relns. There are acrs for each ordering of
% variables in a relations.
make_arcs([],[]).
make_arcs([rel([X,Y],R)|O],
          [rel([X,Y],R),rel([Y,X],R)|OA]) :-
   make_arcs(O,OA).

% consistent(Doms,CA,TDA,A) is true if
% Doms is a set of domains
% CA is a set of consistent arcs,
% TDA is a list of arcs to do
% A is a list of all arcs
consistent(Doms,CA,TDA,A) :-
   consider(Doms,RedDoms,CA,TDA),
   solutions(RedDoms,A).

% consider(D0,D1,CA,TDA)
% D0 is the set of inital domains
% D1 is the set of reduced domains
% CA = consistent arcs,
% TDA = to do arcs
consider(D,D,_,[]).
consider(D0,D3,CA,[rel([X,Y],R)|TDA]) :-
   choose(dom(XV,DX),D0,D1),X==XV,
   choose(dom(YV,DY),D1,_),Y==YV, !,
   prune(X,DX,Y,DY,R,NDX),
   ( NDX = DX
   ->
     consider(D0,D3,[rel([X,Y],R)|CA],TDA)
   ; acc_todo(X,Y,CA,CA1,TDA,TDA1),
     consider([dom(X,NDX)|D1],D3,
              [rel([X,Y],R)|CA1],TDA1)).

% prune(X,DX,Y,DY,R,NDX)
% variable X had domain DX
% variable Y has domain DY
% R is a relation on X and Y
% NDX = {X in DX | exists Y such that R(X,Y) is true}
prune(_,[],_,_,_,[]).
prune(X,[V|XD],Y,YD,R,XD1):-
   \+ (X=V,member(Y,YD),R),!,
   prune(X,XD,Y,YD,R,XD1).
prune(X,[V|XD],Y,YD,R,[V|XD1]):-
   prune(X,XD,Y,YD,R,XD1).

% acc_todo(X,Y,CA,CA1,TDA,TDA1)
% given variables X and Y,
% updates consistent arcs from CA to CA1 and
% to do arcs from TDA to TDA1
acc_todo(_,_,[],[],TDA,TDA).
acc_todo(X,Y,[rel([U,V],R)|CA0],
         [rel([U,V],R)|CA1],TDA0,TDA1) :-
   ( X \== V
   ; X == V,
     Y == U),
   acc_todo(X,Y,CA0,CA1,TDA0,TDA1).
acc_todo(X,Y,[rel([U,V],R)|CA0],
         CA1,TDA0,[rel([U,V],R)|TDA1]) :-
   X == V,
   Y \== U,
   acc_todo(X,Y,CA0,CA1,TDA0,TDA1).

% solutions(Doms,Arcs) given a reduced set of
% domains, Dome, and arcs Arcs, solves the CSP.
solutions(Doms,_) :-
   solve_singletons(Doms).
solutions(Doms,A) :-
   select(dom(X,[XV1,XV2|XVs]),Doms,ODoms),
   split([XV1,XV2|XVs],DX1,DX2),
   acc_todo(X,_,A,CA,[],TDA),
   ( consistent([dom(X,DX1)|ODoms],CA,TDA,A)
   ; consistent([dom(X,DX2)|ODoms],CA,TDA,A)).

% solve_singletons(Doms) is true if Doms is a
% set of singletom domains, with the variables
% assigned to the unique values in the domain
solve_singletons([]).
solve_singletons([dom(X,[X])|Doms]) :-
   solve_singletons(Doms).

:- redefine_system_predicate(select(_,_,_)).

% select(E,L,L1) selects the first element of
% L that matches E, with L1 being the remaining
% elements.
select(D,Doms,ODoms) :-
%   remove(D,Doms,ODoms), !.
   system:select(D,Doms,ODoms), !.

% choose(E,L,L1) chooses an element of
% L that matches E, with L1 being the remaining
% elements.
choose(D,Doms,ODoms) :-
%   remove(D,Doms,ODoms).
    system:select(D,Doms,ODoms).

% split(L,L1,L2) splits list L into two lists L1 and L2
% with the about same number of elements in each list.
split([],[],[]).
split([A],[A],[]).
split([A,B|R],[A|R1],[B|R2]) :-
   split(R,R1,R2).

next / 2への最後の修正後、テストは良好のようです。

?- zebra.
people:[3,4,2,1,5]
color:[3,5,4,1,2]
pet:[4,3,1,2,5]
drink:[5,2,3,4,1]
smoke:[3,1,2,4,5]
true ;
false.
于 2012-11-25T06:38:21.707 に答える