/* Global constraint same_and_global_cardinality in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Csame_and_global_cardinality.html """ Constraint same_and_global_cardinality(VARIABLES1,VARIABLES2,VALUES) Purpose The variables of the VARIABLES2 collection correspond to the variables of the VARIABLES1 collection according to a permutation. In addition, each value VALUES[i].val (1i|VALUES|) should be taken by exactly VALUES​[i].noccurrence variables of the VARIABLES1 collection. Example ( <1,9,1,5,2,1>, <9,1,1,1,2,5>, < val-1 noccurrence-3, val-2 noccurrence-1, val-5 noccurrence-1, val-7 noccurrence-0, val-9 noccurrence-1 > ) The same_and_global_cardinality constraint holds since: * The values 1, 9, 1, 5, 2, 1 assigned to VARIABLES1 correspond to a permutation of the values 9, 1, 1, 1, 2, 5 assigned to VARIABLES2. * The values 1, 2, 5, 7 and 6 are respectively used 3, 1, 1, 0 and 1 times. """ Note: There are 4 unique values in Variables1 and Variables2 and the the Values array is of length 5. Hence there is a value (here 7) that has occurrence = 0. This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go => N = 6, M = 5, Variables1 = new_list(N), Variables1 :: 0..9, Variables2 = new_list(N), Variables2 :: 0..9, Values = new_array(M,2), Values :: 0..9, Variables1 = [1,9,1,5,2,1], Variables2 = [9,1,1,1,2,5], % Values = {{1,3}, % {2,1}, % {5,1}, % {7,0}, % {9,1}}, % Values = {{1,_}, % {2,_}, % {5,_}, % {7,_}, % {9,_}}, same_and_global_cardinality(Variables1,Variables2,Values), Vars = Variables1 ++ Variables2 ++ Values.vars, solve(Vars), println(variables1=Variables1), println(variables2=Variables2), println("Values:"), foreach(Row in Values) println(Row.to_list) end, nl, fail, nl. % % See same.pi % % % same(VARIABLES1, VARIABLES2) % same_and_global_cardinality(Variables1, Variables2,Values) => % Ensure that all values in Variables1 are in Values foreach(V in Variables1) sum([V #= Values[I,1] : I in 1..Values.len]) #= 1 end, foreach(V in Variables2) sum([V #= Values[I,1] : I in 1..Values.len]) #= 1 end, global_cardinality_table(Variables1,Values), global_cardinality_table(Variables2,Values). % See global_cardinality_table.pi global_cardinality_table(Variables,Values) => % sanity/symmetry increasing_strict([Values[J,1] : J in 1..Values.len]), foreach(I in 1..Values.len) Values[I,2] #= sum([Variables[J] #= Values[I,1] : J in 1..Variables.len]) end.