Prolog编程
我在Prolog中使用爬山和波束搜索算法为nqueens难题制作了两个程序 不幸的是,我没有经验来检查这些程序是否正确,我处于死胡同 如果有人能帮我,我将不胜感激。 不幸的是,爬山的程序是不正确的<代码>:( beam搜索中的程序是:Prolog编程,prolog,n-queens,state-space,beam-search,Prolog,N Queens,State Space,Beam Search,我在Prolog中使用爬山和波束搜索算法为nqueens难题制作了两个程序 不幸的是,我没有经验来检查这些程序是否正确,我处于死胡同 如果有人能帮我,我将不胜感激。 不幸的是,爬山的程序是不正确的:( beam搜索中的程序是: queens(N, Qs) :- range(1, N, Ns), queens(Ns, [], Qs). range(N, N, [N]) :- !. range(M, N, [M|Ns]) :- M < N, M1 is M+1,
queens(N, Qs) :-
range(1, N, Ns),
queens(Ns, [], Qs).
range(N, N, [N]) :- !.
range(M, N, [M|Ns]) :-
M < N,
M1 is M+1,
range(M1, N, Ns).
queens([], Qs, Qs).
queens(UnplacedQs, SafeQs, Qs) :-
select(UnplacedQs, UnplacedQs1,Q),
not_attack(SafeQs, Q),
queens(UnplacedQs1, [Q|SafeQs], Qs).
not_attack(Xs, X) :-
not_attack(Xs, X, 1).
not_attack([], _, _) :- !.
not_attack([Y|Ys], X, N) :-
X =\= Y+N,
X =\= Y-N,
N1 is N+1,
not_attack(Ys, X, N1).
select([X|Xs], Xs, X).
select([Y|Ys], [Y|Zs], X) :- select(Ys, Zs, X).
皇后区(北,北):
范围(1,N,Ns),
皇后区(北纬,[],北纬)。
范围(N,N,[N]):-!。
范围(M,N,[M|Ns]):-
Mqueens(0, []).
queens(N, [Q|Qs]) :-
M is N-1,
queens(M, Qs),
between(1, N, Q),
safe(Q, Qs).
如果
safe(Q,Qs)
为真,如果Qs
攻击Q
safe/2
中没有一个是简单memberchk/2
检查的结合(参见SWI Prolog手册)还有你的not_attack/2
谓词,乍一看似乎是正确的。如果我正确阅读了你的代码,你尝试实现的算法是一个简单的深度优先搜索,而不是波束搜索。这没关系,因为它应该是(我不知道波束搜索对这个问题如何有效,而且可能很难编程)
我不会为您调试这段代码,但我会给您一个建议:使用
queens(0, []).
queens(N, [Q|Qs]) :-
M is N-1,
queens(M, Qs),
between(1, N, Q),
safe(Q, Qs).
如果safe(Q,Qs)
为真,如果Qs
攻击Q
safe/2
中没有一个是简单memberchk/2
检查的结合(参见SWI Prolog手册)和您的not_attack/2
谓词,乍一看似乎是正确的。快速检查有助于您使用代码并找到要更改的内容
为了清晰起见,我最喜欢的解决方案是与上面链接的第二个:
% This program finds a solution to the 8 queens problem. That is, the problem of placing 8
% queens on an 8x8 chessboard so that no two queens attack each other. The prototype
% board is passed in as a list with the rows instantiated from 1 to 8, and a corresponding
% variable for each column. The Prolog program instantiates those column variables as it
% finds the solution.
% Programmed by Ron Danielson, from an idea by Ivan Bratko.
% 2/17/00
queens([]). % when place queen in empty list, solution found
queens([ Row/Col | Rest]) :- % otherwise, for each row
queens(Rest), % place a queen in each higher numbered row
member(Col, [1,2,3,4,5,6,7,8]), % pick one of the possible column positions
safe( Row/Col, Rest). % and see if that is a safe position
% if not, fail back and try another column, until
% the columns are all tried, when fail back to
% previous row
safe(Anything, []). % the empty board is always safe
safe(Row/Col, [Row1/Col1 | Rest]) :- % see if attack the queen in next row down
Col =\= Col1, % same column?
Col1 - Col =\= Row1 - Row, % check diagonal
Col1 - Col =\= Row - Row1,
safe(Row/Col, Rest). % no attack on next row, try the rest of board
member(X, [X | Tail]). % member will pick successive column values
member(X, [Head | Tail]) :-
member(X, Tail).
board([1/C1, 2/C2, 3/C3, 4/C4, 5/C5, 6/C6, 7/C7, 8/C8]). % prototype board
然而,最后一个链接以三种不同的方式解决了这个问题,因此您可以将其与三种已知的解决方案进行比较。快速检查有助于您使用代码并找到要更改的内容
为了清晰起见,我最喜欢的解决方案是与上面链接的第二个:
% This program finds a solution to the 8 queens problem. That is, the problem of placing 8
% queens on an 8x8 chessboard so that no two queens attack each other. The prototype
% board is passed in as a list with the rows instantiated from 1 to 8, and a corresponding
% variable for each column. The Prolog program instantiates those column variables as it
% finds the solution.
% Programmed by Ron Danielson, from an idea by Ivan Bratko.
% 2/17/00
queens([]). % when place queen in empty list, solution found
queens([ Row/Col | Rest]) :- % otherwise, for each row
queens(Rest), % place a queen in each higher numbered row
member(Col, [1,2,3,4,5,6,7,8]), % pick one of the possible column positions
safe( Row/Col, Rest). % and see if that is a safe position
% if not, fail back and try another column, until
% the columns are all tried, when fail back to
% previous row
safe(Anything, []). % the empty board is always safe
safe(Row/Col, [Row1/Col1 | Rest]) :- % see if attack the queen in next row down
Col =\= Col1, % same column?
Col1 - Col =\= Row1 - Row, % check diagonal
Col1 - Col =\= Row - Row1,
safe(Row/Col, Rest). % no attack on next row, try the rest of board
member(X, [X | Tail]). % member will pick successive column values
member(X, [Head | Tail]) :-
member(X, Tail).
board([1/C1, 2/C2, 3/C3, 4/C4, 5/C5, 6/C6, 7/C7, 8/C8]). % prototype board
然而,最后一个链接以三种不同的方式解决它,因此您可以与三种已知的解决方案进行比较。我想提到的是,这个问题是一个典型的约束满足问题,可以使用SWI Prolog的CSP模块高效地解决。以下是完整的算法:
:- use_module(library(clpfd)).
queens(N, L) :-
N #> 0,
length(L, N),
L ins 1..N,
all_different(L),
applyConstraintOnDescDiag(L),
applyConstraintOnAscDiag(L),
label(L).
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
N
是皇后的数量或电路板的大小(),其中皇后在线路上的位置
让我们详细介绍上述算法的每个部分,以了解发生了什么
:- use_module(library(clpfd)).
它指示SWI Prolog加载包含约束满足问题谓词的模块
queen
谓词是算法的入口点,它检查术语的格式是否正确(数字范围、列表长度)。它还检查queen是否在不同的行上
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
它检查当前被迭代皇后的后代对角线上是否有皇后
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
和前面一样,但它检查上升对角线上是否有女王
最后,可以通过调用谓词queens/2
找到结果,例如:
?- findall(X, queens(4, X), L).
L = [[2, 4, 1, 3], [3, 1, 4, 2]]
我想提到的是,这个问题是一个典型的约束满足问题,可以使用SWI Prolog的CSP模块高效地解决。下面是完整的算法:
:- use_module(library(clpfd)).
queens(N, L) :-
N #> 0,
length(L, N),
L ins 1..N,
all_different(L),
applyConstraintOnDescDiag(L),
applyConstraintOnAscDiag(L),
label(L).
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
N
是皇后的数量或电路板的大小(),其中皇后在线路上的位置
让我们详细介绍上述算法的每个部分,以了解发生了什么
:- use_module(library(clpfd)).
它指示SWI Prolog加载包含约束满足问题谓词的模块
queen
谓词是算法的入口点,它检查术语的格式是否正确(数字范围、列表长度)。它还检查queen是否在不同的行上
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
它检查当前被迭代皇后的后代对角线上是否有皇后
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
和前面一样,但它检查上升对角线上是否有女王
最后,可以通过调用谓词queens/2
找到结果,例如:
?- findall(X, queens(4, X), L).
L = [[2, 4, 1, 3], [3, 1, 4, 2]]
这里的问题到底是什么?这不是远程波束搜索。您好,谢谢您的回复。我从您的回复中了解到,代码不正确。我的意思是,这不是波束搜索算法。您能否提供更正程序的指南?我是Prolog新手。谢谢这里的问题到底是什么?这不是远程波束搜索。您好谢谢你的回复。我从你的回复中了解到代码是不正确的。我的意思是,它不是波束搜索算法。你能提供修改程序的指南吗?我是Prolog新手。谢谢你回答得很好,谢谢你发帖!不过不需要任何
!/0
。最好保持通用性!参数索引将自动完成OMATALY区分这些情况。您好@mat,谢谢您的评论!它们确实是绿色切割。我引入它们是为了防止执行无用的统一。它们可以安全地删除。:)请尝试最一般的查询:当前,您得到的是?-applyConstraintOnDescDiag(Ls)。
只有一个解决方案