/* Mininum except 0 constraint in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Cminimum_except_0.html """ Constraint minimum_except_0​(MIN,​VARIABLES)​ Purpose MIN is the minimum value of the collection of domain variables VARIABLES, ignoring all variables that take 0 as value. Example (3, <3, 7, 6, 7, 4, 7>) (2, <3, 2, 0, 7, 2, 6>) (1000000, <0, 0, 0, 0, 0, 0>) The three examples of the minimum_except_0 constraint respectively hold since: * Within the first example, MIN is set to the minimum value 3 of the collection <3, 7, 6, 7, 4, 7>. * Within the second example, MIN is set to the minimum value 2 (ignoring value 0) of the collection <3, 2, 0, 7, 2, 6>. * Finally within the third example, MIN is set to the default value 1000000 since all items of the collection <0, 0, 0, 0, 0, 0> are set to 0. Remark The joker value 0 makes sense only because we restrict the variables of the VARIABLES collection to take non-negative values. """ min_except_0(X,MinVal) Snsures that MinVal is the minimum value in X and thus ignores all values of 0. Note: The feature of default value is not implemented. Instead there is a constraint to allow all 0s in the array if max(X) = 0 <=> min(X) = 0 (which is more natural given the use cases I've stumbled upon). 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 = 6, X = new_list(N), X :: 0..7, min_except_0(X,MinVal), % MinVal #= 2, % This give the unique solution % minVal = 0 and x = [0,0,0,0,0,0] % MinVal #= 0, Vars = X ++ [MinVal], solve(Vars), println(x=X), println(minVal=MinVal), nl, fail, nl. go => true. % % Variant: Require that there must be at least % one value > 0 % go2 ?=> N = 6, X = new_list(N), X :: 0..7, % Allow all 0s min_except_0_2(X,MinVal), % MinVal #= 2, % This give no solution since we require at % least one value > 0 % MinVal #= 0, solve(X), println(x=X), println(minVal=MinVal), nl, fail, nl. go2 => true. % % Ensure that the minumum value of X is MinVal. % The only case MinVal = 0 is when MaxVal is 0, % and the check for this is why we use MaxVal as well. % min_except_0(X,MinVal) => Len = X.length, element(_,X,MinVal), % MinVal #= X[I], MaxVal #= max(X), foreach(J in 1..Len) MinVal #=< X[J] #\/ X[J] #= 0 end, MaxVal #= 0 #<=> MinVal #= 0. % % Ensure that the minumum value (> 0) is MinVal. % This requires that there are at least one value > 0. min_except_0_2(X,MinVal) => Len = X.length, between(1,Len,I), MinVal #= X[I], foreach(J in 1..Len) MinVal #=< X[J] #\/ X[J] #= 0 end, MinVal #> 0.