MiniZinc: Remodel a model with constraints in their solutions - minizinc

Let this simple model
int: n=2;
array [0..(n-1)] of var 0..1 : A_;
array [0..(n-1)] of var 0..1 : B_;
array [0..(n-1)] of var 0..1 : C_;
constraint forall (j in 0..n-1) (
A_[j] + B_[j] = C_[j]
);
This model has solutions
solution 1:
A_ = array1d(0..1, [0, 0]);
B_ = array1d(0..1, [1, 1]);
C_ = array1d(0..1, [1, 1]);
---------- 4
solution 2:
A_ = array1d(0..1, [1, 0]);
B_ = array1d(0..1, [0, 1]);
C_ = array1d(0..1, [1, 1]);
---------- 3
solution 3:
A_ = array1d(0..1, [1, 1]);
B_ = array1d(0..1, [0, 0]);
C_ = array1d(0..1, [1, 1]);
---------- 2
solution 4:
A_ = array1d(0..1, [0, 1]);
B_ = array1d(0..1, [1, 0]);
C_ = array1d(0..1, [1, 1]);
---------- 3
solution 5:
A_ = array1d(0..1, [0, 1]);
B_ = array1d(0..1, [0, 0]);
C_ = array1d(0..1, [0, 1]);
---------- 1
solution 6:
A_ = array1d(0..1, [0, 0]);
B_ = array1d(0..1, [0, 1]);
C_ = array1d(0..1, [0, 1]);
---------- 2
solution 7:
A_ = array1d(0..1, [0, 0]);
B_ = array1d(0..1, [1, 0]);
C_ = array1d(0..1, [1, 0]);
---------- 2
solution 8:
A_ = array1d(0..1, [1, 0]);
B_ = array1d(0..1, [0, 0]);
C_ = array1d(0..1, [1, 0]);
---------- 1
solution 9:
A_ = array1d(0..1, [0, 0]);
B_ = array1d(0..1, [0, 0]);
C_ = array1d(0..1, [0, 0]);
---------- 0
==========
How can I remodel it if I want to satisfy the next constraints? I want to introduce some constraints on the set of solutions. Specifically, I would like remodel it to get A such that the sum of the components of their B's and C's solutions is maximum. In this model, for example, the answer will be A = [0, 0], because we have that the sum of the components of the B's and C's (solutions 1, 6, 7, 9) is equal to 4+2+2+0=8.

You cannot model this kind of problem directly in MiniZinc since a MiniZinc model only know its only values (i.e. one solution), not all the possible solutions.
What you can do instead is to use this MiniZinc model to generate all the solutions, and collect them in another system (for example MiniZinc-Python https://pypi.org/project/minizinc/ ) to calculate the optimal solution. If your real problem is similar to your example, it should be fairly easy to just count the components to give that maximum.

Related

How to solve a linear system of equations with 2D matrices on the RHS

I am trying to solve this problem:
I am trying to declare a matrix of matrices for the right hand side (RHS), but I do not know how do it. I am trying this:
MatrizResultados = [[1, 3; -1, 2]; [0, 4; 1, -1]; [2, 1; -1, 1]]
But the result is all one matrix, like so:
MatrizResultados =
1 3
-1 2
0 4
1 -1
2 1
-1 1
How can I store these as separate matrices, within one matrix, to solve the above problem?
Here is my current Matlab code, to try and solve this question:
syms X Y Z;
MatrizCoeficientes = [-1, 1, 2; -1, 2, 3; 1, 4, 2];
MatrizVariables = [X; Y; Z];
MatrizResultados = [[1, 3; -1, 2]; [0, 4; 1, -1]; [2, 1; -1, 1]];
The symbolic math toolbox is overkill for this.
This is 4 separate systems of equations, since addition is linear i.e. there is no cross over in matrix elements. You have, for example
- x(1,1) + y(1,1) + 2*z(1,1) = 1
- x(1,1) + 2*y(1,1) + 3*z(1,1) = 0
x(1,1) + 4*y(1,1) + 2*z(1,1) = 2
This can be solved using the mldivide (\) operator, from a matrix of coefficients. This can be constructed like so:
% Coefficients of all 4 systems
coefs = [-1 1 2; -1 2 3; 1 4 2];
% RHS of the equation, stored with each eqn in a row, each element in a column
solns = [ [1; 0; 2], [-1; 1; -1], [3; 4; 1], [2; -1; 1] ];
% set up output array
xyz = zeros(3, 4);
% Loop through solving the system
for ii = 1:4
% Use mldivide (\) to get solution to system
xyz(:,ii) = coefs\solns(:,ii);
end
Result:
% xyz is a 3x4 matrix, rows are [x;y;z],
% columns correspond to elements of RHS matrices as detailed below
xyz(:,1) % >> [-10 7 -8], solution for position (1,1)
xyz(:,2) % >> [ 15 -10 12], solution for position (2,1)
xyz(:,3) % >> [ -1 0 1], solution for position (1,2)
xyz(:,4) % >> [-23 15 -18], solution for position (2,2)

What's wrong with my implementation of filter function on matlab

I am implementing a function named filter_fir on matlab, referencing the built-in function filter in matlab.
function y = filter_fir(b, a, x)
y = conv(b, x);
y = y(1:length(x));
as = [0 a(2:end)];
a1 = a(1);
if a1 == 0
error('a(1) cannot be zero');
end
ya = y
for n = 1:(length(x))
ya = conv(ya, as);
ya = ya(1:length(x));
y = y - ya;
end
y = y ./ a1;
end
Here are the results:
Yt = filter([1 1 1], 1, [1 2 3 4 5])
Ys = filter_fir([1 1 1], 1, [1 2 3 4 5])
Yt =
1 3 6 9 12
Ys =
1 3 6 9 12
Yt = filter([1 1 1], [2 2], [1 2 3 4 5])
Ys = filter_fir([1 1 1], [2 2], [1 2 3 4 5])
Yt =
0.5000 1.0000 2.0000 2.5000 3.5000
Ys =
0.5000 0.5000 -2.0000 -11.5000 -35.0000
When a=1,two results from the built-in filter function and filter_fir are the same.
But when a = [2 2], they are not the same.
Could anybody tell me what the problem is ?

Vectorize plotting multiple lines with different colors in MATLAB?

Is there a way to vectorize/accelerate the task of plotting multiple lines with different colors?
The working-but-slow approach is
X = [1 2; 3 4];
Y = [2 -4; 5 2];
figure;
hold on;
colors = [1 0 0; 0 1 0];
for idx = 1:size(X, 2)
l = plot(X(:, idx), Y(:, idx), 'Color', colors(idx, :));
end
hold off;
I tried
X = [1 2; 3 4];
Y = [2 -4; 5 2];
figure;
plot(X, Y, 'Color', [1 0 0; 0 1 0]);
but no luck.
This is probably too hacky to be a useful replacement of the loop, but here it goes:
set(gca, 'ColorOrder', [1 0 0; 0 1 0], 'NextPlot', 'add')
plot(X, Y);
The 'ColorOrder' property contains the colors to be used by default for new plots. Setting 'NextPlot' to 'add' seems to be necessary so that the call to plot doesn't reset 'ColorOrder' to its default value.
Tested on R2015b.

Is it possible to change the inequality behaviour of interp1 when using 'previous' or 'next'

Consider as examples:
interp1([0, 1], [2, 3], 0 , 'previous')
interp1([0, 1], [2, 3], 0 , 'next')
which produces
ans =
2
ans =
2
That is, in each respective case it finds the value in [0, 1] closest to and not exceeding 0 (respectively closest to and not below 0), then returns the corresponding value of [2,3]. I would like to change the second condition to "closest to and above 0", that is, it should return the same results as:
interp1([0, 1], [2, 3], 0.1 , 'previous')
interp1([0, 1], [2, 3], 0.1 , 'next')
which gives
ans =
2
ans =
3
In this case this works as 0.1 is a value in between [0, 1].

How to expand my cell without losing information

I have this a cell that holds 4 vectors, and I'd like to expand it so it could hold another vector. Thanks in advance.
a = cell(4, 1);
a{1} = [1, 2, 3];
a{2} = [1, 4, 9];
a{3} = [1, 4, 9];
a{4} = [1; 5];
And I would like to add a new vector [2, 7] so that I will get this
a{1} = [2, 7];
a{2} = [1, 2, 3];
a{3} = [1, 4, 9];
a{4} = [1, 4, 9];
a{5} = [1; 5];
How could I do that ?
a = cell(4, 1);
a{1} = [1, 2, 3];
a{2} = [1, 4, 9];
a{3} = [1, 4, 9];
a{4} = [1; 5];
a = [[2, 7];a]
Yielding:
a =
[1x2 double]
[1x3 double]
[1x3 double]
[1x3 double]
[2x1 double]
The name for what you are trying to do is concatenation. In MATLAB, square brackets are an implicit method of concatenation. While you typically think about these being used to concatenate numbers to form a vector or matrix:
x = [1, 2, 3, 4] % 1 x 4
You can also use them to concatenate other data types (including cell arrays)
y = [{1,2}, 5, {4, 5}]; % 1 x 3 Cell Array
It is also important to keep track of the dimension of concatenation. With square brackets you can either concatenate across the columns (2nd dimension) using a comma or across the rows (1st dimension using a semi-colon).
size([1,2,3])
1 x 3
size([1;2;3])
3 x 1
While square brackets are a quick and easy solution, I prefer to be a little more explicit. For this, MATLAB has the following functions: cat, horzcat, and vertcat. I personally prefer cat since you can specify concatenation in any arbitrary dimension.
x = cat(2, 100, 200, 300); % 1 x 3
100 200 300
x = cat(1, 100, 200, 300); % 3 x 1
100
200
300
x = cat(3, 100, 200, 300) % 1 x 1 x 3
x(:,:,1) =
100
x(:,:,2) =
200
x(:,:,3) =
300
So back to your original question, you want to concatenate in the 1st dimension (rows) so you could simply do the following:
a = cell(4, 1);
a{1} = [1, 2, 3];
a{2} = [1, 4, 9];
a{3} = [1, 4, 9];
a{4} = [1; 5];
a = cat(1, [2, 7], a);
Also remember that this form of using concat or the square brackets can be applied to most datatypes within MATLAB including structs among others.