SWI Prolog Clpfd 库 - 具体化

SWI Prolog Clpfd Library - Reification

我即将参加逻辑考试,并且一直在研究我课程中的一些过去的论文。我遇到了一个关于具体化的问题并将其发布在下面;

用具体化来表示变量B可以表达的属性 取值 1 或 8.

看了一些资源,看了SWI Prolog手册,还是觉得reification的概念比较混乱(主要是学习Java所以转学Prolog一直很困难)。在 prolog 查询中必须使用布尔逻辑是相当令人困惑的。

如果不具体化,我将不得不编写以下代码(我知道这太长了,不是正确答案);

 B in 1..8, B #\= 2,B #\= 3,B #\= 4,B #\= 5,B #\= 6,B #\= 7. 

如果有人能向我展示上述查询,但使用具体化,我将不胜感激。

首先,尝试查询:

?- B in 1..8, B #\= 2,B #\= 3,B #\= 4,B #\= 5,B #\= 6,B #\= 7.
B in 1\/8.

这表明您的查询 等同于 单一目标 B in 1\/8

由此可见,您不需要具体化来表示有限域变量等于 1 或 8。

具体化允许您具体化约束的真值。例如,您可以说:

?- T #<==> B in 1\/8.
T in 0..1,
B in 1\/8#<==>T.

?- T #<==> B in 1\/8, B = 3.
T = 0,
B = 3.

从第二个查询中,您看到如果 B = 3,则 T = 0,因为约束 B in 1\/8 在中不成立 那种情况。

如果您想自己推理 about 约束,那么具体化约束会很有用。例如,这允许您表示列表元素的某个 number 必须等于给定的整数。我把解决这个问题作为一个更有意义的练习来理解具体化。

来自文档:

The constraints in/2, #=/2, #\=/2, #/2, #==/2 can be reified, which means reflecting their truth values into Boolean values represented by the integers 0 and 1. Let P and Q denote reifiable constraints or Boolean variables, then:

...
P #\/ Q True iff either P or Q
...

对你来说,似乎 PB #= 1QB #= 8,所以你最终得到:

?- B #= 1 #\/ B #= 8.
B in 1\/8.

如您所见,您并没有真正使用具体化的值。您只是将具体化用作声明变量域的一种迂回方式。如果您想说 "B is either 1 or 8",您可能会直接使用查询的答案 B in 1 \/ 8。如果仔细查看 documentation of in/2,您应该会发现域可以是整数、范围 Lower .. UpperDomain1 \/ Domain2 的并集。在您的情况下,两个域都是一个整数,1 和 8。

PS:一旦你走上这条路,为什么不呢:

?- B in 1..8 #/\ #\ B in 2..7.
B in 1\/8.

B is in [1,8] AND B is not in [2,7].

无限可能:)

最初我的想法与@Boris 和@mat 相同。但在思考这个问题一段时间后,我想到了对该任务的另一种可能解释。但是,请记住,我不熟悉您的课程 material,因此这是高度推测性的。话虽这么说,也许任务描述要求编写一个谓词,如果上述 属性 成立或 false,则该谓词的计算结果为 true除此以外。像这样的谓词可以定义为:

val_either_or_t(X,Y,Z,true) :-
   ( X#=Y ; X#=Z).
val_either_or_t(X,Y,Z,false) :-
   X #\= Y,
   X #\= Z.

我承认这个名字有点笨拙,但我真的想不出一个更好的名字。无论如何,它根据我上面描述的任务解释来完成工作:

   ?- val_either_or_t(X,1,8,T).
T = true,
X = 1 ? ;
T = true,
X = 8 ? ;
T = false,
X in inf..0\/2..7\/9..sup

   ?- val_either_or_t(X,Y,Z,T).
T = true,
X = Y,
X in inf..sup ? ;
T = true,
X = Z,
X in inf..sup ? ;
T = false,
X#\=Z,
X#\=Y

我想出这个主意是因为最近我在研究在 Whosebug 上发现的一些具体化谓词,我突然想到该任务的目标可能是所描述的方向 属性可以用作此类谓词的条件。例如,在条件中使用 if_/3 that I used a lot with (=)/3,但为什么不将其与 val_either_or_t/4 之类的东西一起使用呢?考虑以下最小示例:

a(condition_was_true).
b(condition_was_false).

somepredicate(X,Y) :-
   if_(val_either_or_t(X,1,8),a(Y),b(Y)).

使用相应的查询:

   ?- somepredicate(X,Y).
X = 1,
Y = condition_was_true ? ;
X = 8,
Y = condition_was_true ? ;
Y = condition_was_false,
X in inf..0\/2..7\/9..sup

这个例子当然意义不大,只是想说明如何具体化给定的属性。此外,我使用原子 truefalse 来具体化关于将它们与 if_/3 一起使用的真实值。但是,您也可以使用 10 来具体化真值,就像@mat 的示例一样。只需将 val_either_or_t/4 定义中的第 4 个参数分别替换为 10。此外,您可能会发现@repeat 在评论中提出的对这个想法的改进也很有趣。