/* Global constraint open_among in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Copen_among.html """ Constraint open_among(S,NVAR,VARIABLES,VALUES) Purpose Let V be the variables of the collection VARIABLES for which the corresponding position belongs to the set S. NVAR is the number of variables of V that take their value in VALUES. Example ( {2,3,4,5}, % S 3, % NVAR <8,5,5,4,1>,% VARIABLES <1,5,8> % VALUES ) The open_among constraint holds since within the last four values (i.e., S={2,3,4,5}) of <8,5,5,4,1> exactly 3 values belong to the set of values {1,5,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. % % The example above: get the NVAR. % go ?=> N = 5, MaxVal = 8, Variables = new_list(N), Variables :: 1..MaxVal, NVar :: 0..MaxVal, % var set of 1..n: s; S = new_list(N), S :: 0..1, Values = new_list(MaxVal), Values :: 0..1, Variables = [8,5,5,4,1], % 1 2 3 4 5 S = [0,1,1,1,1], % the set {2,3,4,5} % 1 2 3 4 5 6 7 8 Values = [1,0,0,0,1,0,0,1], % {1,5,8} % NVar #= 3, open_among(S, NVar, Variables, Values), Vars = Variables ++ S ++ Values ++ [NVar], solve(Vars), println(variables=Variables), % println(s=S), println(s=[I : I in 1..S.len, S[I] == 1]), % println(values=Values), println(values=[I : I in 1..Values.len, Values[I] == 1]), println(nvar=NVar), nl, fail, nl. go => true. % % Let's play a little by letting, S and Values free. % go2 ?=> N = 5, MaxVal = 8, Variables = new_list(N), Variables :: 1..MaxVal, NVar :: 0..MaxVal, % var set of 1..n: s; S = new_list(N), S :: 0..1, Values = new_list(MaxVal), Values :: 0..1, Variables = [8,5,5,4,1], % 1 2 3 4 5 % S = [0,1,1,1,1], % the set {2,3,4,5} % 1 2 3 4 5 6 7 8 % Values = [1,0,0,0,1,0,0,1], % {1,5,8} NVar #= 3, open_among(S, NVar, Variables, Values), Vars = Variables ++ S ++ Values ++ [NVar], solve(Vars), println(variables=Variables), % println(s=S), println(s=[I : I in 1..S.len, S[I] == 1]), % println(values=Values), println(values=[I : I in 1..Values.len, Values[I] == 1]), println(nvar=NVar), nl, fail, nl. go2 => true. open_among(S, NVar,Variables,Values) => NVar #= sum([ S[I] #= 1 #/\ B #= 1 : I in 1..Variables.len, B :: 0..1, element(Variables[I],Values,B)]).