/* Global constraint assign_and_nvalues in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Cassign_and_nvalues.html """ Constraint assign_and_nvalues(ITEMS,RELOP,LIMIT) Purpose Given several items (each of them having a specific value that may not be initially fixed), and different bins, assign each item to a bin, so that the number n of distinct values in each bin satisfies the condition n RELOP LIMIT. Example ( < bin-2 value-3, bin-1 value-5, bin-2 value-3, bin-2 value-3, bin-2 value-4 >,<= ,2 ) Figure 4.24.1 depicts the solution corresponding to the example. The assign_and_nvalues constraint holds since for each used bin (i.e., namely bins 1 and 2) the number of distinct colours of the corresponding assigned items is less than or equal to the limit 2. """ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp,util. main => go. go ?=> Items = [[2,3], [1,5], [2,3], [2,3], [2,4]], % This is the only decision value Limit :: 0..10, Relop = #=<, Limit #= 2, assign_and_nvalues(Items, Relop, Limit, Bins), Vars = [Limit] ++ Bins, solve(Limit), println(relop=Relop), println(limit=Limit), fail, nl. go => true. % % Note: items must be fixed. % Also, Bins is output since it should be used in solve/1. % assign_and_nvalues(Items, Relop, Limit, Bins) => Len = Items.len, Low = min([Items[I,1] : I in 1..Len]), High = max([Items[I,1] : I in 1..Len]), Bins = new_array(High), Bins :: 0..Len, foreach(B in 1..High) if B < Low then Bins[B] #= 0 else nvalue(Bins[B], [Items[I,2] : I in 1..Len, Items[I,1] == B]), call(Relop, Bins[B],Limit) end end.