从剩余目标中获取价值

Get a value from residual goals

如果我有X #> 3.,Prolog 将给出残差目标X in 4..sup.。我如何分配 X 从 4 到 sup 的可能值之一?任何随机值都可以。

在 SWI-Prolog 中,您可以使用秘密选项 random_value(Seed) 来随机分配值。 看到这个:How does `random_variable `random_value` work in SWI-Prolog's labeling/2?



    :- use_module(library(clpfd)).

    random_labeling_test(A):-
        A in 1..5,
        labeling([random_value(332)],[A]).



    ?- random_labeling_test(A).
    A = 5 ;
    A = 1 ;
    A = 2 ;
    A = 4 ;
    A = 3.

332 是 meaningless.Set 随机种子,通常使用 here.current 毫秒。

我不确定这个选项是否安全。

但在你的情况下,这不起作用,因为上限是 infinite.It 是合理的。

在ECLiPSe中,标签变量选择和赋值选择完全可以通过indomaindelete来控制。 看到这个:http://eclipseclp.org/doc/tutorial/tutorial088.html

一个天真的解决这个问题的方法是使用这样的谓词:

enumeration(Z) :-
        length(_, N),
        enumeration_(N, Z).

enumeration_(N, N).
enumeration_(N0, N) :- N #= -N0.

您现在可以按如下方式解决您的任务:

?- X #> 3, enumeration(X).
X = 4 ;
X = 5 ;
X = 6 ;
X = 7 ;
X = 8 .

优点:

  • 一个相当简单的解决方案
  • 可移植到不同的 Prolog 系统。

缺点:

  • 可能相当.

示例:

?- X #> 2^100, enumeration(X).
[waiting...]

为了提高效率,您需要考虑变量的实际

至少有两种方法可以做到这一点:

(a) 使用求解器的反射谓词

反射谓词 让您可以推理变量的实际,方法是将它们作为 Prolog 项提供。

例如,如果可用,您可以使用 fd_inf/2 来获取约束变量域的 infimum

?- X #> 3, fd_inf(X, Inf).
Inf = 4,
X in 4..sup.

您可以将其用作枚举的起点。我把它作为一个挑战。

有关其反射谓词的更多信息,请参阅您的 Prolog 系统手册。

(b) 检查剩余目标

或者,您可以检查 剩余目标 作为 Prolog 术语。这也是一种反射机制,尽管对于各种不同的约束求解器只需要一个谓词。

例如,如果可用,您可以使用 copy_term/3 将剩余目标作为 Prolog 目标的 list :

?- X #> 3, copy_term(X, X, Gs).
Gs = [clpfd:(X in 4..sup)],
X in 4..sup.

根据这些目标,再次straight-forward推导出X的域的下界。

请注意,top-level 可以使用相同的机制来实际生成剩余目标。