2012-04-28 4 views
4
likes(tom,jerry). 
likes(mary,john). 
likes(mary,mary). 
likes(tom,mouse). 
likes(jerry,jerry). 
likes(jerry,cheese). 
likes(mary,fruit). 
likes(john,book). 
likes(mary,book). 
likes(tom,john). 

likes(john,X):-likes(X,john), X\=john. 

안녕하세요, 위의 아주 간단한 프롤로그 파일입니다. 몇 가지 사실과 단 하나의 규칙이 있습니다. 존은 그를 좋아하는 사람을 좋아합니다. 그러나이 파일을로드하고 프롤로그에게 다음 쿼리 요청 후 :이 간단한 예제에서 Prolog가 충돌하는 이유는 무엇입니까?

likes(john,X). 

프로그램 충돌. 그 이유는 어쨌든 프롤로그가 인데도 불구하고 likes(john,john)에 머물러 있기 때문입니다.

어떤 조언이 필요합니까?

+0

호기심에서 X \ = john이 좋아요 앞에 오면 어떻게됩니까? – pedrofurla

+0

이상하게도, 몸의 앞에 놓으면 프롤로그가 돌아올 것입니다 : 'X = book; 거짓 .' '책'바로 뒤에 멈추는 이유를 모르겠습니다. –

답변

3

역설적이게도, 우리가있는 사이트에서 스택 오버플로가 발생합니다.

이 때문에 프롤로그 사용, 규칙에 likes(X,john)에서 무한 재귀에 갈거야 것을 실행 순서의이 작업을 수행, 그것은 다시 규칙을 활성화 -없는 사실 - 결코 X\=john 비트에 도착합니다. 이 문제를 해결하는

한 가지 방법은 규칙이처럼 사실에서 다른 이름 한 것입니다 :

kindoflikes(tom,jerry). 
kindoflikes(mary,john). 
kindoflikes(mary,mary). 
kindoflikes(tom,mouse). 
kindoflikes(jerry,jerry). 
kindoflikes(jerry,cheese). 
kindoflikes(mary,fruit). 
kindoflikes(john,book). 
kindoflikes(mary,book). 
kindoflikes(tom,john). 

likes(Y,X):- kindoflikes(X,Y), X\=Y. 
likex(Y,X):- kindoflikes(Y,X), X\=Y. 

주 두 규칙 정의에 kindoflikes에서 X와 Y의 반전. 그래서 당신이 얻을 :

?- likes(john,X). 
X = mary ; 
X = tom ; 
X = book. 

하지만 당신은 존이 좋아하는 것을 발견에 고정하지 않는, 당신은 할 수 있습니다 :

?- likes(jerry,X). 
X = tom ; 
X = cheese. 
+0

완벽한 답변입니다. 감사합니다! –

+0

@GregHNZ : 프롤로그는 사실 전에 규칙을 실행하지 않습니다. – m09

2

첫 번째 질문은 왜 프로그램이 충돌했다. 어떤 종류의 프롤로그 시스템을 사용하고 있는지 잘 모르겠지만 많은 시스템은 프롤로그 내에서 처리 할 수있는 깨끗한 "자원 오류"를 생성합니다.

실제 문제는 프로그램이 쿼리 likes(john, X)에 대해 종료되지 않는다는 것입니다. 그것은 당신에게 예상되는 답변을주고 그때 만 반복합니다.

 
?- likes(john,X). 
X = book ; 
X = mary ; 
X = tom ; 
ERROR: Out of local stack 

당신은 그 문제를 너무 빨리 발견 한 것을 매우 행운아하게 생각합니다. 더 많은 해답을 상상해보십시오. 그리고 모든 해답을 거치려면 인내심을 가지고 있다는 것이 분명하지 않았을 것입니다. 그러나 바로 가기가 있습니다. 대신 묻기 :

 
?- likes(john, X), false. 

false 목표는 사실이 아닙니다. 그래서 그것은 쉽게 모든 대답을 방지합니다. 기껏해야 false이 끝나는 쿼리가 종료됩니다. 현재로서는 그렇지 않습니다. 다음 (자세한 내용은 찾아 다른 답변)을 고려할 때이 아닌 종료에 대한 이유는 최고의 볼 수 있습니다 :

 
?- likes(john,X), false. 

likes(tom,jerry) :- false. 
likes(mary,john) :- false. 
likes(mary,mary) :- false. 
likes(tom,mouse) :- false. 
likes(jerry,jerry) :- false. 
likes(jerry,cheese) :- false. 
likes(mary,fruit) :- false. 
likes(john,book) :- false. 
likes(mary,book) :- false. 
likes(tom,john) :- false. 
likes(john,X) :- 
    likes(X,john), false, 
    X\=john. 

는 그래서 스택 오버 플로우에 대한 책임이 프로그램의 아주 작은 부분이다. 문제를 해결하려면 무언가을 사용해야합니다. 여기에 하나입니다 규칙이 지금 읽고되도록 목표 dif(X, john)을 추가 경우, SICStus, SWI, YAP, B :

 
likes(john,X) :- 
    dif(X, john), 
    likes(X,john). 

dif/2이 같은 많은 프롤로그 시스템에서 사용할 수 있습니다.

관련 문제