I'm using SWI 7.2.3 and have the following program :
?-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).
As you can see size,wall
are dynamic and both essentially takes integers.
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).
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
).
I tried using forall
but forall doesn't work good with constraints as stated in this question.
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 ?.
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.
size(N,M)
means our board has N
rows and M
columns, wall(X,Y)
means the cell (X,Y)
is a wall.
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.
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_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.