What is Channeling in MiniZinc? Can you provide an simple example to explain Channeling? Finally, What is Inverse? - minizinc

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.

Related

Defining constraints in MiniZinc

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]]);

Creating a graph using maple

What is the (maple) code for the following graph: The vertices are the elements of M_2(\mathbb{Z}_2) and two vertices A and B are adjacent if and only if AB = I.
If you know the code or any references, please let me know.
Start step by step. Think what you need. You need to define your set of vertices and then set of edges. First with the set of vertices. You want all matrices of size 2 by 2 with binary entries, it means a finite set of 16 elements. Matrices are defined in Maple. You can define a matrix with entries (1,1), (1,2), (2,1) and (2,2) beign a, b, c and d respectively in one of the following two ways.
M := Matrix([ [a, b], [c, d] ]);
which means row-wise, or column-wise as in below.
M := < < a, b > | < c, d > >;
Now, I want to put them in an ordered collection, so I choose list data structure. You can make an empty list and then add the matrices one by one with for-loops to it, but since lists are immutable data structures, I would use Array instead and then convert it to a list in the end. Another way is to use list-comprehension using seq. Here is how I do it.
V := [ seq( seq( seq( seq( Matrix([ [a, b], [c, d] ]), d = 0..1 ), c = 0..1 ), b = 0..1 ), a = 0..1 ) ];
And you will see a beautiful list with all 16 matrices that you expect.
Now for the set of edges. Your set is small, so going for a command to find the inverse is not really necessary, just have a nested for-loop to actually multiply matrices A and B and then compare if the result is the identity matrix or not. Remember that in Maple = is not a mathematical equality comparison. To check whether two matrices are equal, use the Equal command in the LinearAlgebra package. So here is how I do it.
E := Array([]); # empty 1-dimensional array
for A in V do
for B in V do
if LinearAlgebra:-Equal( ( A . B mod 2 ) , Matrix([ [1, 0], [0, 1] ]) ) then
ArrayTools:-Append( E, [A, B] ): # modifying E itself instead of defining new one.
end if:
end do:
end do:
Now if you ask to see E, you will see 6 ordered pairs of matrices that their product is the the identity matrix. Note the use of mod to have remain in GF(2) (binary field). If you do the multiplications and additions in Z and then take mod 2, the result will be the same as if you were doing the multiplications and additions in GF(2) from the beginning.
Technically you already have your graph and if you don't want to do anything further, that is the end. The ordered pair (V, E) is the graph itself. But Maple has a package dedicated to Graph theory called GraphTheory. If you want to have a Graph object that you can apply the commands of this package on it, then you need to convert the array of edges to a set. Remember that having the edges stored as ordered pairs (list of length 2) will tell Maple that your edges are directed. If you want undirected edges, then use set of length 2. The following line define the graph object for this example.
E := convert( E, set );
G := GraphTheory:-Graph( V, E );
However, you will get an error message. That is because the elements in your vertices set must be integers or strings or something else, but not matrices, it seems the developers didn't support matrices as label of vertices or something like that. So now instead of saving nodes of the graph as matrices, I pick up the integer indices of them as members of V. For example the identity matrix is the 10th element of V (if you have used the same loop code that I used to generate V above). So instead of asking Maple to have [1 0\\ 0 1] as a vertex of G, I will ask it to have 10 as this vertec, and the edge connecting this node to itself, will be [10, 10]. So I redefine E and V for G.
E := Array([]);
for i from 1 by 1 to 16 do
for j from 1 by 1 to 16 do
if LinearAlgebra:-Equal( ( V[i] . V[j] mod 2 ) , Matrix([ [1, 0], [0, 1] ]) ) then
ArrayTools:-Append( E, [i, j] ):
end if:
end do:
end do:
E := convert( E, set );
G := GraphTheory:-Graph( [ seq(i, i = 1..16) ], E );
No error message this time :)
Now what can we do with this G? The first thing you may want to try is to draw it. Here is how you can do it using GraphTheory's predefined commands.
GraphTheory:-DrawGraph( G );
Here is the picture you get from Maple.
Note that in this case direction was not very important as every edge is two-sided, but in general matrix-multiplication is not commutative so in a different case (if your edge definition is different) you may want to keep the direction and also that is why I did not simplify the nested-loops for E to a n(n-1)/2 cases and kept the whole n^2 cases.

Unsatisfiable solution with `constraint forall(i in x)( x[i] <= x[i+1] );`

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]);
----------

vectorized block assign with overlopping values

So I ran into this bug today
A_TEST(dest,:)=A_TEST(source,:)+A_TEST(dest,:);
A_TEST(:,dest)=A_TEST(:,source)+A_TEST(:,dest);
If dest is non-unique, this fails (which makes sense). So my quick fix is to do a for loop over dest
for (k=1:numel(dest))
A(dest(k),:)=A(source(k),:)+A(dest(k),:);
A(:,dest(k))=A(:,source(k))+A(:,dest(k));
end
And matlab is bad at such for loops. How would one vectorize this call?
With the following, I show how to do it with rows.
To do it with columns, it's a similar approach but different code, I'll explain why.
To summarize, you have a matrix A, with n rows and p columns.
You have a list of integers in the range [1,n], src, and idem for dst.
I'm assuming that they both have the same size, and might contain more than n elements (so that there are repetitions in both potentially).
Grouping the srcs by dsts, it's clear that the operation you're talking about is equivalent to a linear recombination of rows. This is equivalent to a pre-multiplication by a n x n matrix in which element (i,j) = k means "the recombination corresponding to the destination row i contains row j with multiplicity k".
This is what the following code does:
function A = madScience( A, src, dst )
n = size(A,1);
M = eye(n);
ix = sub2ind( [n,n], dst, src );
[ux,~,mlt] = unique( ix );
nux = length(ux);
mlt = accumarray( mlt(:), 1, [nux,1] );
M(ux) = M(ux) + mlt';
A = M*A;
end
Note 1: The two codes that you give in your post are NOT equivalent; you would need two separate for loops to make them equivalent.
Note 2: The same operation on columns is equivalent to a post multiplication by a matrix in which element (i,j) = k means "the recombination corresponding to column j contains column i with multiplicity k".
Note 3: If A is square, then both operations can be performed with the same matrix M as (M*A) * M' (the parenthesis are important).

Ordering a list of lists subject to constraints

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
}