2

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.
mhourdakis
  • 179
  • 8

1 Answers1

2

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}
wmeyer
  • 3,426
  • 1
  • 18
  • 26
  • Thanks for the answer. Unfortunately, I need the whole constraint store and not just the domains. For e.g, if I have two constraints `a=:b` and `b=:c`, be able to know if a new constraint `a=:c` or even again the constraint `a=:b` will not constraint my variables any further. Concurrency is not an issue. – mhourdakis May 10 '11 at 07:02
  • Thank you very much. This is exactly what I was asking for. – mhourdakis May 11 '11 at 10:16