/* Global constraint distribute in Picat. Decomposition of global constraint distribute. From MiniZinc globals.mzn: """ Requires that 'card[i]' is the number of occurences of 'value[i]' in 'base'. """ Model created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. /* Solution: card[4,1,1,1] value[6,7,8,9] base[6,7,6,8,6,9,6] */ main => go. go => % This test is from MiniZinc's testcases. Len = 4, Card = new_list(Len), Card :: 1..10, Value = new_list(Len), Value :: 1..10, Base = new_list(7), Base :: 1..10, % test values Card = [4, _, 1, _], Value = [_, 7, 8, _], Base = [_, 7, 6, 8, 6, 9, _], distribute(Card, Value, Base), Vars = Card ++ Value ++ Base, solve([ff],Vars), writeln(card=Card), writeln(value=Value), writeln(base=Base), nl. % % No initial values of Card and Value % go2 ?=> Len = 4, Card = new_list(Len), Card :: 1..10, Value = new_list(Len), Value :: 1..10, Base = new_list(7), Base :: 1..10, % test values % Card = [4, _, 1, _], % Value = [_, 7, 8, _], Base = [_, 7, 6, 8, 6, 9, _], distribute(Card, Value, Base), Vars = Card ++ Value ++ Base, solve([ff],Vars), writeln(card=Card), writeln(value=Value), writeln(base=Base), nl, fail. go2 => true. % % (This comment is from the ECLiPSe model): % hakank: Compared to the Comet model, I require that Value are % distinct, but not ordered and not the complete range of values % (these two requirements seems to be common in the implementations of % the global cardinality constraint). % distribute(Card, Value, Base) => % Card and Value must have the same length CardLen = length(Card), CardLen = length(Value), BaseLen = length(Base), all_different(Value), foreach(I in 1..CardLen) Sum #= sum([(ValueI #= BaseJ) : J in 1..BaseLen, element(I,Value,ValueI), element(J,Base,BaseJ)]), element(I,Card,Sum) end.