2014-12-01 2 views
3

이 추적 메타 인터프리터가 있습니다. 그것은 swi-prolog 용으로 작성되었습니다.프롤로그 바인딩 해제 변수

trace(Goal):- 
     trace(Goal, 0). 

trace(true, _Depth):-!, true. 
trace(fail, _Depth):-!, fail. 
trace(A > B, _Depth):-!, A > B. 
trace(A < B, _Depth):-!, A < B. 
trace(A <= B, _Depth):-!, A <= B. 
trace(A >= B, _Depth):-!, A >= B. 
trace(A = B, _Depth):-!, A = B. 
trace(A is B, _Depth):-!, A is B. 
trace(!, _Depth):-!, fail. 
trace(not(A), _Depth):-!, not(A). 
trace((Goal1, Goal2), Depth):-!, 
     trace(Goal1, Depth), 
     trace(Goal2, Depth). 
trace(Goal, Depth):- 
     display('Call: ', Goal, Depth), 
     clause(Goal, Body), 
     Depth1 is Depth + 1, 
     trace(Body, Depth1), 
     display('Exit: ', Goal, Depth), 
     display_redo(Goal, Depth). 
trace(Goal, Depth):- 
     display('Fail: ', Goal, Depth), 
     fail. 

display(Message, Goal, Depth):- 
     tab(Depth), write(Depth), write(': '), write(Message), 
     write(Goal), nl. 

display_redo(Goal, Depth):- 
     true 
     ; 
     display('Redo: ', Goal, Depth), 
     fail. 

just_do_it(In, Out, Query):- 
     consult(In), 
     tell(Out), 
     call_with_depth_limit(findall(Query, trace(Query), _Solutions), 30, _XMessage), 
     writeln(_XMessage), 
     writeln(_Solutions), 
     told, 
     unload_file(In), 
     true. 

그것은 한 가지를 제외하고 잘 작동하고 있습니다. 함수 just_do_it(In, Out, Query)에있는 Query에 변수가 있으면 출력은 바인드 된 변수와 같습니다. 추적 할 때 추가 단계에서 변수를 바인딩 해제 할 수있는 방법이 있습니까? 바인딩 될 때와 그렇지 않을 때를 볼 수 있습니까?

예 출력 :

0: Call: a(_G1085,_G1085,_G1087) 
0: Exit: a(3,3,7) 
0: Redo: a(3,3,7) 
    1: Call: b(_G1087,_G1085) 
    1: Exit: b(7,3) 
    1: Redo: b(7,3) 
    1: Exit: b(5,1) 
    1: Redo: b(5,1) 
    1: Fail: b(_G1087,_G1085) 
0: Fail: a(_G1085,_G1085,_G1087) 

예 출력은 내가 얻고 자 :

0: Call: a(_G1085,_G1085,_G1087) 
0: Exit: a(3,3,7) 
0: Redo: a(_G1085,_G1085,_G1087) 
1: Call: b(_G1087,_G1085) 
1: Exit: b(7,3) 
1: Redo: b(_G1087,_G1085) 
1: Exit: b(5,1) 
1: Redo: b(_G1087,_G1085) 
1: Fail: b(_G1087,_G1085) 
0: Fail: a(_G1085,_G1085,_G1087) 
+0

속편 : http://stackoverflow.com/questions/27235148/implementing-cut-in-tracing-meta-interpreter-prolog/ – false

답변

4

귀하의 통역에 몇 가지 문제가 있습니다 : 당신은 어떤 존재하지 않는 연산자 <=를 사용하는

은 . 따라서 구문 오류가 발생해야합니다. Prolog에서 less-then-equal은 =<이며 화살표가 혼동되지 않도록 ⇐/<=입니다.

술어 trace/1을 정의하고 있지만이 프리디 케이트가 이미 사전 정의 된 다른 많은 프롤로그만큼 SWI가 정의되어 있습니다. 그래서 다른 이름을 더 잘 사용하십시오.

절단이 올바르게 구현되지 않았습니다.

not/1에 대한 규칙은 오히려 (\+)/1을 정의해야하고, 읽을 수 :

trace(\+A, Depth):-!, \+trace(A, Depth). 

증명 변수가 instantiation_error 발생한다. call(_)에서와 같이 그래서 당신은

trace(V, _) :- var(V), !, throw(error(instantiation_error, _)). 

좀 더 명시 적 방법으로 목표 clause(Goal, Body),를 교체해야 제대로 다시 표시하려면 첫 번째 규칙으로 필요합니다. 결국, 역 추적 (backtracking)을 제외하고 변수를 바인딩 해제 할 방법이 없습니다. 즉, 변수가 아직 인스턴스화되지 않은 적절한 순간을 찾아야합니다. clause/2redo_clause/3으로 바꿉니다.

redo_clause(Depth, Goal, Body) :- 
    findall(Goal-Body, clause(Goal, Body), [First|Rest]), 
    (Goal-Body = First 
    ; length(Rest, RL), length(RestC, RL), 
    member(Goal-Body,RestC), 
    display('Redo: ', Goal, Depth), 
    Rest = RestC 
    ). 
+0

나는 당신의 충고를 따랐다 나는 이름과 연산자 인터프리터를 변경. 그러나 이것은 내 문제를 해결하지 못합니다. 내 질문을 편집하고 예제 출력과 출력을 추가했습니다. –

+0

답변으로 표시 했으므로 프롤로그 멍청하다고 말할 수 있기 때문에 정말 도움이되었습니다. 컷이 올바르게 구현되지 않았다는 것을 언급했는데, 그게 잘못 됐는지 말해 줄 수 있습니까? –

+0

이제 Depth 0 만 사용하여 통화 및 재실행 코드가 표시되지 않습니다. 나는 슬쩍 흔드는 데 노력했고, 해결할 수없는 몇 가지 실패가 있습니다. 이것은 redo_clause/3이있을 때 발생합니다. 왜 이런 일이 일어나는 지 아십니까? –