2012-12-29 4 views
0
에 무한 루프를 피

I 기술 자료에서 다음과 같은 사실이 있습니다프롤로그

lineEqual(line(C, D), line(A, B)):- 
    lineEqual(line(A,B),line(C,D)). 

:

line(a,b). -- denotes the line determined by point a and b 
line(c,d). -- denotes the line determined by point c and d 
lineEqual(line(a,b),line(c,d)) -- denotes the length of two lines are equal 

내가 lineEqual의 두 인수 주위에 교환 할 수있는 또 다른 규칙/2를 갖고 싶어 불행히도이 규칙은 Prolog에서 무한 루프를 생성합니다. 다른 생각?

감사합니다.

transitiveSymmetricRelPath(L1, L2, IntermediateNodes) :- symmetricRel(L1, L3), 
       \+member(L3, IntermediateNodes), 
       transitiveSymmetricRelPath(L1, L2, [L3 | IntermediateNodes]). 

내가 바로 L1과 L3 모두 연결되어 일어나는 경우 헤드 노드를 제거하려고 할 때마다 상상할 수 : 당신의 마지막 규칙을 이해 확실하지면? 우리는 빈리스트로 끝날 그렇다면 우리는이 규칙 사용할 수 있습니다

transitiveSymmetricRel(L1, L2) :- transitiveSymmetricRelPath(L1, L2, []). 

을하지만 시작하는 transitiveSymmetricRelPath/3의 중간 노드의 비어 있지 않은 목록을 얻는 곳 난 정말 점점 아니에요 비트입니다. 사실 주어진 rel (a, b)로 코드를 시도했습니다. rel (a, c). transitiveSymmetricRel (b, c)를 반환하지 않으며 transitiveSymmetricRel (c, b)도 반환하지 않습니다. 좀 들여다 볼 수 있겠습니까?

고맙습니다.

편집 : 나는이 같은 규칙을 수정하여 작업 있어요 : 귀하의 제안에 대한

transitiveSymmetricRelPath(L2, L3, IntermediateNodes) :- symmetricRel(L1, L3), 
    \+member(L3, IntermediateNodes), 
    transitiveSymmetricRelPath(L1, L2, [L3 | IntermediateNodes]). 

감사 어쨌든.

답변

1

첫 번째 예제에서 linelineEqual과 같은 코드와 두 번째 예제에서 lineEqual과 같은 코드를 단일 이름으로 사용하지 마십시오. 대신, 데이터베이스 사실을 다른 이름으로 유지하십시오. 그런 다음 정의 : 일반적으로

areLinesEqual(L1, L2) :- linesEqual(L1, L2). 
areLinesEqual(L1, L2) :- linesEqual(L2, L1). 

, 당신은 관계 rel이 있고 대칭 전이 폐쇄를 구축하려는 경우, 당신은 한 번에 하나 개의 개념을 소개한다. 예를 들면 :

symmetricRel(L1, L2) :- rel(L1, L2). 
symmetricRel(L1, L2) :- rel(L2, L1). 

transitiveSymmetricRel(L1, L2) :- 
    transitiveSymmetricRelPath(L1, L2, []). 

transitiveSymmetricRelPath(L1, L2, _) :- 
    symmetricRel(L1, L2). 

transitiveSymmetricRelPath(L1, L2, IntermediateNodes) :- 
    symmetricRel(L1, L3), 
    \+ member(L3, IntermediateNodes), 
    transitiveSymmetricRelPath(L1, L2, [L3 | IntermediateNodes]). 

(우리는 기본적으로 무향 그래프의 경로를 찾을 수 있어야하고, 관리가 루프를 피하기 위해주의해야 점에 유의). 귀하의 경우에는 line(A, B)line(B, A)도 같은 것으로 간주하는 것이 좋습니다. 이를 위해, 다시, 당신은 간접 다른 수준 소개합니다 :

% to check two lines for identity 
same(line(A, B), line(A, B)). 
same(line(A, B), line(B, A)). 

linesEqual2(L1, L2) :- 
    same(L1, LI1), 
    same(L2, LI2), 
    (linesEqual(LI1, LI2); linesEqual(LI2, LI1)). 

을 ... 그리고 대칭 관계의 정의에 linesEqual2 대신 linesEqual를 사용합니다.

당신이 모든 조건을 혼동하지 않도록 어려운 부분은 지금 명명 체계로오고있다 ...

당신은 다른 방법으로 할 수도 있습니다. 대칭 관계의 전이 폐쇄 (transitive closure)를 찾으면 기본적으로 모든 노드 집합 (여기에서는 : 선)을 분리 가능한 하위 집합으로 분할합니다. 이 통찰력은 위와 같은 훨씬 효율적인 코드를 작성하는 데 도움이 될 것입니다 ... 그러나 이것은 이미이 질문의 범위를 벗어났습니다.

+0

답장을 보내 주셔서 감사합니다. 전이 관계는 어떻습니까?areLinesEqual (L1, L3) : - linesEqual (L2, L1), linesEqual (L2, L3). 제안에 따라 8 개의 규칙을 작성해야합니다. areLinesEqual (L1, L3) : - linesEqual (L1, L2), linesEqual (L2, L3)입니다. areLinesEqual (L1, L3) : - linesEqual (L2, L1), linesEqual (L3, L2)입니다. areLinesEqual (L1, L3) : - linesEqual (L1, L2), linesEqual (L3, L2)입니다. L1과 L3을 바꿔 치기위한 또 다른 네 가지 규칙은 무엇입니까? 갈 수있는 좋은 방법이 아닐 수도 있습니다. – user1935724

+0

@ user1935724 : 답변을 업데이트했습니다. – liori

+0

업데이트 주셔서 감사합니다. 귀하의 답변에 따라 질문을 편집했습니다. – user1935724