Reputation: 115
I have a clause is_adjacent([X1,Y1], [X2,Y2])
which is true, when [X2,Y2]
is a neighbor of [X1,Y1]
. I get all possible results (four) if i ask is_adjacent([2,2], [X,Y])
, in this case:
is_adjacent([2,2],[X,Y]).
X = 2,
Y = 3 ;
X = 3,
Y = 2 ;
X = 2,
Y = 1 ;
X = 1,
Y = 2.
I want to use this behavior in another clause:
anotherClause :-
is_adjacent([2,2],[X,Y]),
[to be continued...].
Now, how can i work automatically with every possible result? For example if i want to check if every single result is a member of a specific list.
Thanks for your answers!
Upvotes: 0
Views: 792
Reputation: 13223
There is a way to transform ∀ (for all) into ∃ (there exists) with double-not approach:
∀x.f(x) = ¬¬∀x.f(x) = ¬∃x.¬f(x)
anotherClause :- \+(notAnotherClause).
notAnotherClause :- is_adjacent([2,2],[X,Y]), \+(memberchk([X,Y], SomeList)).
Idea is that we search for existence of negative result within all alternatives and absence of that actually means "for all variants".
P.S. \+/1
(\+(Goal)
) sometimes written as not/1
(not(Goal)
)
Upvotes: 0
Reputation: 60024
there is forall/2, that seems to fit your requirements:
% this fails because not all results are in list
anotherClause :-
forall(is_adjacent([2, 2], [X, Y]),
memberchk([X, Y], [[2, 3], [3, 2]])).
% this succeed, all results are in list
anotherClause :-
forall(is_adjacent([2, 2], [X, Y]),
memberchk([X, Y], [[2, 3], [3, 2], [1, 2], [2, 1]])).
for test purpose, I coded is_adjacent this way:
is_adjacent([A, B], [X, Y]) :-
member(U / V, [1 / 0, 0 / 1, -1 / 0, 0 / -1]),
X is A + U, Y is B + V.
Upvotes: 1
Reputation: 24409
If you want to collect all solutions, I think you might be looking for the set of predicate setof
. This finds all solutions of a predicate.
setof([X,Y], is_ajacent([2,2],[X,Y], Z)
then
Z = [[2,3], [1,2], ...]
If you don't want to collect all solutions, but simply do something for each solution, then do as dasblinkenlight second solution shows. specifically fail
at the end so Prolog tries the next solution. Then finally succeed.
Upvotes: 0
Reputation: 726699
To check every result of is_adjacent
against some other rule, all you need to do is to write that rule in terms of X
and Y
, like this:
anotherClause :-
is_adjacent([2,2],[X,Y]),
X > 0,
Y > 0,
check_x_and_y(X, Y, Result),
...
and so on. When you evaluate anotherClause
, Prolog will unify X
and Y
with the first set of values, and then go on with the rest of the clause (above, it's checking that X
and Y
are greater than zero, and evaluating the two variables with the check_x_and_y
rule. Once the rule comes up with a set of assignments, it gives them to you, and lets you stop or continue. If you want to always continue until the whole set is exhausted (e.g. to print all assignments of X
and Y
), the pattern looks like this:
anotherClause :-
is_adjacent([2,2],[X,Y]),
print_x_and_y(X,Y),
fail.
anotherClause.
The first rule goes through each assignment of X
, Y
, prints them, and then fail to trigger re-evaluation. The second rule is a catch-all fact to stop further evaluation.
Here is a link to a demo on ideone that prints all pairs of adjacent cells.
Upvotes: 0