2014-11-16 2 views
3

먼저 전체 프로그램을 게시하는 것에 대해 유감 스럽지만 문제가 무엇인지 모르기 때문에 어떤 부분이 부적절한 것인지 알지 못합니다. SWI-Prolog에서 동일한 논리 퍼즐에 대한 두 가지 구현이 약간 다르지만 첫 번째 오류가 성공하면 두 번째 오류가 발생하고 오류의 원인을 찾을 수 없습니다.제약 조건 논리 프로그램에서 이상한 경고 및 계산 결과

퍼즐 :

4 persons are having a diner: 
Donna, Doreen, David, Danny 

the woman (Donna,Doreen) are sitting vis-a-vis. 
the men (David,Danny) are sitting vis-a-vis. 

Each of them picked a unique meal and beverage. 

1) Doreen sits next to the person that ordered risotto. 
2) the salad came with a coke. 
3) the person with the lasagna sits vis-a-vis the person with the milk. 
4) david never drinks coffee. 
5) donna only drinks water. 
6) danny had no appetite for risotto. 

who ordered the pizza? 

나는 다음과 같은 접근 방식을

table with positions: 

    1 
4 O 2 
    3 

domain: positions{1,2,3,4} 
variables: persons, meals, beverages 

먼저 비효율적 성공 구현을 선택합니다

이 작동하고 올바른 결과를 제공
solution(Pizza, Doreen, Donna, David, Danny) :- 

    % assignment of unique positions to the variables 
    unique(Doreen,Donna,David,Danny), 
    unique(Lasagna,Pizza,Risotto,Salad), 
    unique(Water,Coke,Coffee,Milk), 

    % general setting 
    vis_a_vis(Donna,Doreen), 
    vis_a_vis(David,Danny), 

    % the six constraints 
    next_to(Doreen,Risotto), 
    Salad = Coke, 
    vis_a_vis(Lasagna,Milk), 
    \+ David = Coffee, 
    Donna = Water, 
    \+ Danny = Risotto. 



unique(X1,X2,X3,X4) :- 
    pos(X1), 
    pos(X2), 
    \+ X1 = X2, 
    pos(X3), 
    \+ X1 = X3, \+ X2 = X3, 
    pos(X4), 
    \+ X1 = X4, \+ X2 = X4, \+ X3 = X4. 

right(1,2). 
right(2,3). 
right(3,4). 
right(4,1). 

vis_a_vis(1,3). 
vis_a_vis(3,1). 
vis_a_vis(2,4). 
vis_a_vis(4,2). 

next_to(X,Y) :- right(X,Y). 
next_to(X,Y) :- right(Y,X). 

pos(1). 
pos(2). 
pos(3). 
pos(4). 

.

Warning: /home/pizza.pl:28: 
Singleton variable in \+: Coffee 

: 좀 더 효율적으로 해결 절차의 절을 순서를 변경하려고 할 때

solution(Pizza, Doreen, Donna, David, Danny) :- 

    % general setting 
    vis_a_vis(Donna,Doreen), 
    vis_a_vis(David,Danny), 

    % the six constraints 
    Salad = Coke, 
    vis_a_vis(Lasagna,Milk), 
    \+ David = Coffee, 
    Donna = Water, 
    \+ Danny = Risotto, 

    % assignment of unique positions to the variables 
    unique(Doreen,Donna,David,Danny), 
    unique(Lasagna,Pizza,Risotto,Salad), 
    unique(Water,Coke,Coffee,Milk). 

    %% all other predicates are like the ones in the first implementation 

내가 파일을로드하려고 할당되지 않은 변수 경고가 (이 두 번째 구현입니다) 계산은 false을 반환합니다. 그러나 동일한 결과를 반환해서는 안됩니까? 차이점이없는 이유는 없습니다 ...

+1

참조 [태그 : 얼룩말 퍼즐]에 대한 유사한 문제. – false

답변

1

경고는 부정이 실행될 때 Coffe와 Risotto가 언 바운드된다는 사실 때문입니다. \+ David = Coffee,David \= Coffee,으로 바꾸면 경고 메시지는 표시되지 않지만 솔루션을 계산할 수는 없습니다. 커피가 묶여 있기 때문에 David \ = Coffee는 항상 실패 할 것임이 분명해야합니다. dif/2를 사용할 수 있습니다.이 솔루션이 효과적 일 것이며 더 효율적입니다. 나는 solution1/2 첫 번째 조각의 이름 및 solution2/5이 하나 한 (사용 DIF/2) :

solution2(Pizza, Doreen, Donna, David, Danny) :- 

    % general setting 
    vis_a_vis(Donna,Doreen), 
    vis_a_vis(David,Danny), 

    % the six constraints 
    next_to(Doreen,Risotto), % note: you forgot this one 
    Salad = Coke, 
    vis_a_vis(Lasagna,Milk), 
    dif(David, Coffee), 
    Donna = Water, 
    dif(Danny, Risotto), 

    % assignment of unique positions to the variables 
    unique(Doreen,Donna,David,Danny), 
    unique(Lasagna,Pizza,Risotto,Salad), 
    unique(Water,Coke,Coffee,Milk). 

작은 시험 :

?- time(aggregate_all(count,solution1(P,A,B,C,D),N)). 
% 380,475 inferences, 0.058 CPU in 0.058 seconds (100% CPU, 6564298 Lips) 
N = 8. 

?- time(aggregate_all(count,solution2(P,A,B,C,D),N)). 
% 10,626 inferences, 0.002 CPU in 0.002 seconds (100% CPU, 4738996 Lips) 
N = 8. 
+0

대단히 감사합니다! – jules

+0

감사합니다. @CapelliC. 함수의 성능을 평가할 시간과 aggregate_all 조건을 발견했습니다 ... – Lahniep

+0

@Lahniep : 코드를 미세 조정해야 할 경우를 대비해 SWI-Prolog에 작동 프로파일 러가 있습니다. – CapelliC