Prolog 序言:使用*解决8个难题
我正在尝试实现一个问题的求解器。拼图板用列表表示。例如,目标状态:Prolog 序言:使用*解决8个难题,prolog,graph-theory,path-finding,heuristics,sliding-tile-puzzle,Prolog,Graph Theory,Path Finding,Heuristics,Sliding Tile Puzzle,我正在尝试实现一个问题的求解器。拼图板用列表表示。例如,目标状态: 1 | 2 | 3 --------- 4 | 5 | 6 --------- 7 | 8 | 0 表示为[1,2,3,4,5,6,7,8,0],其中0表示空白 我已经实现了move(+Board,-move),它通过move成功,因为Board one的所有可能状态都从Board移开。此外,我还实现了solvable(+Board),它给出了true或false关于是否可以解决Board的问题 我还实现了两种启发式算法,ma
1 | 2 | 3
---------
4 | 5 | 6
---------
7 | 8 | 0
表示为[1,2,3,4,5,6,7,8,0]
,其中0
表示空白
我已经实现了move(+Board,-move)
,它通过move
成功,因为Board one的所有可能状态都从Board
移开。此外,我还实现了solvable(+Board)
,它给出了true
或false
关于是否可以解决Board的问题
我还实现了两种启发式算法,manhattan(+Board,+Goal,-H)
和hamming(+Board,+Goal,-H)
,它们计算从Board
到Goal
的启发式成本。例如:
?- hamming([1,2,3,8,0,4,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 0.
?- hamming([1,2,3,4,0,8,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 2.
?- manhattan([1,2,3,8,0,4,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 0.
?- manhattan([1,2,3,4,0,8,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 4.
?- solve([0,1,3,4,2,5,7,8,6],manhattan,Solution).
Solution = [
[0, 1, 3, 4, 2, 5, 7, 8, 6],
[1, 0, 3, 4, 2, 5, 7, 8, 6],
[1, 2, 3, 4, 0, 5, 7, 8, 6],
[1, 2, 3, 4, 5, 0, 7, 8, 6],
[1, 2, 3, 4, 5, 6, 7, 8, 0]
].
我想实现求解(+Board,+Heuristic,-Solution)
,它成功地使用解决方案
作为Board
的一个最佳解决方案,使用给定的启发式
,并且它必须精确地以一个解决方案终止。例如:
?- hamming([1,2,3,8,0,4,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 0.
?- hamming([1,2,3,4,0,8,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 2.
?- manhattan([1,2,3,8,0,4,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 0.
?- manhattan([1,2,3,4,0,8,7,6,5],[1,2,3,8,0,4,7,6,5],H).
H = 4.
?- solve([0,1,3,4,2,5,7,8,6],manhattan,Solution).
Solution = [
[0, 1, 3, 4, 2, 5, 7, 8, 6],
[1, 0, 3, 4, 2, 5, 7, 8, 6],
[1, 2, 3, 4, 0, 5, 7, 8, 6],
[1, 2, 3, 4, 5, 0, 7, 8, 6],
[1, 2, 3, 4, 5, 6, 7, 8, 0]
].
我为A*算法编写了伪代码:
For each Child of Board do:
If Child in Closed do:
Continue
If Child not in Closed or G(Board) + 1 < G(Child) do:
G(Child) := G(Board) + 1
F(Child) := G(Child) + Heuristic(Child,Goal)
If Child not in Open do:
Open := Open + {Child}
对于板的每个子级,请执行以下操作:
如果儿童处于关闭状态,请执行以下操作:
继续
如果儿童未处于关闭状态或G(板)+1
其中G(Board)
是Board
的实际成本,定义为从初始板到Board
的最佳路径的长度F(Board)
是Board
的组合成本,定义为G(Board)
和Board
的估计成本之和(由启发式函数定义)。当然,Closed
和Open
是由A*算法维护的两个集合,Closed
包含已访问的板,Open
包含未访问的板
问题是我不知道如何在Prolog中实现这一点。我认为需要一些堆数据结构来维护这两个列表,但不知道是什么或如何。任何帮助都会很好