0

我有一个is_adjacent([X1,Y1], [X2,Y2])正确的子句,什么时候[X2,Y2][X1,Y1]. 如果我问is_adjacent([2,2], [X,Y]),我会得到所有可能的结果(四个),在这种情况下:

is_adjacent([2,2],[X,Y]).
X = 2,
Y = 3 ;
X = 3,
Y = 2 ;
X = 2,
Y = 1 ;
X = 1,
Y = 2.

我想在另一个子句中使用这种行为:

anotherClause :-
    is_adjacent([2,2],[X,Y]),
    [to be continued...].

现在,我怎样才能自动处理所有可能的结果?例如,如果我想检查每个结果是否都是特定列表的成员。

感谢您的回答!

4

4 回答 4

1

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.
于 2013-04-18T17:26:48.587 回答
0

如果您想收集所有解决方案,我想您可能正在寻找 predicate 的集合setof。这会找到谓词的所有解。

setof([X,Y], is_ajacent([2,2],[X,Y], Z)

然后

Z = [[2,3], [1,2], ...]

如果您不想收集所有解决方案,而只是为每个解决方案做一些事情,那么按照 dasblinkenlight 的第二个解决方案所示进行操作。特别fail是在最后,所以 Prolog 尝试下一个解决方案。然后终于成功了。

于 2013-04-18T14:36:40.393 回答
0

有一种方法可以将 ∀(对于所有)转换为 ∃(存在),使用双非方法:
∀xf(x) = ¬¬∀xf(x) = ¬∃x.¬f(x)

anotherClause :- \+(notAnotherClause).
notAnotherClause :- is_adjacent([2,2],[X,Y]), \+(memberchk([X,Y], SomeList)).

想法是我们在所有备选方案中寻找否定结果的存在,而没有否定结果实际上意味着“所有变体”。

PS \+/1( \+(Goal)) 有时写成not/1( not(Goal))

于 2013-04-19T09:46:00.047 回答
0

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.

于 2013-04-18T14:23:36.567 回答