【发布时间】:2016-09-27 13:00:13
【问题描述】:
我正在使用 SWI 7.2.3 并且有以下程序:
?-use_module(library(clpfd)).
:- dynamic size/2,wall/2.
in_board(X,Y):-X #> 0,Y #> 0,size(N,M),X #=< N,Y #=< M.
wall_exists_line(X,Y,W) :- wall(X,Z),(Y #=< Z,W #=< Y;Y#=< W,Z#=< Y).
wall_not_exists_line(X,Y,W) :- not(wall_exists_line(X,Y,W)).
same_line(X,Y,Z,W):- X #= Z,in_board(Z,W),in_board(X,Y),wall_not_exists_line(X,Y,W).
我在这里使用约束编程,因为我希望 in_board 能够工作,即使 X 和 Y 都没有实例化(是的,我知道它可以通过其他方式实现,但我发现这更容易)。
如您所见,size,wall 是动态的,并且两者本质上都采用整数。
我的问题是,如果我断言size(4,4) 和wall(2,2) 并查询same_line(X,1,Y,3),它在应该返回X = Y, X in 1\/3..4(或类似的)时返回false。
我知道not(something(X)) 的意思是“在某事为真的地方不存在 X”,我想要“在某事 (X) 不为真的地方存在 X”(实际上我的意思是wall_exists_line)。
我尝试使用forall,但对于this 问题中所述的约束条件,forall 无法正常工作。
可以找到针对我的特定问题的解决方案但我更喜欢一般性的答案,那就是如何解决forall 通常会做的约束?
大目标
上面的程序只是prolog程序的一个子集,它应该解决akari游戏(也称为点亮,参见game),需要谓词same_line来确定哪些单元格被某些人点亮光。
size(N,M) 表示我们的板有N 行和M 列,wall(X,Y) 表示单元格(X,Y) 是一堵墙。
编辑
我之前没有wall_not_exists_line,我把not(wall_exists_line)直接放在same_line中,我以为引入单独的谓词可以解决它,但它没有。
我想把wall_exists_line改成它的否定,q and p的否定是not(q) or not(p)所以wall_exists_line会变成这样:
wall_not_exists_line(X,Y,W) :- not(wall(X,Z));(not(Y #=<Z);not(W #=<Y)),(not(Y#=<W);not(Z#=<Y)).
不幸的是,not(wall(X,Z)) 的意思是“不存在 X 或 Z,而 wall(X,Z) 为真”,我不想要这个,因为wall 是动态的,所以我无能为力。
【问题讨论】: