我想用Prolog作为练习来解决“Fox, goose and bag of beans puzzle”。
所以我写了
p(left).
p(right).
valid((Man, Goose, Fox, Beans)) :- p(Man),p(Goose),p(Fox),p(Beans), Man == Goose.
valid((Man, Goose, Fox, Beans)) :- p(Man),p(Goose),p(Fox),p(Beans), Man == Beans, Goose \= Fox.
valid((Man, Goose, Fox, Beans)) :- p(Man),p(Goose),p(Fox),p(Beans), Man == Fox, Goose \= Beans.
step((Man1, Goose, Fox, Beans), "Man", (Man2, Goose, Fox, Beans)) :-
valid((Man1, Goose, Fox, Beans)), valid((Man2, Goose, Fox, Beans)),
Man1 \= Man2.
step((Man1, Goose1, Fox, Beans), "Goose", (Man2, Goose2, Fox, Beans)) :-
valid((Man1, Goose1, Fox, Beans)), valid((Man2, Goose2, Fox, Beans)),
Man1 \= Man2, Goose1 \= Goose2.
step((Man1, Goose, Fox1, Beans), "Fox", (Man2, Goose, Fox2, Beans)) :-
valid((Man1, Goose, Fox1, Beans)), valid((Man2, Goose, Fox2, Beans)),
Man1 \= Man2, Fox1 \= Fox2.
step((Man1, Goose, Fox, Beans1), "Beans", (Man2, Goose, Fox, Beans1)) :-
valid((Man1, Goose, Fox, Beans1)), valid((Man2, Goose, Fox, Beans2)),
Man1 \= Man2, Beans1 \= Beans2.
reachable(S, _,[], S).
reachable(S, Visited, [Step|Steps], Z) :-
step(S,Step,Tmp),valid(Tmp), not(member(Tmp,Visited)),
reachable(Tmp, [Tmp|Visited], Steps, Z).
start((left,left,left,left)).
goal((right,right,right,right)).
solve(Steps) :- start(S), goal(Z), reachable(S, [], Steps, Z).
我想到solve(X).
我会得到一系列有效的步骤。但相反,我得到
?- solve(X).
false.
为什么我没有得到从开始到目标的步骤列表?
valid
检查一个4元组,其中第一个元素是“Man”的位置,第二个元素是“Goose”的位置,第三个元素是“Beans”的位置,如果没有人被吃掉
step(Situation1, Description, Situation2)
从有效的情境向另一个有效的情况迈出了一步。
reachable(Start, SituationList, Steps, Goal)
检查Goal
情况Goal
是否可以通过SituationList
访问情况Steps
只访问{{1}},{{1}}是描述采取了哪些步骤。
答案 0 :(得分:2)
导致失败的主要问题是拼写错误:
step((Man1, Goose, Fox, Beans1), "Beans", (Man2, Goose, Fox, Beans1)) :-
应该是:
step((Man1, Goose, Fox, Beans1), 'Beans', (Man2, Goose, Fox, Beans2)) :-
这将生成正确的解决方案。还有一些其他清理点:
'Man'
代替"Man"
。valid(Tmp)
条款中reachable/2
的目标是多余的,因为step
的先前目标确保Tmp
根据valid
规则有效valid
子句中的两个step/3
目标中的第一个是不必要的,因为您的第一个参数来自先前验证的步骤。 (这取决于"一般"您希望step/3
表现如何)。除此之外,solve/1
仍会产生许多重复的结果,但它们都是正确的,并且发现了所有正确的解决方案。