在 Mozart/Oz 中检查变量元组是否不能进一步受到约束

发布于 2024-11-06 10:22:01 字数 355 浏览 0 评论 0原文

您好,

这个想法可以通过一个例子来最好地给出:

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

莫扎特/奥兹国可以做到吗?

我想这样想。

循环中:

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

Greetings,

The idea can be best given with an example:

Suppose we have a vector vec(a:{FD.int 1#100} b:{FD.int 1#100} c:{FD.int 1#100}).
I want to be able to add constraints to this vector, until the point that every additional constraint I add
to it does not add any more information, e.g. does not constraint vec.a, vec.b and vec.c any further.

Is it possible to do it in Mozart/Oz?

I'd like to think it that way.

In a loop:

  1. Access the constraint store,
  2. Check whether it is changed
  3. Terminate if there is no change.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏末的微笑 2024-11-13 10:22:01

您可以使用 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}

You can check the state of a finite domain variable with the functions in the FD.reflect module. The FD.reflect.dom function seems especially useful in this context.

To get the current domain of every field in a record, you can map this function over records:

declare

fun {GetDomains Vec}
   {Record.map Vec FD.reflect.dom}
end

The initial result in your example would be:

vec(a:[1#100] b:[1#100] c:[1#100])

Now you can compare the result of this function before and after adding constraints, to see if anything happens.

Two limitations:

  1. This will only work with constraints which actually change the domain of at least one variable. Some constraints change the constraint store but do not change any domains, for example an equality constraint with an unbound variable.
  2. Using reflection like this does not work well with concurrency, i.e. if constraints are added from multiple threads, this will introduce race conditions.

If you need an example on how to use the GetDomains function in a loop, let me know...

EDIT: With a hint from an old mailing list message, I came up with this general solution which should work with all types of constraints. It works by speculatively executing a constraint in a subordinate computation space.

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}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文