2015-02-01 3 views
1

나는이 프롤로그 코드를 가지고 있습니다 : [[vincent,vincent],[vincent,marcellus],[marcellus,vincent],[marcellus,marcellus],[pumpkin,pumpkin],[honey_bunny,honey_bunny]].프롤로그로 고유 한 결과 얻기

:- initialization main. 

loves(vincent, mia). 
loves(marcellus, mia). 
loves(pumpkin, honey_bunny). 
loves(honey_bunny, pumpkin). 

jealous(X, Y) :- 
    loves(X, Z), 
    loves(Y, Z). 

main :- 
    findall([X, Y], jealous(X, Y), L), 
    write(L), 
    halt. 

X! = Y 일 때 유일한 결과를 얻는 방법? 이전과 같은 결과를 얻으려고 다음 코드를 시도했습니다. \=

jealous(X, Y) :- 
    X \== Y, 
    loves(X, Z), 
    loves(Y, Z). 

, 나는 []을 얻었다. 그 결과로 얻는 방법 [vincent,marcellus] 그 결과로?

답변

1

시도한 솔루션의 목표 순서가 잘못되었습니다. 두 개의 별개의 변수로 호출하면 (\==)/2 표준 술어가 항상 성공합니다. 인수가 인스턴스화 될 때 해결책은 술어 만 호출하는 것입니다 :이 수정

jealous(X, Y) :- 
    loves(X, Z), 
    loves(Y, Z), 
    X \== Y. 

, 쿼리는 이제 반환

?- findall([X, Y], jealous(X, Y), L). 
L = [[vincent, marcellus], [marcellus, vincent]]. 

그래서, 아무도 더 이상 자신의 질투입니다. 하지만 여전히 중복 솔루션이 있습니다. jealous/2 술어를 반환 솔루션의 이름으로 수정할 수 있습니다. 예를 들어 :

jealous(X, Y) :- 
    loves(X0, Z), 
    loves(Y0, Z), 
    X0 \== Y0, 
    ( X0 @< Y0 -> 
     X = X0, Y = Y0 
    ; X = Y0, Y = X0 
    ). 

지금, setof/3를 사용하는 대신 findall/3에 의해, 우리가 얻을 :

?- setof([X, Y], jealous(X, Y), L). 
L = [[marcellus, vincent]]. 

마지막으로 관찰. 목록은 쌍의을 나타내는 데 적합하지 않습니다. 전통적인 방법은 X-Y 또는 (X, Y)을 사용하는 것입니다.

1

가능한 경우 (\==)/2 대신 dif/2을 사용하십시오.

dif/2 논리적으로 안전한 프로그램을 작성하는 데 도움이됩니다.

자세한 내용은 을 참조하십시오!