我有一个充满事实的数据库,例如:
checkpoint(checkpoint1,checkpoint2,2).
checkpoint(checkpoint2,checkpoint3,3).
checkpoint(checkpoint3,checkpoint4,4).
checkpoint(checkpoint4,checkpoint5,2).
checkpoint(checkpoint5,checkpoint6,2).
例如checkpoint(firstcheckpoint,secondcheckpoint,timeinminutes)。
然后,以下规则测试是否可以在比赛中的两个检查点之间进行旅程:
journey(X,Y):- checkpoint(X,_,_), checkpoint(_,Y,_),!; checkpoint(Y,_,_), checkpoint(_,X,_),!.
journey(X,Y):- checkpoint(X,Z,_), journey(Z,Y).
journey(X,Y):- checkpoint(Z2,Y,_), journey(X,Z2).
请注意,你不能跳过检查站,你只能先到1,2然后3到达checkpoint4。然而你可以倒退,例如从检查站4回到3。
我知道如果在X和Y之间有一个中间检查点,这个代码检查两个检查点之间是否可以进行旅行,在这种情况下是Z.但是我不太明白Z2在做什么。我认为它只是被用作Z之类的另一个中间体,但为什么它被命名为另一个变量呢?不能将Z2改为Z,它仍然可以工作吗?
答案 0 :(得分:1)
Z2
绝对可以在最后一条规则中重命名为Z
,并且规则的逻辑不会改变。作者犹豫使用Z
的原因可能是因为该变量并不表示Z
在第一条规则中所做的“中点”。
就个人而言,我会使用更具描述性的变量名称 - From
和To
听起来像是好人选:
journey(From,To):- checkpoint(From,Mid,_), journey(Mid,To).
journey(From,To):- checkpoint(Someplace,To,_), journey(From,Someplace).
答案 1 :(得分:1)
如果您以相同的方式重命名 all ,则可以重命名变量而不更改规则的含义。
但是第一次旅程规则对我来说是错误的:你期望削减有什么影响? 分离没有机会,导致第一次削减。
只留下第一条规则,然后尝试?- findall((X,Y),journey(X,Y),L).
您将看到唯一的答案L = [ (checkpoint1, checkpoint2)].
所以,来自@dasblinklight(+1)的答案建议更深层次修正变量重命名:只需删除第一个旅程规则......
修改强>
此程序(没有剪切)扩展了原始规范,允许枚举所有可能的旅程,并且可以匹配原始定义:
journey(X, Y):-
journey([], X, Y).
journey(Visited, X, Y) :-
( checkpoint(X, I, _) ; checkpoint(I, X, _) ),
\+ memberchk(I, Visited),
( I = Y ; journey([X|Visited], I, Y) ).