/* Global constraint global_cardinality_no_loop in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_cardinality_no_loop.html """ Constraint global_cardinality_no_loop(NLOOP,VARIABLES,VALUES) ... Purpose VALUES[i].noccurrence (1=, 〈val-1 noccurrence-1, val-5 noccurrence-0, val-6 noccurrence-1> ) The global_cardinality_no_loop constraint holds since: * Values 1, 5 and 6 are respectively assigned to the set of variables {VARIABLES[2].var} (i.e., 1 occurrence of value 1), {}(i.e., no occurrence of value 5) and {VARIABLES[4].var} (i.e., 1 occurrence of value 6). Observe that, due to the definition of the constraint, the fact that VARIABLES[1].var is assigned to 1 is not counted. * In addition the number of assignments of the form VARIABLES[i].var=i(i∈[1, 4]) is equal to NLOOP=1. Usage Within the context of the tree constraint the global_cardinality_no_loop constraint allows to model a minimum and maximum degree constraint on each vertex of our trees. """ 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, % number of variables M = 3, % number of values Variables = new_list(N), Variables :: 1..8, Values = new_array(M,2), Values :: 0..8, NLoop :: 0..N, Values = { {1,1}, {5,0}, {6,1}}, Variables = [1,1,8,6], global_cardinality_no_loop(NLoop, Variables, Values), Vars = Variables ++ Values, println(vars=Vars), solve(Vars), println(variables=Variables), println(values=Values), println(nloop=NLoop), nl, fail, nl. go => true. global_cardinality_no_loop(NLoop,Variables,Values) => M = Values[1].len, N = Variables.len, foreach(I in 1..M) Values[I,2] #= sum([Variables[J]#=Values[I,1] : J in 1..N, I!=J]) end, NLoop #= sum([Variables[J] #= J : J in 1..N])