如果我有X #> 3.
Prolog将给出剩余目标X in 4..sup.
。如何将X
中的一个可能值指定为sup
?任何随机值都足够了。
答案 0 :(得分:2)
在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
没有意义。将随机种子放入here.current毫秒经常使用。
我不确定这个选项是否安全。
但在你的情况下,这不起作用,因为上限是无限的。这是合理的。
在ECLiPSe中,使用indomain
和delete
可以完全控制标记变量选择和赋值选择。
看到这个:http://eclipseclp.org/doc/tutorial/tutorial088.html
答案 1 :(得分:1)
解决此问题的一种天真方法是使用这样的谓词:
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 .
优点:
缺点:
示例:
?- X #> 2^100, enumeration(X). [waiting...]
为了提高效率,您需要考虑变量的实际域。
至少有两种方法可以做到这一点:
反射谓词让您可以将变量的实际域作为Prolog术语提供。
例如,如果可用,您可以使用 fd_inf/2
来获取受约束变量域的 infimum :
?- X #> 3, fd_inf(X, Inf). Inf = 4, X in 4..sup.
您可以将其用作枚举的起点。我把这作为挑战。
有关其反射谓词的详细信息,请参阅Prolog系统手册。
或者,您可以将剩余目标视为Prolog术语。这也是一种反射机制,尽管只需要一个谓词用于各种不同的约束求解器。
例如,如果可用,您可以使用 copy_term/3
获取剩余目标作为Prolog目标的列表:
?- X #> 3, copy_term(X, X, Gs). Gs = [clpfd:(X in 4..sup)], X in 4..sup.
从这些目标中,再次直接推断出X
域名的下限。
请注意,顶级可以使用相同的机制来实际产生剩余目标。