I am new to Constraint programming and to MiniZinc
I want to define the constraints for the following problem. Can you help me
3 Arrays F1,F2 and F3 have child elements (F1a,F1b) ; (F2a,F2b,F2c) ; (F3a,F3b,F3c,F3d) respectively.
I need to define constraints with below rules
*Need to Pick 1 element from each Family F1 and F3 with F2b included in all possible solutions
F2b and F1a cannot coexist in a solution
F2b and F3b cannot coexist in a solution
F1a F2b and F3a cannot coexist in a solution
I need to find possible solutions
Thanks
My Actual Problem has 650 Arrays like F1,F2,... and have 75000 constraints like what i stated. Will I run into performance issue if extend the same logic given below by Alex/Dekker ?. what should be rigth approach to solve problems of this magnitude
THanks
The idea that a certain number of elements has to be picked in an array of elements can be represented in many different ways. If we are forced to pick a certain number, then a constraint using the count global is the best way to do so. (However, picking at least one element is better done using the exists function, which represents a logical or operation.)
The coexistance of elements is also represented by the counting of the number of activated elements. If coexistance is not allowed, then only 1 can be activated at a time. In the situation where we are reasoning about only two elements, there is a unique scenario where we can just exclude the usage of both elements at the same time using the /\ operator.
Your model could thus become:
array[1..2] of var bool: F1;
array[1..3] of var bool: F2;
array[1..4] of var bool: F3;
constraint count(F1) == 1; % Pick 1 element from F1
constraint count(F2) == 1; % Pick 1 element from F2
constraint count(F3) == 1; % Pick 1 element from F3
constraint not (F1[1] /\ F2[2]); % F2b and F1a cannot coexist in a solution
constraint not (F2[2] /\ F3[2]); % F2b and F3b cannot coexist in a solution
constraint count([F1[1], F2[2], F3[1]]) <= 1; % F1a F2b and F3a cannot coexist in a solution
This can be expressed using the sum function and a user-defined predicate:
array[1..2] of var bool: F1;
array[1..3] of var bool: F2;
array[1..4] of var bool: F3;
% assuming that exactly one has to be picked
constraint sum(F1) == 1; % same as (F1[1]+F1[2]) == 1
constraint sum(F2) == 1;
constraint sum(F3) == 1;
predicate coexist(array[int] of var bool: x ) =
sum(x) > 1;
constraint not coexist([F1[1], F2[2]]);
constraint not coexist([F2[2], F3[2]]);
constraint not coexist([F1[1], F2[2], F3[1]]);
Related
I need some help with the following case.
let say I have the following code:
enum x= {p,k,m};
enum y= {t1,t2,t3,t4};
array[y] of set of int:against=[{1,3,6},{3,3,6},{6,1,1},{6,3,6}];
array[x] of set of int:attack=[{3,3,6},{6,2,2},{3,1,3}];
array[x] of set of y: NodesD=[{t2,t3},{t2,t3,t4},{t1,t4}];
array[x]of var y: Select;
constraint forall(p in x)(Select[p] in NodesD[p]);
So for each enum of x I should select only on enum of Y. Then I want to select the one that suitable for each set of attack in the following way:
let take the first enum of x {p} which have two possible chooses of y{t2,t3}, so I want to do like this: t2={1,1,6}, t3={6,3,3} so I want to subtract each value in x attack[] {3,3,6} from each value in y against[] and the sum up the results:
{1,1,6}-
{3,3,6}
-----------
{-2,-2,0} then sum them which is equal to -4
then do the same with t2
{6,3,3}-
{3,3,6}
------------
{3,0,-3} which is equal to 0
and in this case, t3 which is equal to 0 is better than t2=-4.
I want to do the same for each enum x and Maximize the power.
I tried to do it in the following way but it does not work
var int: power = sum(p in x)(card(against[Select[p]])-(card(attack[p])*Select[p]) );
solve maximize power ;
Any help or hint please,:)
If you want to make an element by element comparison a matrix is better suited for that than an array of sets, because that way you ensure that both matrixes have the same width and also the syntax is less cumbersome, so instead of summing with an index from 1 to the cardinality of the set you use a different set to sum over the columns of the matrix.
You could calculate the sum of the element wise difference of the sets with
sum(i in 1..min(card(set_A),card(set_B)))(set_A[i] - set_B[i]);
using the min to be sure that you only iterate over the smallest set and don't access elements that don't exist.
But written like this is cleaner in my opinion, basically, change the {} of sets for | to delimit the rows of the matrix in attack and against, and add a new variable that will index the columns of the matrix, I called it FRONTS in this example, so you pick an X and compare the difference of forces over the different battlefronts.
enum X = {p,k,m};
enum y = {t1,t2,t3,t4};
set of int : FRONTS = 1..3;
array[y,FRONTS] of int : against=[|1,3,6|3,3,6|6,1,1|6,3,6|];
array[X,FRONTS] of int : attack=[|3,3,6|6,2,2|3,1,3|];
array[X] of set of y : nodesD=[{t2,t3},{t2,t3,t4},{t1,t4}];
array[X] of var y : select;
var int: power;
constraint forall(p in X)(select[p] in nodesD[p]);
constraint power = sum(p in X)( sum(i in FRONTS)( against[ select[p], i] - attack[ p, i ] ) );
solve maximize power;
output [show(select) ++ " = " ++ show(power)];
What is Channeling in MiniZinc? Can you provide an simple example to explain Channeling? Finally, What is Inverse?
Both are used to establish a bidirectional relationship between two arrays.
Let f be an array with index_set(f) equal to 1..10 and values in 81..90.
Then f can be seen as a mapping --a.k.a. a function-- from the set of values 1..10 to the set of values 81..90.
Inverse.
predicate inverse(array [int] of var int: f,
array [int] of var int: invf)
This constraint says that if f is a function mapping an index i to a value j, then invf is a function mapping an index j to a value i (and vice-versa). In other words, the array invf is indexed with the values in f and it yields the position in f of the each value contained in f.
int_set_channel.
predicate int_set_channel(array [int] of var int: x,
array [int] of var set of int: y)
The constraint says that if x is a function mapping an index i to a given set j, then the value i is contained in the set at index j in y (and vice-versa). This is the exact same thing as the inverse constraint, only that y is an array of sets rather than an array of values.
In my experience, chanelling constraints are useful to move from one problem view to another, so as to express other constraints in the most natural --and efficient-- way. This type of constraints may use the global constraints described above, or expressed using basic language constructs. See, for instance, carseq.mzn.
For more useful information and a concrete example, see Section 2.6.6.1 of the docs.
Example:
int: n;
array [1..n] of var 1..n: q; % queen is column i is in row q[i]
include "alldifferent.mzn";
constraint alldifferent(q); % distinct rows
constraint alldifferent([ q[i] + i | i in 1..n]); % distinct diagonals
constraint alldifferent([ q[i] - i | i in 1..n]); % upwards+downwards
include "lex_lesseq.mzn";
% Alternative Boolean model:
% Map each position i,j to a Boolean telling us whether there is a queen at i,j
array[1..n,1..n] of var bool: qb;
% Channeling constraint
constraint forall (i,j in 1..n) ( qb[i,j] <-> (q[i]=j) );
% Lexicographic symmetry breaking constraints
constraint
lex_lesseq(array1d(qb), [ qb[j,i] | i,j in 1..n ])
/\ lex_lesseq(array1d(qb), [ qb[i,j] | i in reverse(1..n), j in 1..n ])
/\ lex_lesseq(array1d(qb), [ qb[j,i] | i in 1..n, j in reverse(1..n) ])
/\ lex_lesseq(array1d(qb), [ qb[i,j] | i in 1..n, j in reverse(1..n) ])
/\ lex_lesseq(array1d(qb), [ qb[j,i] | i in reverse(1..n), j in 1..n ])
/\ lex_lesseq(array1d(qb), [ qb[i,j] | i,j in reverse(1..n) ])
/\ lex_lesseq(array1d(qb), [ qb[j,i] | i,j in reverse(1..n) ])
;
% search
solve :: int_search(q, first_fail, indomain_min)
satisfy;
output [ if fix(q[j]) == i then "Q" else "." endif ++
if j == n then "\n" else "" endif | i,j in 1..n]
Here, the channeling constraints put in relation the two views of the n-queens problem contained in the model. The first view q is uni-dimensional, and tells the row position of the queen within each column. The second view qb is bi-dimensional, and tells which tile of the chessboard is occupied by some queen. The first view is great for solving the placement part of the problem. the second view is great for applying symmetry breaking constraints.
I'm working on a toy problem to learn minizinc. Take an array (hardcoded to size 3 for now) of values between 0 and 9 and find the combinations where the sum is equal to the product.
par int: n = 3; % hardcode for now
array[1..n] of var 0..9: x;
constraint sum(x) != 0;
constraint sum(x) == product(x);
output["\(x)"];
Outputs
[2, 3, 1]
----------
This works as expected, however, next I try to constrain so that the values must increase in order.
First I tried this:
constraint forall(i in x)(
x[i] <= x[i+1]
);
This was UNSATISFIABLE. I was thinking this could be due to the i+1 index being greater than the size of the array for the last item. So I added a condition to the forall to prevent the index of the last item being out of bounds:
constraint forall(i in x)(
i < n /\ x[i] <= x[i+1]
);
However, this was also UNSATISFIABLE.
Something is amiss with my conceptual understanding. What is wrong with my approach?
PROBLEM(s).
In general, the constraint is fine. In the context of this example, however, it is inconsistent. Let's see why this is the case.
We know that the solution must include 1, 2, 3, thus, we can infer that the constraint
constraint forall (i in x) (
x[i] <= x[i+1]
);
is "equivalent" to
constraint x[1] <= x[2];
constraint x[2] <= x[3];
constraint x[3] <= x[4];
for which mzn2fzn reports the following issue:
WARNING: undefined result becomes false in Boolean context
(array access out of bounds)
./t.mzn:12:
in binary '<=' operator expression
in array access
When the same constraint is written without hard-encoded index values, the mzn2fzn compiler is unable to detect the inconsistency before the solver is invoked. However, the semantics of the access out of bounds is still the same (i.e. false) at run-time, so the formula becomes unsatisfiable.
The constraint
constraint forall(i in x)(
i < n /\ x[i] <= x[i+1]
);
augments the previous constraint with the requirement that i must be smaller than n. This is clearly false for i = 3, so there is one more inconsistency in the model. The constraint would be correct if you used the implication symbol -> instead of the (logical) and symbol /\.
SOLUTION(s).
First, let me set aside a possible misunderstanding of the language. The comprehension i in x, which you used in your model, refers to the elements inside the array x, and not to the index set of x. In this particular case the solution and the index set of x contain the same values, so it does not cause an inconsistency. However, this is not true in general, so it's better to use the function index_set() as follows:
constraint forall(i, j in index_set(x) where i < j)(
x[i] <= x[j]
);
example:
par int: n = 3; % hardcode for now
array[1..n] of var 0..9: x;
constraint sum(x) != 0;
constraint sum(x) == product(x);
constraint forall(i, j in index_set(x) where i < j)(
x[i] <= x[j]
);
solve satisfy;
output["\(x)"];
yields
~$ mzn2fzn test.mzn
~$ optimathsat -input=fzn < test.fzn
x = array1d(1..3, [1, 2, 3]);
----------
A more elegant solution is to use the following global constraint, which is mentioned in the documentation (v. 2.2.3) of MiniZinc:
predicate increasing(array [int] of var bool: x)
predicate increasing(array [int] of var int: x)
predicate increasing(array [int] of var float: x)
The predicate admits duplicate values in the array, that is, it enforces a non-strict increasing order (if that is needed, combine increasing with distinct).
The predicate is contained in the file increasing.mzn. However, people normally include the file globals.mzn instead, so as to have access to all predicates at once.
example:
include "globals.mzn";
par int: n = 3; % hardcode for now
array[1..n] of var 0..9: x;
constraint sum(x) != 0;
constraint sum(x) == product(x);
constraint increasing(x);
solve satisfy;
output["\(x)"];
yields
~$ mzn2fzn t.mzn
~$ optimathsat -input=fzn < t.fzn
x = array1d(1..3, [1, 2, 3]);
----------
What I have is a vector (n = 4 in the example):
x = '0123';
What I want is a vector y of the same size of x and with the same elements as in x in different order:
y = ['0123'; '0132'; '0213'; '0231'; '0312'; '0321'; '1023'; '1032'; '1203'; '1302'; '2013'; '2031'; '2103'; '2301'];
y(ceil(rand * numel(y(:, 1))), :)
i.e. a permutation such that each element in y is allowed to randomly change no more than k positions with respect to its original position in x (k = 2 in the example). The probability distribution must be uniform (i.e. each permutation must be equally likely to occur).
An obvious but inefficient way to do it is of course to find a random unconstrained permutation and check ex post whether or not this happens to respect the constraint. For small vectors you can find all the permutations, delete those that are not allowed and randomly pick among the remaining ones.
Any idea about how to do the same more efficiently, for example by actually swapping the elements?
Generating all the permutations can be done easily using constraint programming. Here is a short model using MiniZinc for the above example (note that we assume that x will contain n different values here):
include "globals.mzn";
int: k = 2;
int: n = 4;
array[1..n] of int: x = [0, 1, 2, 3];
array[1..n] of var int: y;
constraint forall(i in 1..n) (
y[i] in {x[i + offset] | offset in -min(k, i-1)..min(k, n-i)}
);
constraint all_different(y);
solve :: int_search(y, input_order, indomain_min, complete)
satisfy;
output [show(y)];
In most cases, constraint programming systems have the possibility to use a random search. However, this would not give you a uniform distribution of the results. Using CP will however generate all valid permutations more efficiently than the naive method (generate and test for validity).
If you need to generate a random permutation of your kind efficiently, I think that it would be possible to modify the standard Fisher-Yates shuffle to handle it directly. The standard algorithm uses the rest of the array to choose the next value from, and chooses the value with a probability distribution that is uniform. It should be possible to keep a list of only the currently valid choices, and to change the probability distribution of the values to match the desired output.
I don't see any approach other than the rejection method that you mention. However, instead of listing all allowed permutations and then picking one, it's more efficient to avoid that listing. Thus, you can randomly generate a permutation, check if it's valid, and repeat if it's not:
x = '0123';
k = 2;
n = numel(x);
done = 0;
while ~done
perm = randperm(n);
done = all( abs(perm-(1:n)) <= k ); %// check condition
end
y = x(perm);
I have encountered a surprisingly challenging problem arranging a matrix-like (List of Lists) of values subject to the following constraints (or deciding it is not possible):
A matrix of m randomly generated rows with up to n distinct values (no repeats within the row) arrange the matrix such that the following holds (if possible):
1) The matrix must be "lower triangular"; the rows must be ordered in ascending lengths so the only "gaps" are in the top right corner
2) If a value appears in more than one row it must be in the same column (i.e. rearranging the order of values in a row is allowed).
Expression of the problem/solution in a functional language (e.g. Scala) is desirable.
Example 1 - which has a solution
A B
C E D
C A B
becomes (as one solution)
A B
E D C
A B C
since A, B and C all appear in columns 1, 2 and 3, respectively.
Example 2 - which has no solution
A B C
A B D
B C D
has no solution since the constraints require the third row to have the C and D in the third
column which is not possible.
I thought this was an interesting problem and have modeled a proof-of-concept-version in MiniZinc (a very high level Constraint Programming system) which seems to be correct. I'm not sure if it's of any use, and to be honest I'm not sure if it's powerful for very largest problem instances.
The first problem instance has - according to this model - 4 solutions:
B A _
E D C
B A C
----------
B A _
D E C
B A C
----------
A B _
E D C
A B C
----------
A B _
D E C
A B C
The second example is considered unsatisfiable (as it should).
The complete model is here: http://www.hakank.org/minizinc/ordering_a_list_of_lists.mzn
The basic approach is to use matrices, where shorter rows are filled with a null value (here 0, zero). The problem instance is the matrix "matrix"; the resulting solution is in the matrix "x" (the decision variables, as integers which are then translated to strings in the output). Then there is a helper matrix, "perms" which are used to ensure that each row in "x" is a permutation of the corresponding row in "matrix", done with the predicate "permutation3". There are some other helper arrays/sets which simplifies the constraints.
The main MiniZinc model (sans output) is show below.
Here are some comments/assumptions which might make the model useless:
this is just a proof-of-concept model since I thought it was an interesting
problem.
I assume that the rows in the matrix (the problem data) is already ordered
by size (lower triangular). This should be easy to do as a preprocessing step
where Constraint Programming is not needed.
the shorter lists are filled with 0 (zero) so we can work with matrices.
since MiniZinc is a strongly typed language and don't support
symbols, we just define integers 1..5 to represent the letters A..E.
Working with integers is also beneficial when using traditional
Constraint Programming systems.
% The MiniZinc model (sans output)
include "globals.mzn";
int: rows = 3;
int: cols = 3;
int: A = 1;
int: B = 2;
int: C = 3;
int: D = 4;
int: E = 5;
int: max_int = E;
array[0..max_int] of string: str = array1d(0..max_int, ["_", "A","B","C","D","E"]);
% problem A (satifiable)
array[1..rows, 1..cols] of int: matrix =
array2d(1..rows, 1..cols,
[
A,B,0, % fill this shorter array with "0"
E,D,C,
A,B,C,
]);
% the valid values (we skip 0, zero)
set of int: values = {A,B,C,D,E};
% identify which rows a specific values are.
% E.g. for problem A:
% value_rows: [{1, 3}, {1, 3}, 2..3, 2..2, 2..2]
array[1..max_int] of set of int: value_rows =
[ {i | i in 1..rows, j in 1..cols where matrix[i,j] = v} | v in values];
% decision variables
% The resulting matrix
array[1..rows, 1..cols] of var 0..max_int: x;
% the permutations from matrix to x
array[1..rows, 1..cols] of var 0..max_int: perms;
%
% permutation3(a,p,b)
%
% get the permutation from a b using the permutation p.
%
predicate permutation3(array[int] of var int: a,
array[int] of var int: p,
array[int] of var int: b) =
forall(i in index_set(a)) (
b[i] = a[p[i]]
)
;
solve satisfy;
constraint
forall(i in 1..rows) (
% ensure unicity of the values in the rows in x and perms (except for 0)
alldifferent_except_0([x[i,j] | j in 1..cols]) /\
alldifferent_except_0([perms[i,j] | j in 1..cols]) /\
permutation3([matrix[i,j] | j in 1..cols], [perms[i,j] | j in 1..cols], [x[i,j] | j in 1..cols])
)
/\ % zeros in x are where there zeros are in matrix
forall(i in 1..rows, j in 1..cols) (
if matrix[i,j] = 0 then
x[i,j] = 0
else
true
endif
)
/\ % ensure that same values are in the same column:
% - for each of the values
% - ensure that it is positioned in one column c
forall(k in 1..max_int where k in values) (
exists(j in 1..cols) (
forall(i in value_rows[k]) (
x[i,j] = k
)
)
)
;
% the output
% ...
I needed a solution in a functional language (XQuery) so I implemented this first in Scala due to its expressiveness and I post the code below. It uses a brute-force, breadth first style search for solutions. I'm inly interested in a single solution (if one exists) so the algorithm throws away the extra solutions.
def order[T](listOfLists: List[List[T]]): List[List[T]] = {
def isConsistent(list: List[T], listOfLists: List[List[T]]) = {
def isSafe(list1: List[T], list2: List[T]) =
(for (i <- list1.indices; j <- list2.indices) yield
if (list1(i) == list2(j)) i == j else true
).forall(_ == true)
(for (row <- listOfLists) yield isSafe(list, row)).forall(_ == true)
}
def solve(fixed: List[List[T]], remaining: List[List[T]]): List[List[T]] =
if (remaining.isEmpty)
fixed // Solution found so return it
else
(for {
permutation <- remaining.head.permutations.toList
if isConsistent(permutation, fixed)
ordered = solve(permutation :: fixed, remaining.tail)
if !ordered.isEmpty
} yield ordered) match {
case solution1 :: otherSolutions => // There are one or more solutions so just return one
solution1
case Nil => // There are no solutions
Nil
}
// Ensure each list has unique items (i.e. no dups within the list)
require (listOfLists.forall(list => list == list.distinct))
/*
* The only optimisations applied to an otherwise full walk through all solutions is to sort the list of list so that the lengths
* of the lists are increasing in length and then starting the ordering with the first row fixed i.e. there is one degree of freedom
* in selecting the first row; by having the shortest row first and fixing it we both guarantee that we aren't disabling a solution from being
* found (i.e. by violating the "lower triangular" requirement) and can also avoid searching through the permutations of the first row since
* these would just result in additional (essentially duplicate except for ordering differences) solutions.
*/
//solve(Nil, listOfLists).reverse // This is the unoptimised version
val sorted = listOfLists.sortWith((a, b) => a.length < b.length)
solve(List(sorted.head), sorted.tail).reverse
}