从剩余目标中获取价值
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中,标签变量选择和赋值选择完全可以通过indomain
和delete
来控制。
看到这个: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 可以使用相同的机制来实际生成剩余目标。
如果我有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中,标签变量选择和赋值选择完全可以通过indomain
和delete
来控制。
看到这个: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 可以使用相同的机制来实际生成剩余目标。