我在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)))) ?
我确信我做的事情显然很愚蠢,但我很难看到它是什么。
答案 0 :(得分:3)
你的子句与(,)仿函数匹配两次:fuzzy_prove的第3和第4个子句,当它与第4个子句匹配时,它最终将无限循环,因为子句本身是一个并且不能简化。
此查询将演示正在发生的事情:
clause(grandfather(A,B), C0), clause(C0, C1), clause(C1, C2).
在我的翻译中,至少C1 = C2,我们有一个无限循环。
在递归之前,您至少需要检查子句体的仿函数是否(,)。我怀疑会有其他像这样的角落情况,所以事实上最好找出如何正确处理调用仿函数。
答案 1 :(得分: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
不存在。