[英]prolog constraint programming and forall/2
I'm using SWI 7.2.3 and have the following program : 我正在使用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).
I'm using constraint programming here because I want in_board
to work even when both X
and Y
are not instantiated(yes I know it could be implemented other ways but I found this to be easier). 我在这里使用约束编程因为我希望
in_board
能够工作,即使X
和Y
都没有实例化(是的,我知道它可以通过其他方式实现,但我发现这更容易)。
As you can see size,wall
are dynamic and both essentially takes integers. 你可以看到
size,wall
是动态的,两者都基本上是整数。
My problem is if I assert size(4,4)
and wall(2,2)
and query same_line(X,1,Y,3)
it returns false when it should return X = Y, X in 1\\/3..4
(or alike). 我的问题是如果我断言
size(4,4)
和wall(2,2)
并查询same_line(X,1,Y,3)
它返回false时它应该返回X = Y, X in 1\\/3..4
(或相似)。
I know that not(something(X))
means "no X exists where something is true", I wanted "there exists X where something(X) is not true"(by something I actually mean wall_exists_line
). 我知道
not(something(X))
意味着“没有X存在于某些东西是真的”,我想“存在X,某些东西(X)不是真的”(通过我实际上是指wall_exists_line
东西)。
I tried using forall
but forall doesn't work good with constraints as stated in this question. 我尝试使用
forall
但是forall不能很好地解决这个问题中所述的约束。
A solution for my particular problem can be found But I'd prefer a general answer, that is how to do for constraints what forall
would do normally ?. 我可以找到针对我的特定问题的解决方案但是我更喜欢一般性的答案,那就是如何处理
forall
通常会做的约束?
The program above is just a subset of a prolog program which is supposed to solve akari game(also called light-up, see game ), the predicate same_line
is needed to determine which cells are lighten up by some light. 上面的程序只是prolog程序的一个子集,它应该解决akari游戏(也称为点亮,参见游戏 ),需要谓词
same_line
来确定哪些细胞被某些光照亮。
size(N,M)
means our board has N
rows and M
columns, wall(X,Y)
means the cell (X,Y)
is a wall. size(N,M)
表示我们的板有N
行和M
列, wall(X,Y)
表示单元(X,Y)
是墙。
I didn't have wall_not_exists_line
before, I put not(wall_exists_line)
directly in same_line
, I thought introducing separate predicate would solve it but it didn't. 之前我没有
wall_not_exists_line
,我把not(wall_exists_line)
直接放在same_line
,我认为引入单独的谓词会解决它,但事实并非如此。
I thought of changing wall_exists_line
into the negation of it, the negation of q and p
is not(q) or not(p)
so wall_exists_line
would change to this: 我
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)).
Unfortunately not(wall(X,Z))
means "No X or Z exists for which wall(X,Z) is true", I don't want this and as wall
is dynamic I can't do anything with it. 不幸的是
not(wall(X,Z))
意味着“没有X或Z存在哪个墙(X,Z)是真的”,我不想要这个,因为wall
是动态的我不能用它做任何事情。
I have found the solution. 我找到了解决方案。
not(wall_exists_line(X,Y,W))
would check every value of X
and Y
and W
if they don't have a fixed value. not(wall_exists_line(X,Y,W))
会检查X
, Y
和W
每个值,如果它们没有固定值。
in_board(X,Y)
constraint both X
and Y
in intervals but not a fixed value so not
would try every value in the interval. in_board(X,Y)
在间隔中约束X
和Y
,但不是固定值,因此not
尝试间隔中的每个值。
The solution is to have the variables X,Y,W
instantiated before entering not
, this is done by changing in_board
to this : 解决的办法是有变量
X,Y,W
在进入之前实例化not
,这是通过改变做in_board
这样:
in_board(X,Y):-size(N,M),between(0,N,X),between(0,M,Y).
This way between
will instantiate X
and Y
and fortunately between
gives all the values in the interval. 通过这种方式
between
将实例X
和Y
,幸好between
给出了区间所有的值。
The main difference between clpfd and just between
is that clpfd returns domain while between
- if the third argument isn't instantiated - returns every value between two values. clpfd和它
between
的主要区别在于clpfd返回域而between
- 如果第三个参数未实例化 - 返回两个值之间的每个值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.