嗨,所以在我被告知这个问题被多次询问之前,我已经查看过一堆问题,但没有一个与Prolog有关。这就是我遇到的困难。
我试图找到棋盘上两点之间的最短路径。我的代码专门针对骑士。到目前为止,这是我的代码:
move1( (X1,Y1), (X2,Y2) ) :- up1( X1, X2 ), up2( Y1, Y2 ).
move1( (X1,Y1), (X2,Y2) ) :- up2( X1, X2 ), up1( Y1, Y2 ).
move1( (X1,Y1), (X2,Y2) ) :- up1( X1, X2 ), down2( Y1, Y2 ).
move1( (X1,Y1), (X2,Y2) ) :- up2( X1, X2 ), down1( Y1, Y2 ).
move1( (X1,Y1), (X2,Y2) ) :- down1( X1, X2 ), up2( Y1, Y2 ).
move1( (X1,Y1), (X2,Y2) ) :- down2( X1, X2 ), up1( Y1, Y2 ).
move1( (X1,Y1), (X2,Y2) ) :- down1( X1, X2 ), down2( Y1, Y2 ).
move1( (X1,Y1), (X2,Y2) ) :- down2( X1, X2 ), down1( Y1, Y2 ).
up1( U, V ) :- successor( U, V ).
up2( U, W ) :- successor( U, V ), successor( V, W ).
down1( U, V ) :- up1( V, U ).
down2( U, V ) :- up2( V, U ).
successor( 1, 2 ).
successor( 2, 3 ).
successor( 3, 4 ).
successor( 4, 5 ).
edge((X1,Y1) , (X2,Y2)) :- move1( (X1,Y1), (X2,Y2) ).
path((X1,Y1), (X2,Y2),N,[(X1,Y1), (X2,Y2)]) :- N > 0, edge((X1,Y1), (X2,Y2)).
path((X1,Y1), (X3,Y3),N,[(X1,Y1)|P1]) :- N > 0, N1 is N-1, path((X2,Y2), (X3,Y3),N1,P1), edge((X1,Y1), (X2,Y2)), nonmember((X1,Y1),P1).
shortest((X1,Y1),(X2,Y2),P) :- path((X1,Y1),(X2,Y2),24,P),!.
visit((X1,Y1),P,N) :- path((X1,Y1), (X2,Y2),N,P),N2 is N+1,len(P,N2).
len([],0).
len([_|T],N) :- len(T,X), N is X+1.
nonmember(X,[]).
nonmember(X,[U|Y]) :- X \= U, nonmember(X,Y).
如您所见,我只找到第一条路径而不是最短路径。我不知道如何在prolog中编码并找到一种方法来获得所有最短的路径。我正在考虑制作一个列表,列出所有可能的路径,然后找到最短但我似乎无法编写代码。
findAll((X1,Y1),(X2,Y2),P,L) :- path((X1,Y1),(X2,Y2),24,P),length(P,L).
给我每条路的长度,但我不知道该怎么做。 任何有关如何在Prolog中编码以找到最短路径的帮助都将非常有用,而且正是我所寻求的。
答案 0 :(得分:0)
要按照您的方法来计算所有路径并找到最小路径,我会选择aggregate
库。
但首先,我建议对代码进行一些清理,因为我不确定它是否会以这种方式正常工作(但我刚刚检查过很快)。
特别是,您希望到达谓词path((X1, Y1),(X2, Y2),Path)
,该谓词允许枚举所有路径(如果您多次重试)然后停止。一旦所有路径都耗尽,你的东西似乎无限循环。
您可以找到有关如何枚举所有非循环路径here的一些启示。
修复后,您可以通过以下方式使用aggregate/3
:
:-use_module(library(aggregate)).
find_min(Start, End, Path) :-
aggregate(
min(Length, Path),
(path(Start, End, Path), length(Path, Length)),
min(_,P)
).
然后 find_min(Start, End, Path)
将允许您枚举从一个单元格到另一个单元格的所有最短路径。
请注意,从Start
到End
可能有多条最短路径;这将返回所有最短路径,而不仅仅是一条路径。
另一个可能的解决方案是实现Djikstra的最短路径算法,这可能比枚举所有路径和找到最小路径算法更有效,就像我们在这里做的那样。但这将是一种完全不同的方法。
编辑:使用小型主板4x4或5x5,然后枚举所有路径并找到最小方法可能会起作用,但在8x8主板上,复杂性将变得无法控制。 在这里,最好的方法是改变你的方法和实现,例如,Djikstra的算法。