Dear Michal,

Here is a slightly different solution. It uses the inverse of your vector Pos, i.e., it gives the sequence of match numbers.

It also creates three intermediary vectors: the left and right color of each match after it has been possibly flipped, and the whole sequence of colors, where adjacent colors are equal two by two. We then use the propagator FD.element to link the sequence numbers with the colors in the sequence.

These intermediate variables provide better propagation, because it allows to represent explicitly information like: "the third match cannot have its left color equal to 2". If this occurs, it immediately restrict the possible values for the 2nd and 3rd matches in the sequence.

BTW, I have eliminated a symmetry that occurs in Filip's solution: when a match has two same colors, you never flip it. My solver find 20 solutions with only 40 failed nodes in the search tree.

Have fun,
raph
declare
%% 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))
%%
M = matches(match(0 1)
            match(1 0)
            match(0 2)
            match(2 2)
            match(2 0))
Num = {Width M}

proc {EqualTwoByTwo L}
   case L of X|Y|T then X=Y {EqualTwoByTwo T} else skip end
end

proc {Solver Sol}
   %% for each match, whether it is flipped, and its left and right
   %% color after the flip
   Flip={FD.tuple flip Num 0#1}
   Left={FD.tuple left Num 0#2}
   Right={FD.tuple right Num 0#2}

   %% sequence of match numbers (inverse of Pos)
   Seq={FD.tuple seq Num 1#Num}

   %% sequence of match colors
   ColSeq={FD.tuple col 2*Num 0#2}

   Vars = {FoldL {Map [Flip Left Right Seq ColSeq] Record.toList} Append nil}
in
   Sol = solution(seq:Seq flip:Flip)

   %% first define the flip of each match
   for I in 1..Num do
      match(A B) = M.I
   in
      if A==B then
         Flip.I = 0
         Left.I = Right.I = A
      else
         [Left.I Right.I] ::: [A B]
         {FD.distinct [Left.I Right.I]}
         Flip.I = (Left.I =: B)
      end
   end

   %% now define the sequence of matches
   {FD.distinct Seq}
   {EqualTwoByTwo {Record.toList ColSeq}.2}

   for I in 1..Num do
      thread
         %% the match number Seq.I has its left color in
         %% ColSeq.(2*I-1) and its right color in ColSeq.(2*I)
         {FD.element Seq.I Left ColSeq.(2*I-1)}
         {FD.element Seq.I Right ColSeq.(2*I)}
      end
   end

   {FD.distribute ff Vars}
end

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

Reply via email to