Is it possible to add a XOR Equation Constraint to a CP-Solver model in OR-Tools? - or-tools

I'm trying to solve a problem with Google OR-Tools' CP-Solver.
Is it possible to add a constraint like this:
x1 XOR x2 XOR x3 == 0
Thanks in advance.

AddBoolXOr of n booleans means that the sum is odd. You could just add another True boolean.
from ortools.sat.python import cp_model
model = cp_model.CpModel()
solver = cp_model.CpSolver()
a = model.NewBoolVar("")
b = model.NewBoolVar("")
c = model.NewBoolVar("")
model.AddBoolXOr([a, b, c, 1])
solver.Solve(model)
print([solver.Value(x) for x in (a, b, c)])

Related

How can I show the equality between two symbolic matrices?

I need to prove that formula with using symbolic elements : (A*B)^-1 = B^-1 * A^-1
I couldn't figure out what is the problem but matlab does not show that these two matrices are equal.
Here is my code:
syms a b c d
A = [a b ; c d];
B = [c a ; b d];
F = simplify(inv(A*B));
G = simplify(inv(B) * inv(A));
isequal(F,G)
The result is 0 as I said above. Can anyone help me?

MATLAB: efficient generating of block matrices using a block vector

Suppose
x = [x1;x2; ...; xn]
where each xi is a column vector with length l(i). We can set L = sum(l), the total length of x. I would like to generate 2 matrices based on x:
Let's call them A and B. For example, when x only as 2 blocks x1 and x2 then:
A = [x1*x1' zeros(l(1),l(2)); zeros(l(2),l(1)), x2*x2'];
B = [x1 zeros(l(1),1);
zeros(l(2),1), x2];
In the notation of the problem, A is always L by L and B is L by n. I can generate A and B given x using loops but it is tedious. Is there a clever (loop-free) way to generate A and B. I am using MATLAB 2018b but you can assume earlier version of MATLAB if necessary.
I think it is both short and fast:
B = x .* (repelem((1:numel(l)).',l)==(1:numel(l)));
A = B * B.';
If you have large data It is better to use sparse matrix:
B = sparse(1:numel(x), repelem(1:numel(l), l), x);
A = B * B.';
The following should work. In this case I do an inefficient conversion to cell arrays so there may be a more efficient implementation possible.
cuml = [0; cumsum(l(:))];
get_x = #(idx) x((1:l(idx))+cuml(idx));
x_cell = arrayfun(get_x, 1:numel(l), 'UniformOutput', false);
B = blkdiag(x_cell{:});
A = B*B';
Edit
After running some benchmarks I found a direct loop based implementation to be about twice as fast as the cell based approach above.
A = zeros(sum(l));
B = zeros(sum(l), numel(l));
prev = 0;
for idx = 1:numel(l)
xidx = (1:l(idx))+prev;
A(xidx, xidx) = x(xidx,1) * x(xidx,1)';
B(xidx, idx) = x(idx,1);
prev = prev + l(idx);
end
Here's an alternative approach:
s = repelem(1:numel(l), l).';
t = accumarray(s, x, [], #(x){x*x'});
A = blkdiag(t{:});
t = accumarray(s, x, [], #(x){x});
B = blkdiag(t{:});

How to vectorize vector-matrix element-by-element operation?

I have the following code:
A = rand(N1,N2);
b = rand(1,N1);
B = zeros(N1,N2);
for i=1:N1
for j=1:N2
B(i,j) = A(i,j)*b(i);
end
end
The question is how to write it in vector operation form? Something like B(:,:) = A(:,:).*b(:).
Simple use for bsxfun:
B = bsxfun(#times, A, b')
You can also try:
B = A*.(repmat(b,N2,1))';
Here, firstly you produce N2 repeated version of vector b and multiply it with A in an elementwise manner

Modulo and remainder (Chinese remainder theorem) in MATLAB

How do I find the least possible value in Matlab, given the modulo values and its remainder values in an array? for example:
A=[ 23 90 56 36] %# the modulo values
B=[ 1 3 37 21] %# the remainder values
which leads to the answer 93; which is the least possible value.
EDIT:
Here is my code but it only seems to display the last value of the remainder array as the least value:
z = input('z=');
r = input('r=');
c = 0;
m = max(z);
[x, y] = find(z == m);
r = r(y);
f = find(z);
q = max(f);
p = z(1:q);
n = m * c + r;
if (mod(n, p) == r)
c = c + 1;
end
fprintf('The lowest value is %0.f\n', n)
Okay, so your goal is to find the smallest x that satisfies B(i) = mod(x, A(i)) for each i.
This page contains a very simple (yet thorough) explanation of how to solve your set of equations using the Chinese Remainder Theorem. So, here's an implementation of the described method in MATLAB:
A = [23, 90]; %# Moduli
B = [1, 3]; %# Remainders
%# Find the smallest x that satisfies B(i) = mod(x, A(i)) for each i
AA = meshgrid(A);
assert(~sum(sum(gcd(AA, AA') - diag(A) > 1))) %# Check that moduli are coprime
M = prod(AA' - diag(A - 1));
[G, U, V] = gcd(A, M);
x = mod(sum(B .* M .* V), prod(A))
x =
93
You should note that this algorithm works only for moduli (the values of A) which are coprime!
In your example, they are not, so this will not work for your example (I've put an assert command to break the script if the moduli are not coprime). You should try to implement yourself the full solution for non-comprime moduli!
P.S
Also note that the gcd command uses Euclid's algorithm. If you are required to implement it yourself, this and this might serve you as good references.

Matlab Generating a Matrix

I am trying to generate a matrix in matlab which I will use to solve a polynomial regression formula.
Here is how I am trying to generate the matrix:
I have an input vector X containing N elements and an integer d. d is the integer to know how many times we will add a new column to the matrix we are trying to generate int he following way.
N = [X^d X^{d-1} ... X^2 X O]
O is a vector of same length as X with all 1's.
Everytime d > 2 it does not work.
Can you see any errors in my code (i am new to matlab):
function [ PR ] = PolyRegress( X, Y, d )
O = ones(length(X), 1)
N = [X O]
for j = 2:d
tmp = power(X, j)
N = [tmp N]
end
%TO DO: compute PR
end
It looks like the matlab function vander already does what you want to do.
The VANDER function will only generate powers of the vector upto d = length(X)-1. For a more general solution, you can use the BSXFUN function (works with any value of d):
N = bsxfun(#power, X(:), d:-1:0)
Example:
>> X = (1:.5:2);
>> d = 5;
>> N = bsxfun(#power, X(:), d:-1:0)
N =
1 1 1 1 1 1
7.5938 5.0625 3.375 2.25 1.5 1
32 16 8 4 2 1
I'm not sure if this is the order you want, but it can be easily reversed: use 0:d instead of d:-1:0...