【问题标题】:Prolog - Arguments are not sufficiently instantiated - Knight/chessboardProlog - 参数没有充分实例化 - Knight/chessboard
【发布时间】:2014-11-22 19:30:30
【问题描述】:

我对 Prolog 很陌生,我正在尝试编写一个简单的方法来确定棋盘上的骑士是否可以跳到另一个方格,或者输出一个骑士可以跳到给定方格的所有方格。对于此方法,假设必须始终实例化第一个参数。给定两个参数,它可以正常工作,但我不确定为什么它不会只输出一个。

% validSquare/2
% validSquare(X1/Y1, X2/Y2) iff the coordinate is a valid position on an 8x8 chessboard.
validSquare(X1/Y1, X2/Y2) :-
  X1 >= 1, X1 =< 8,
  Y1 >= 1, Y1 =< 8,
  X2 >= 1, X2 =< 8,
  Y2 >= 1, Y2 =< 8.


% jump/2
% jump(Square1, Square2) iff a knight could jump to the coordinate
% Square1/Square2 on a chessboard.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 + 1,
  Y2 is Y1 + 2.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 + 2,
  Y2 is Y1 + 1.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 + 1,
  Y2 is Y1 - 2.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 + 2,
  Y2 is Y1 - 1.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 - 1,
  Y2 is Y1 - 2.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 - 2,
  Y2 is Y1 - 1.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 - 1,
  Y2 is Y1 + 2.
jump(X1/Y1, X2/Y2) :-
  validSquare(X1/Y1, X2/Y2),
  X2 is X1 - 2,
  Y2 is Y1 + 1.

就像我说的,我对 Prolog 很陌生,所以我不确定我应该如何格式化查询。这个查询是假的。

?- jump(1/1, X2/Y2).
ERROR: >=/2: Arguments are not sufficiently instantiated

感谢您的帮助。

【问题讨论】:

  • 如果您只使用 CLP(FD) 约束而不是低级整数算术,这将完全按预期工作:而不是 (is)/2,使用更通用的 (#=)/2。代替(&gt;=)/2,使用更通用的(#&gt;=)/2。而不是(=&lt;)/2,使用更通用的(#=&lt;)/2
  • 将validSquare/2重写为validSquare/1!

标签: prolog instantiation-error


【解决方案1】:
:- use_module(library(clpfd)).

jump(X0/Y0, X/Y) :-
   abs(X0-X)+abs(Y0-Y)#=3,
   X0 #\= X,
   Y0 #\= Y,
   [X0,Y0,X,Y]ins 1..8.

【讨论】:

  • 如果您编辑答案以解释其工作原理/原因,提问者可能会更感激它
【解决方案2】:

validSquare 中的 >= 测试中断了。当两者都未绑定时,您无法确定X &lt;= Y 的真值,基本上,因为数字运算符不分配值。您可以通过使用成员将坐标绑定到有效正方形来解决此问题,即

validSquare(X1/Y1, X2/Y2):-
    member(X1, [1,2,3,4,5,6,7,8]),
    member(X2, [1,2,3,4,5,6,7,8]),
    member(Y1, [1,2,3,4,5,6,7,8]),
    member(Y2, [1,2,3,4,5,6,7,8]).

根据您使用的 Prolog 方言,member 可能是内置的(例如 SWI-Prolog)。

【讨论】:

  • 太好了,谢谢。我希望它会是那么简单。感谢您的帮助
  • @ChrisPhillips between(1,8,X1),请
  • 请考虑使用 CLP(FD) 约束而不是低级整数运算。
【解决方案3】:

这是this fine answer 中提供的代码的替代方案。它也是基于

跳跃(X0/Y0,X/Y):- D_x #= X0-X, D_y #= Y0-Y, abs(D_x) #\= abs(D_y), [D_x , D_y] ins (-2 .. -1)\/(1..2), [X0,X,Y0,Y] 插入 1..8。

效率很高1,2


脚注 1: 使用 版本 4.3.2(64 位)和 版本 7.3.11(64 位)进行测试。
脚注 2: SICStus Prolog 需要一个合适的 (ins)/2 定义才能运行上面的代码。

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多