Hi Michal,

    /*    FIXME

        {For 1 NUM-1 1 proc {$ I}

% The trailing edge of a placed match is the same the leading edge
            % of the next match.
            M.(Pos.I).(2 - Flip.I) =: M.(Pos.(I+1)).(1 + Flip.(I+1))

        end}

*/
I suppose that the statement(equation) in the for-loop is what you think should hold when a solution is found. (I did not analyze the this equation however...) But what should this statement do when the solution is under construction, i.e. when the variables "Pos.I", "Flip.I" etc. are not numbers, but (e.g.) intervals? Clearly, in such situation, the equation does not have sense, and so can not help in constructing the solution (so the solver ends up trying many solutions because of no propagation).

Technically, you should understand that the constraint-posting statement "A =: B" translates internally to
 {FD.sumC [1 ~1] [A B] '=:' 0}
i.e. a procedure call (see docs for FD.sumC) with some arguments which have to be passed to it (they can be non-determined FDInt variables). The problem in your case is that neither "A" or "B" can be evaluated at the point when FD.sumC is called (e.g. "M.(Pos.I)" is trying to access feature "Pos.I" of "M", but "Pos.I" is undetermined, so the expression blocks). The advice here is to rework your model to avoid the need for such constraints.

To be a bit more constructive, here is a hack that gets you a quick and dirty solution (I only changed the for loop and the last statement):
local
  %% Our matches, where each match has different coloured ends.
  %% Different colours represented by different numbers.
  %% Note that the matches are given in an order that provides a solution:
%% 0---1 1---0 0---2 2---2 2---0 %%
  %% This is equavalent to the solution (see code):
  %%    solution(flip:flip(0 0 0 0 0) pos:pos(1 2 3 4 5))
  %%
  %% Another solution might be:
  %%    1---0 0---2 2---2 2---0 0---1
  %%
  %% This is equavalent to the solution (see code):
  %%    solution(flip:flip(1 1 0 0 0) pos:pos(1 5 2 3 4))
  %%
  NUM = 5
  M = matches(
         match(0 1)
         match(1 0)
         match(0 2)
         match(2 2)
         match(2 0)
         )
  proc {Solve Root}
       % Which numbered match is in each position of the line.
     Pos = {MakeTuple pos NUM}
       % Whether we rotated the match or not
     Flip = {MakeTuple flip NUM}
  in
     %% Post the solution
     Root = solution(pos:Pos flip:Flip)
     %% Initialize the variable domains.
     Pos = {FD.tuple pos NUM 1#NUM}
     Flip = {FD.tuple flip NUM 0#1}
     for I in 1..NUM-1 do
        %% The trailing edge of a placed match is the same the leading edge
        %% of the next match.
        thread
           M.(Pos.I).(2 - Flip.I) =: M.(Pos.(I+1)).(1 + Flip.(I+1))
        end
     end
     %% We can only place each match once.
     {FD.distinct Pos}
     {FD.distribute ff Pos}
     {FD.distribute ff Flip}
end in
  {ExploreAll Solve}
end

(Note how I use "%%" instead of "%" to prevent indentation problems in emacs.) The thing that makes the difference is that the blocking statements "A =: B" run in separate threads and wait for all the needed variables to get determined (which happens during the FD.distribute calls). So you have a working example of the "generate-and-test" paradigm, which is not constraint programming (no constraint propagation takes place here). See the explorer tree - there are 720 failures and 40 solutions. With good constraint propagation, you could perhaps avoid failures at all.

Cheers,
Filip

_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to