/* Global constraint open_global_cardinality in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Copen_global_cardinality.html """ Constraint open_global_cardinality(S,VARIABLES,VALUES) Purpose Each value VALUES[i].val(1<=i<=|VALUES|)should be taken by exactly VALUES[i].noccurrence variables of the VARIABLES collection for which the corresponding position belongs to the set S. Example ( {2,3,4}, <3,3,8,6>, ) The open_global_cardinality constraint holds since: * Values 3, 5 and 6 respectively occur 1, 0 and 1 times within the collection <3,3,8,6> (the first item 3 of <3,3,8,6> is ignored since value 1 does not belong to the first argument S={2,3,4} of the open_global_cardinality constraint). * No constraint was specified for value 8. """ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> N = 4, Variables = new_list(N), Variables :: 1..8, S = new_list(N), S :: 0..1, M = 3, Values = new_array(M,2), Values :: 0..6, Variables = [3,3,8,6], S = [0,1,1,1], % the set {2,3,4} % Values = {{3,1}, % {5,0}, % {6,1}}, Values = {{3,_}, {5,_}, {6,_}}, open_global_cardinality(S, Variables, Values), Vars = Variables ++ S ++ Values.vars, solve(Vars), println(variables=Variables), println(s=[I : I in 1..S.len, S[I] == 1]), println(variables_selection=[Variables[I] : I in 1..S.len, S[I] == 1]), foreach(Row in Values) println(Row) end, nl, fail, nl. go => true. % % Extend the Values with all 8 values % go2 ?=> N = 4, Variables = new_list(N), Variables :: 1..8, S = new_list(N), S :: 0..1, M = 8, Values = new_array(M,2), Values :: 0..8, Variables = [3,3,8,6], % S = [0,1,1,1], % the set {2,3,4} % Values = {{3,1}, % {5,0}, % {6,1}}, Values = {{1,_}, {2,_}, {3,_}, {4,_}, {5,_}, {6,_}, {7,_}, {8,_}}, open_global_cardinality(S, Variables, Values), Vars = Variables ++ S ++ Values.vars, solve(Vars), println(variables=Variables), println(s=[I : I in 1..S.len, S[I] == 1]), println(variables_selection=[Variables[I] : I in 1..S.len, S[I] == 1]), foreach(Row in Values) println(Row) end, nl, fail, nl. go2 => true. open_global_cardinality(S,Variables,Values) => foreach(I in 1..Values.len) Values[I,2] #= sum([S[J] #= 1 #/\ Variables[J] #= Values[I,1] : J in 1..Variables.len]) end.