2

问候,

这个想法最好用一个例子来说明:

假设我们有一个向量vec(a:{FD.int 1#100} b:{FD.int 1#100} c:{FD.int 1#100})。我希望能够向该向量添加约束,直到我添加到它的每个附加约束都不会添加任何更多信息,例如不添加约束vec.avec.b以及vec.c任何进一步的信息。

有可能在莫扎特/奥兹中做到吗?

我愿意这样想。

在一个循环中:

  1. 访问约束存储,
  2. 检查是否改变
  3. 如果没有变化则终止。
4

1 回答 1

2

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])

现在你可以比较这个函数在添加约束之前和之后的结果,看看有没有发生任何事情。

两个限制:

  1. 这仅适用于实际更改至少一个变量的域的约束。一些约束会更改约束存储但不会更改任何域,例如具有未绑定变量的等式约束。
  2. 像这样使用反射不适用于并发,即如果从多个线程添加约束,这将引入竞争条件。

如果您需要有关如何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}
于 2011-05-08T18:51:21.413 回答