【问题标题】:Prevent unification of variables within list防止列表中的变量统一
【发布时间】:2018-01-21 21:12:04
【问题描述】:

我正在尝试编写一个谓词,如果变量X 和谓词f(X) 都是输入列表L 的元素,则返回1,如果其中至少一个缺失,则返回0。

这是谓词应该做的:

?- f_in_list([X, f(X)], Val).
  should return Val = 1

?- f_in_list([X, f(Y), Z], Val).
  should return Val = 0, as X and Y are different variables.

我写了这个简单的代码:

f_in_list(L, 1) :-
    member(X, L),
    member(f(X), L),
    !.
f_in_list(_, 0).

我的问题是 Prolog 总是试图统一输入变量,所以它分别返回 X = f(X)X = f(Y)
我尝试使用dif(X, f(X)) 来规避这个问题,但即使这样也没有用。如果列表包含至少两个元素,Val 将始终为 1。

有没有办法将变量转换为原子或字符串,所以Prolog无法统一变量?或者更好的是,有没有办法防止同名变量的统一?

【问题讨论】:

  • 由于您只需要检测Xf(X),因此可以将它们写为xf(x)。然后你可以提供这样的列表[x, f(x), z](使用常量而不是变量)。
  • 遗憾的是我不能这样做,因为该程序需要特定类型的输入。如果有一种方法可以自动为我的输入变量分配成对不同的常量,这将起作用。
  • 您以什么方式尝试使用dif/2?我有兴趣看到这种尝试的解决方案。

标签: prolog


【解决方案1】:

正如@lurker 所提到的,您应该考虑使用==/2,因为它只有在两个术语已经相同而没有进一步统一的情况下才会成功。

她是我的实现:

f_in_list(L, 1) :-
    member(X, L),
    member(f(Y), L),
    X == Y ,!.

f_in_list(_, 0).

例子:

?- f_in_list([X, f(X)], Val).
Val = 1.

?- f_in_list([X, f(Y), Z], Val).
Val = 0.

【讨论】:

  • 您可以使用X \== f(Y) 并避免使用\+。 :)
  • 你需要X \== f(X)吗?我无法亲自尝试,但我认为这种说法可能永远是正确的。
  • 我现在比我更喜欢你的回答。 :)
【解决方案2】:

这可以很好地使用==/2。此运算符不统一,但它检查其参数是否相同。这是==/2的一点点行为:

2 ?- X == X
|    .
true.

3 ?- X == Y.
false.

4 ?- X = Y, Z = Y, X == Z, write('yes'), nl.
yes
X = Y, Y = Z.

5 ?- X = Y, Z = W, X == Z.
false.

6 ?-

我们可以使用它来创建一个不统一的nu_member/2 谓词:

nu_member(X, [Y|_]) :- X == Y.
nu_member(X, [_|T]) :- nu_member(X, T).

我们在f_in_list/2 中使用它:

f_in_list(L, 1) :-
    member(X, L),
    nu_member(f(X), L),
    !.
f_in_list(_, 0).

结果:

2 ?- f_in_list([X,f(X), Z], B).
B = 1.

3 ?- f_in_list([X,f(Y), Z], B).
B = 0.

4 ?- f_in_list([X,f(Y), f(Z)], B).
B = 0.

5 ?- f_in_list([X,f(Y), f(Z),Z], B).
B = 1.

【讨论】:

  • 非常感谢!我没想到这么简单的解决方案。干得好!
猜你喜欢
  • 1970-01-01
  • 2015-09-13
  • 2016-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-07
  • 2013-05-09
  • 2013-03-20
相关资源
最近更新 更多