2015-12-11 2 views
4

Я пишу тривиальный metainterpreter в Прологе для самообразования. В принципе, я хочу нести «вероятность» данного решения. Для этого я просто заявляю, что вероятность того, что моя статья будет правильной. Я ожидаю, что, если это работает я продлить его с более прочной основой, но сейчас я просто заинтересован в решении насущной проблемы, которая является то, что мой metainterpreter петли:Looping in Prolog metainterpreter

Код:

fuzzy_prove(true, 1.0) :- !. 
fuzzy_prove(probability(P), P) :- !. 
fuzzy_prove((A,B), Prob) :- 
    fuzzy_prove(A, P1), 
    fuzzy_prove(B, P2), 
    Prob is P1 * P2. 
fuzzy_prove(A, P) :- 
    clause(A, B), fuzzy_prove(B, P). 

father(dave, jean). 
father(dave, don) :- probability(0.5). 
father(don, claudia). 
father(don, jimmy) :- probability(0.5). 
father(jean, davey). 

grandfather(Grandpop, Babs) :- 
    father(Grandpop, Dad), 
    father(Dad, Babs). 

Моих запросов кажется сперва к работе:

?- fuzzy_prove(grandfather(X, Z), Prob). 
X = dave, 
Z = davey, 
Prob = 1.0 ; 
X = dave, 
Z = claudia, 
Prob = 0.5 ; 
X = dave, 
Z = jimmy, 
Prob = 0.25 ; 

Когда я прошу о следующем решении, я получаю сумасшедший цикл. Если я прерываю его, это выглядит следующим образом:

continue (trace mode) 
    Call: (3,973,299) fuzzy_prove(call((father(_G3, _G28), father(_G28, _G4))), _G5) ? 
^ Call: (3,973,300) clause(call((father(_G3, _G28), father(_G28, _G4))), _G2044) ? 
^ Exit: (3,973,300) clause(call((father(_G3, _G28), father(_G28, _G4))), call((father(_G3, _G28), father(_G28, _G4)))) ? 
    Call: (3,973,300) fuzzy_prove(call((father(_G3, _G28), father(_G28, _G4))), _G5) ? 
^ Call: (3,973,301) clause(call((father(_G3, _G28), father(_G28, _G4))), _G2051) ? 
^ Exit: (3,973,301) clause(call((father(_G3, _G28), father(_G28, _G4))), call((father(_G3, _G28), father(_G28, _G4)))) ? 
    Call: (3,973,301) fuzzy_prove(call((father(_G3, _G28), father(_G28, _G4))), _G5) ? 
^ Call: (3,973,302) clause(call((father(_G3, _G28), father(_G28, _G4))), _G2058) ? 
^ Exit: (3,973,302) clause(call((father(_G3, _G28), father(_G28, _G4))), call((father(_G3, _G28), father(_G28, _G4)))) ? 
    Call: (3,973,302) fuzzy_prove(call((father(_G3, _G28), father(_G28, _G4))), _G5) ? 
^ Call: (3,973,303) clause(call((father(_G3, _G28), father(_G28, _G4))), _G2065) ? 
^ Exit: (3,973,303) clause(call((father(_G3, _G28), father(_G28, _G4))), call((father(_G3, _G28), father(_G28, _G4)))) ? 
    Call: (3,973,303) fuzzy_prove(call((father(_G3, _G28), father(_G28, _G4))), _G5) ? 
^ Call: (3,973,304) clause(call((father(_G3, _G28), father(_G28, _G4))), _G2072) ? 
^ Exit: (3,973,304) clause(call((father(_G3, _G28), father(_G28, _G4))), call((father(_G3, _G28), father(_G28, _G4)))) ? 

Я уверен, что я делаю что-то, очевидно, глупо, но у меня возникают проблемы, видя, что это такое.

ответ

3

Ваш пункт с (,) функторами соответствует дважды: как 3-й, так и 4-й клаузулы fuzzy_prove, когда он соответствует 4-му предложению, он, в конце концов, будет контур бесконечно, потому что тело предложения само по себе является и не может быть упрощено.

Этот запрос покажет, что происходит:

clause(grandfather(A,B), C0), clause(C0, C1), clause(C1, C2). 

На мой интерпретатором, по крайней мере C1 = C2, и мы имеем бесконечный цикл.

Необходимо, по крайней мере, проверить, что функтор тела вашего предложения не (,) перед рекурсией. Я подозреваю, что будут другие угловые случаи, подобные этому, поэтому на самом деле может быть лучше разобраться, как правильно обращаться с функтором вызова.

+0

Спасибо! Можете ли вы немного рассказать о том, что было предложено при правильном обращении с функтором вызова? Я основывал свой код на [этой странице] (http://kti.ms.mff.cuni.cz/~bartak/prolog/meta_interpret.html). –

+0

@ DanielLyons Я точно не знаю, просто «call» - это функтор, который сразу же петли, поэтому, возможно, есть что-то, что можно сделать там ... – tobyodavies

2

Проблема, с которой вы столкнулись, относится к SWI. Только SWI получает гол clause((A,B),R). Требования ISO для выпуска permission_error(access,private_procedure,Culprit) и B, IF, IV, GNU, SICStus, XSB и YAP производят эту ошибку. Обратите внимание на фактическую причину: private_procedure, для встроенных и управляющих конструкций - все частные, т. Е. Они не могут быть доступны через clause/2.

Есть много других проблем с вашим кодом.

Цель fuzzy_prove(true,0.0) создает эту ошибку вместо того, чтобы терпеть неудачу. Кратко, ваш код не обладает стойкостью.

Другая проблема - fuzzy_prove(G, P), которая скорее всего должна скорее дать соответствующую ошибку при создании экземпляра вместо G = true.

fuzzy_prove(probability(1.0),0.0) зависит от наличия соответствующего предиката, возможно, это не предназначено. И если нет, SWI предупредит вас о несуществовании probability/1.

+0

Я ценю информацию. Было бы еще более полезно, если бы вы могли показать мне надежный подход. –

+0

Это не будет ответом на ваш вопрос. – false

+0

Если я задам еще один вопрос, чтобы увидеть ваш подход, вы побалуете меня?:) –