鉴于这个小例子:
go:-
length( X, 200 ),
domain( X, 1, 25),
postConstraints( X, Y ),
labeling( [minimize(Y), X ).
如果我们假设postConstraints
设置了一些复杂的约束。
Y从postConstraints
返回,并在标记期间用作成本函数。
我们假设我们没有(或极少)了解postConstraints
设置的约束。但我们知道最佳解决方案(或一个好的解决方案)将是X包含可能域的或多或少的均匀分布。即值1将出现在8(200/25)次左右,2将出现在8次左右,等等。
但是我们不知道每个值会出现在什么位置。
如果我们从使用默认标签开始,X将首先仅分配1,这是一个解决方案,但不是一个好的解决方案(高Y)。通过长时间运行搜索,将找到最佳解决方案,这在可能的域上或多或少是均匀分布。
这意味着搜索需要很长时间才能从第一个可能的解决方案转到最佳(或更好)的解决方案。
我认为如果在标记之前可以将初始'猜测'应用于X,则搜索会更快。
防爆。如果X填充了域中的随机值?
在Sicstus有没有办法做到这一点?这是您在value(Enum)
中使用labeling
的位置吗?
答案 0 :(得分:1)
您的问题不包含具体示例,因此很难提出具体建议。但是,您可以先考虑标签选项ff
。至少原因很简单:添加预定义的标签选项可能会影响运行时但不会影响正确性。更复杂的方法总是存在引入错误的风险。
谓词labeling/2
提供了两种预定义方式来枚举所选变量的值:up
(默认值)和down
。要从不同的值开始,您可以将变量映射到另一个变量,该变量再次使用其中一个内置枚举。定义自己的枚举方法是可能的,但绝对不是初学者的任务。事实上,即使library/clpfd/examples/
也没有提供单一的例子。
为了说明如何以不同方式枚举变量,我将使用单个变量X
:
| ?- X in 1..5, labeling([],[X]).
X = 1 ? ;
X = 2 ? ;
X = 3 ? ;
X = 4 ? ;
X = 5 ? ;
no
| ?- X in 1..5, labeling([down],[X]).
X = 5 ? ;
X = 4 ? ;
X = 3 ? ;
X = 2 ? ;
X = 1 ? ;
no
现在我们要以价值3开始X
。因此,X
会映射到Xx
,而不会用于标注:
| ?- X in 1..5, Xx #= (X+5-3)mod 5,labeling([],[Xx]).
X = 3,
Xx = 0 ? ;
X = 4,
Xx = 1 ? ;
X = 5,
Xx = 2 ? ;
X = 1,
Xx = 3 ? ;
X = 2,
Xx = 4 ? ;
no
通过这种方式,您可以将每个变量映射到其他一些初始值。或者都是一样的。但请注意,由于(mod)/2
的相对较弱的一致性,并非所有原始变量中存在的信息都可以立即看到。如果你使用像ff
这样动态检查域的选项,这反过来可能会恶化标签:
| ?- assert(clpfd:full_answer).
yes
| ?- X in 1..5, Xx #= (X+5-3)mod 5, X #\= 2.
clpfd:(_A#=X+2),
clpfd:(_A mod 5#=Xx),
X in{1}\/(3..5),
_A in{3}\/(5..7),
Xx in 0..4 ? ;
no
所以,Xx
的域名尚未更新为0..3
,但是:
| ?- X in 1..5, Xx #= (X+5-3)mod 5, X #\= 2, Xx = 4.
no
此外,非常智能的默认选项step
也会受到影响。
答案 1 :(得分:0)
你说好的解决方案将在可能的域上进行或多或少的均匀分布",我认为这意味着所有域值在解决方案向量中都会出现相似的次数。
在这种情况下,您可以引入一个辅助变量,以某种方式测量变量赋值的启发式质量。然后,首先标记此辅助变量,然后再标记其他变量,从而开始搜索。这样,可以首先检查潜在的好分配。
我没有SICStus,但这里有一个ECLiPSe示例,应该很容易适应。我已经引入了约束来计算主变量向量1
中不同域值ND
到Xs
的出现频率。然后计算变量Ns
的不平衡在变量Imbalance
中计算,这是首先标记的变量(从值0开始,即完美平衡):
:- lib(ic).
:- lib(ic_global).
main(NX, ND, Xs) :-
length(Xs,NX),
Xs::1..ND,
( for(I,1,ND), foreach(N,Ns), param(Xs) do
occurrences(I, Xs, N) % SICStus: count(I,Xs,#=,N)
),
sum(Ns) #= NX,
Imbalance #= max(Ns) - min(Ns),
Imbalance :: 0..NX,
labeling([Imbalance|Xs]).
示例运行显示了如何首先枚举平衡解决方案:
?- main(4, 2, Xs), writeln(Xs), fail.
[1, 1, 2, 2]
[1, 2, 1, 2]
[1, 2, 2, 1]
[2, 1, 1, 2]
[2, 1, 2, 1]
[2, 2, 1, 1]
[1, 1, 1, 2]
[1, 1, 2, 1]
[1, 2, 1, 1]
[1, 2, 2, 2]
[2, 1, 1, 1]
[2, 1, 2, 2]
[2, 2, 1, 2]
[2, 2, 2, 1]
[1, 1, 1, 1]
[2, 2, 2, 2]
No (0.01s cpu)
您的实际问题限制可以简单地添加到此模板中。