问候,
这个想法最好用一个例子来说明:
假设我们有一个向量vec(a:{FD.int 1#100} b:{FD.int 1#100} c:{FD.int 1#100})
。我希望能够向该向量添加约束,直到我添加到它的每个附加约束都不会添加任何更多信息,例如不添加约束vec.a
,vec.b
以及vec.c
任何进一步的信息。
有可能在莫扎特/奥兹中做到吗?
我愿意这样想。
在一个循环中:
- 访问约束存储,
- 检查是否改变
- 如果没有变化则终止。
问候,
这个想法最好用一个例子来说明:
假设我们有一个向量vec(a:{FD.int 1#100} b:{FD.int 1#100} c:{FD.int 1#100})
。我希望能够向该向量添加约束,直到我添加到它的每个附加约束都不会添加任何更多信息,例如不添加约束vec.a
,vec.b
以及vec.c
任何进一步的信息。
有可能在莫扎特/奥兹中做到吗?
我愿意这样想。
在一个循环中:
FD.reflect
您可以使用模块中的函数检查有限域变量的状态。该FD.reflect.dom
功能在这种情况下似乎特别有用。
要获取记录中每个字段的当前域,可以将此函数映射到记录:
declare
fun {GetDomains Vec}
{Record.map Vec FD.reflect.dom}
end
您的示例中的初始结果是:
vec(a:[1#100] b:[1#100] c:[1#100])
现在你可以比较这个函数在添加约束之前和之后的结果,看看有没有发生任何事情。
两个限制:
如果您需要有关如何GetDomains
在循环中使用该函数的示例,请告诉我...
编辑:根据旧邮件列表消息的提示,我想出了这个通用解决方案,它应该适用于所有类型的约束。它通过在从属计算空间中推测性地执行约束来工作。
declare
Vec = vec(a:{FD.int 1#100} b:{FD.int 1#100} c:{FD.int 1#100})
%% A number of constraints as a list of procedures
Constraints =
[proc {$} Vec.a <: 50 end
proc {$} Vec.b =: Vec.a end
proc {$} Vec.b <: 50 end
proc {$} Vec.a =: Vec.b end
]
%% Tentatively executes a constraint C (represented as a procedure).
%% If it is already entailed by the current constraint store, returns false.
%% Otherwise merges the space (and thereby finally executes the constraint)
%% and returns true.
fun {ExecuteConstraint C}
%% create a compuation space which tentatively executes C
S = {Space.new
proc {$ Root}
{C}
Root = unit
end
}
in
%% check whether the computation space is entailed
case {Space.askVerbose S}
of succeeded(entailed) then false
else
{Wait {Space.merge S}}
true
end
end
for C in Constraints I in 1..4 break:Break do
{System.showInfo "Trying constraint "#I#" ..."}
if {Not {ExecuteConstraint C}} then
{System.showInfo "Constraint "#I#" is already entailed. Stopping."}
{Break}
end
{Show Vec}
end
{Show Vec}