在此页面http://cseweb.ucsd.edu/classes/fa09/cse130/misc/prolog/goat_etc.html 它演示了如何解决流行的狼,山羊和白菜拼图。
change(e,w).
change(w,e).
move([X, X,Goat,Cabbage], wolf,[Y, Y,Goat,Cabbage]) :- change(X,Y).
move([X,Wolf, X,Cabbage], goat,[Y,Wolf, Y,Cabbage]) :- change(X,Y).
move([X,Wolf,Goat, X],cabbage,[Y,Wolf,Goat, Y]) :- change(X,Y).
move([X,Wolf,Goat,Cabbage],nothing,[Y,Wolf,Goat,Cabbage]) :- change(X,Y).
oneEq(X,X,_).
oneEq(X,_,X).
safe([Man,Wolf,Goat,Cabbage]) :-
oneEq(Man,Goat, Wolf),
oneEq(Man,Goat,Cabbage).
solution([e,e,e,e],[]).
solution(Config,[FirstMove|OtherMoves]) :-
move(Config,FirstMove,NextConfig),
safe(NextConfig),
solution(NextConfig,OtherMoves).
但是为了找到这个程序的实际解决方案,有必要指定所需的确切移动次数,如下所示:
?- length(X,7), solution([w,w,w,w],X).
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ;
false.
是否有标准方法可以找到最小移动解决方案,而无需在上述程序中指定移动次数?
答案 0 :(得分:2)
length / 2具有生成能力,然后只是避免指定值:
?- length(X,_),solution([w,w,w,w],X).
答案 1 :(得分:2)
我们知道有一定数量的解决方案具有相同的最小步数,我们将密切关注实现通用终止。
minlen_solution(Xs,S) :-
( setof(t,solution([w,w,w,w],Xs),_) % eliminate redundant answers
*-> Xs = S
; minlen_solution([_|Xs],S) % no solution? try bigger length
).
minlen_solution/2
使用(*->)/2
,称为" soft cut",以提交最小解决方案长度。
关于便携性的说明:
示例查询:
?- minlen_solution([],Xs).
Xs = [goat,nothing,cabbage,goat, wolf,nothing,goat]
; Xs = [goat,nothing, wolf,goat,cabbage,nothing,goat].
如果我们想找到长度大于或等于8的所有解决方案,我们 可以这样做:
?- length(Xs,8), solution([w,w,w,w],Xs). % try length = 8
false. % no solutions!
?- length(Xs,9), solution([w,w,w,w],Xs). % try length = 9
...
但是,我们仍然必须承诺最小长度。
使用minlen_solutions/2
我们可以直接指定解决方案列表长度的下限,如下所示:
?- length(Xs,8),minlen_solution(Xs,S).
S = [goat, goat, goat,nothing,cabbage, goat, wolf,nothing,goat]
; S = [goat, goat, goat,nothing, wolf, goat,cabbage,nothing,goat]
; S = [goat,nothing,cabbage,cabbage,cabbage, goat, wolf,nothing,goat]
; S = [goat,nothing,cabbage,cabbage, wolf, goat,cabbage,nothing,goat]
; S = [goat,nothing,cabbage, goat, goat, goat, wolf,nothing,goat]
; S = [goat,nothing,cabbage, goat, wolf,cabbage,cabbage,nothing,goat]
; S = [goat,nothing,cabbage, goat, wolf,nothing, goat, goat,goat]
; S = [goat,nothing,cabbage, goat, wolf,nothing,nothing,nothing,goat]
; S = [goat,nothing,cabbage, goat, wolf, wolf, wolf,nothing,goat]
; S = [goat,nothing,nothing,nothing,cabbage, goat, wolf,nothing,goat]
; S = [goat,nothing,nothing,nothing, wolf, goat,cabbage,nothing,goat]
; S = [goat,nothing, wolf, goat,cabbage,cabbage,cabbage,nothing,goat]
; S = [goat,nothing, wolf, goat,cabbage,nothing, goat, goat,goat]
; S = [goat,nothing, wolf, goat,cabbage,nothing,nothing,nothing,goat]
; S = [goat,nothing, wolf, goat,cabbage, wolf, wolf,nothing,goat]
; S = [goat,nothing, wolf, goat, goat, goat,cabbage,nothing,goat]
; S = [goat,nothing, wolf, wolf,cabbage, goat, wolf,nothing,goat]
; S = [goat,nothing, wolf, wolf, wolf, goat,cabbage,nothing,goat].
为了便于阅读,上面仅显示S
的答案替换。
请注意,所有使用minlen_solution/2
的查询都会被终止。