简体   繁体   English

prolog约束编程和forall / 2

[英]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能够工作,即使XY都没有实例化(是的,我知道它可以通过其他方式实现,但我发现这更容易)。

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通常会做的约束?

Big Goal 大目标

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)是墙。

Edit 编辑

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))会检查XYW每个值,如果它们没有固定值。

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)在间隔中约束XY ,但不是固定值,因此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将实例XY ,幸好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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM