prolog - Prolog失败一次就放弃了?
问题描述
我还在学习 Prolog,如果我在这里犯了一些基本错误,请原谅我。我添加了注释来解释我认为代码在做什么,以防我错了。如果我在某些地方解释显而易见的事情,请原谅我。
n_queens(NumQueens, Answer) :-
length(Answer, NumQueens), %Answer must be a list of length NumQueens
queens_are_safe(Answer). %All queens in Answer must be safe
queens_are_safe([]). %If there are no queens, nobody's in danger
queens_are_safe([Queen | Queens]) :-
queen_is_safe(Queen, Queens), %Is the queen safe from her peers?
queens_are_safe(Queens). %Recursively check the other queens
queen_is_safe(_, []).
queen_is_safe(NewQueen, [Queen | Queens]) :-
not(same_column(NewQueen, Queen)),
not(same_row(NewQueen, Queen)),
not(diagonal(NewQueen, Queen)),
queen_is_safe(NewQueen, Queens). %Recursively ensure NewQueen is safe from other queens
diagonal(X/Y, X1/Y1) :- Y1 - Y = X1 - X. %If the X and Y deltas are equal, arguments are diagonal
same_column(X/_, X/_). %If the X coordinates are the same, it's the same column.
same_row(_/Y, _/Y). %If the Y coordinates are the same, it's the same row.
我期望 Prolog 做的是生成一个皇后列表,将其绑定到 Answer,然后重复,直到找到满足所有条件的值列表。例如,如果 NumQueens 为 2,它将测试 [0/0, 0/0],然后是 [1/0, 0/0],依此类推。
但是我怀疑我在这里大错特错。跟踪堆栈在这里失败:
Exit: (12) samecolumn(_15108/_15110, _15108/_15116) ? creep
Fail: (11) not(user:samecolumn(_15048, _15054)) ? creep
显然问题在于它使用_15108 作为same_column 的X 值。我希望它然后尝试 same_column 但使用不同的 X 值。但它不会再试一次,它会失败并为查询返回 falsen_queens(8,Ans).
为什么会这样?
解决方案
尝试在 SWI-Prolog 中运行代码时出现以下错误:
?- n_queens(8, Ans).
ERROR: not/1: Undefined procedure: samecolumn/2
ERROR: However, there are definitions for:
ERROR: same_column/2
您是否使用了在尝试调用未定义谓词时静默失败的 Prolog?您不应该,或者您应该将其配置为在这种情况下引发错误。例如,在 YAP 中,默认行为是您看到的损坏的行为:
?- n_queens(8, Ans).
no
但是你可以像这样修复它:
?- set_prolog_flag(unknown, error).
yes
?- n_queens(8, Ans).
ERROR!!
EXISTENCE ERROR- procedure samecolumn/2 is undefined, called from context prolog:$query/2
Goal was user:samecolumn(_131242,_131243)
编辑:只是为了明确这一点,如消息所示,直接的问题之一是您试图调用samecolumn/2
未定义的谓词;你可能打算打电话给same_column/2
.
Y1 - Y = X1 - X
在此之后,由于diagonal/2
. 例如,您可能希望diagonal(2/3, 3/4)
成功,但目标在 Prolog4 - 3 = 3 - 2
中没有成功:
?- 4 - 3 = 3 - 2.
false.
这是因为 Prolog 不将类似的项4 - 3
视为算术表达式来计算为类似的数字1
。您可能需要将=:=
两个操作数都计算为数字然后比较它们的运算符:
?- 4 - 3 =:= 3 - 2.
true.
但即使在这一切之后,这段代码也行不通。您的程序从不指定应该将 中的变量Queens
绑定到整数1
的任何地方NumQueens
。Prolog 不只是为您编造这些数字!您可能想使用clpfd
.
推荐阅读
- android - flutter - 如何在应用程序启动和使用时下载资产
- python - 如何修复/删除动态创建的geoJson文件中不需要的“\ n”新行(Python)
- ios - Xcode自动布局不适用于所有设备
- julia - 两个不同的 Julia 项目和他们的 toml
- python - 没有从烧瓶应用程序中的 mysql.connector 取回 dict
- scala - 包含来自字符串列表的确切字符串的文本
- javascript - 试图将数字保留在仅包含 5 位数字且仅包含数字 2、3、5、7 的数组中
- python - 如何在 Python 中找到日期时间值的百分比增加/减少?
- windows - 如何检查输入是否已经在列表中 - 批处理
- python - Python 通过 win32com 运行 MessageQueue.Peek,如何正确超时?