SWI Prolog Clpfd图书馆 - 具体化

时间:2016-05-08 10:12:32

标签: prolog clpfd reification

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

通过使用它来表示变量B可以的属性来说明具体化 取值1或8。

在阅读了一些资源并查看了SWI Prolog手册后,我仍然发现具体化的概念令人困惑(主要是研究Java,因此转向学习Prolog很困难)。在prolog查询中使用布尔逻辑非常令人困惑。

如果没有具体化,我将不得不编写以下代码(我知道这个代码太长而不能成为正确的答案);

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

如果有人可以向我展示上述查询,但使用具体化,我们将非常感激。

3 个答案:

答案 0 :(得分:4)

首先,试试你的问题:

?- 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。

Reification允许您 reify 约束的真值。例如,您可以说:

?- 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 不能保留

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

答案 1 :(得分:3)

来自文档:

  

/ 2,#= / 2,#\ = / 2,#/ 2,#== / 2中的约束可以被确定,这意味着将它们的真值反映为由整数0和1表示的布尔值。设P和Q表示可再生约束或布尔变量,然后:

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

对您而言,似乎PB #= 1QB #= 8,因此您最终会:

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

如您所见,您并未真正使用具体化的值。您只是使用reification作为声明变量域的循环方式。如果你想说“B是1或8”,你的查询答案B in 1 \/ 8就是你可能直接使用的答案。如果仔细查看documentation of in/2,您应该会看到域可以是整数,范围Lower .. Upper,也可以是Domain1 \/ Domain2的并集。在您的情况下,两个域都是一个整数,1和8。

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

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

B在[1,8]中,B不在[2,7]中。

可能性无穷无尽:)

答案 2 :(得分:2)

最初我的想法和@Boris和@mat一样。但在思考了一段时间之后,对这个任务的另一种可能的解释发生在我身上。但是,请记住,我不熟悉您的课程材料,因此这是非常具有推测性的。话虽这么说,也许任务描述要求编写一个谓词,如果上面的属性成立,则评估为 true ,否则为 false 。像这样的谓词可以定义为:

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

我想出了这个想法,因为最近我正在玩Stackoverflow上发现的一些reifying谓词,我突然想到这个任务可能是针对所描述的属性可以用作条件的方向有这样的谓词。例如if_/3我在条件中使用(=)/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一起使用它们的thruth值。但是,您也可以使用10来统一真值,例如在@ mat的示例中。只需将10分别替换为val_either_or_t / 4定义中的第4个参数。此外,你可能会发现@repeat在评论中提出的这个想法的改进也很有趣。