Linear programming using the spicy.optimize.linprog - scipy

I’m trying to formulate and solve a linear programming problem using the spicy.optimize.linprog function.
I want to solve the function Ax = b subject to the following constraints:
# A b
-0.4866 x1 + 0.1632 x2 < 0
0.3211 x1 + 0.5485 x2 < 0
-0.5670 x1 + 0.1099 x2 < 0
-0.1070 x1 + 0.0545 x2 = 1
-0.4379 x1 + 0.1465 x2 < 0
0.0220 x1 + 0.7960 x2 < 0
-0.3673 x1 - 0.0494 x2 < 0
I have as input an nx2 matrix A and nx1 matrix b. The result should be the vectors x1 and x2. Here's my input data.
# Coefficients
A = [[-0.4866, 0.1632],
[0.3211, 0.5485],
[-0.5670, 0.1099],
[-0.1070, 0.0545],
[-0.4379, 0.1465],
[0.0220, 0.7960],
[-0.3673, -0.0494]]
# Inequalities
b = [0, 0, 0, -1, 0, 0, 0]
I think my problem is how to formulate c, the function the be minimized for input into the linprog function.
res = linprog(c, A, b)

I'm able to solve for the upper bounds by:
c = [1, 0, 0]
A = [[-1, -0.486, 0.1632],
[-1, 0.3211, 0.5485],
[-1, -0.5670, 0.1099],
[-1, -0.1070, 0.0545],
[-1, -0.4379, 0.1465],
[-1, 0.220, 0.7960],
[-1,-0.3673, -0.0494]]
b = [0, 0, 0, -1, 0, 0, 0]
c0_bounds = (0, 1)
x1_bounds = (-np.inf, np.inf)
x2_bounds = (-np.inf, np.inf)
res = linprog(c, A_ub=A, b_ub=b, bounds=(c0_bounds, x1_bounds, x2_bounds), options={"disp": True})
But now what if I also want to solve for the lower bounds?

Related

Using 3D RANSAC to estimate the 3D affine transform

I am trying to register two volumeetric images(img1 and img2). The size of the img1 is 40x40x24. The size of the img2 is 64 x64x11.
So far, I have extracted their features (vol1 and vol2, the same size as the images) and then matched them.
Now, I have a set of corresponding points in two feature volumes that is stored in pairs which is a matrix of size 100x6 (every row of pairs is [x, y, z, X, Y, Z] where (x,y,z) are the coordinates of a voxel in vol1 and [X Y Z] is the coordinates of corresponding voxel in vol2).
Now, I am trying to use RANSAC algorithm to estimate the 3D affine transform, T. I have written the below code, but I think there is a problem with it because when I get the output transform T and multiply it by a sample voxel coordinates from vol1, I get some negative coordinates!!!
Below is my implementation for 3D RANSAC algorithm. I have used 2D RANSAC implementation in this link. Please let me know if you see any problem.
function [bp] = ransac(data,bpI,iter,num,distThresh)
% data: a nx6 dataset with #n data points
% num: the minimum number of points. Here num=4.
% iter: the number of iterations
% distThresh: the threshold of the distances between points and the fitting line
% inlierRatio: the threshold of the number of inliers
% bpI : Initialized affine transform model
number = size(data,1); % Total number of points
bestInNum = 0; % Best fitting line with largest number of inliers
% Initial parameters for best model (affine transform)
% Affine transform : T = [bp1, bp2, bp3, bp4; bp5, bp6, bp7, bp8; bp9, bp10, bp11, bp12;]
bp1 = bpI(1,1); bp2 = bpI(1,2); bp3 = bpI(1,3); bp4 = bpI(1,4);
bp5 = bpI(1,5); bp6 = bpI(1,6); bp7 = bpI(1,7); bp8 = bpI(1,8);
bp9 = bpI(1,9); bp10 = bpI(1,10); bp11 = bpI(1,11); bp12 = bpI(1,12);
for i=1:iter
% Randomly select 4 points
idx = randperm(number,num); sample = data(idx,:);
% Creating others which is the data that does not contain data in sample
idxs = sort(idx, 'descend'); % Sorting idx
others = data;
for n = 1:num
others(idxs(1,n), :) = [];
end
x1 = sample(1,1); y1 = sample(1,2); z1 = sample(1,3);
x2 = sample(2,1); y2 = sample(2,2); z2 = sample(2,3);
x3 = sample(3,1); y3 = sample(3,2); z3 = sample(3,3);
x4 = sample(4,1); y4 = sample(4,2); z4 = sample(4,3);
X1 = sample(1,4); Y1 = sample(1,5); Z1 = sample(1,6);
X2 = sample(2,4); Y2 = sample(2,5); Z2 = sample(2,6);
X3 = sample(3,4); Y3 = sample(3,5); Z3 = sample(3,6);
X4 = sample(4,4); Y4 = sample(4,5); Z4 = sample(4,6);
B = [X1; Y1; Z1; X2; Y2; Z2; X3; Y3; Z3; X4; Y4; Z4];
A = [
x1, y1, z1, 1, 0 , 0 , 0, 0, 0, 0, 0, 0;
0 , 0 , 0, 0, x1, y1, z1, 1, 0, 0 ,0, 0;
0 , 0 , 0, 0, 0 , 0 , 0, 0, x1, y1, z1, 1;
x2, y2, z1, 1, 0 , 0 , 0, 0, 0, 0, 0, 0;
0 , 0 , 0, 0, x2, y2, z2, 1, 0 , 0 ,0, 0;
0 , 0 , 0, 0, 0 , 0 , 0, 0, x2, y2, z2, 1;
x3, y3, z3, 1, 0 , 0 , 0, 0, 0, 0, 0, 0;
0 , 0 , 0, 0, x3, y3, z3, 1, 0 , 0 ,0, 0;
0 , 0 , 0, 0, 0 , 0 , 0, 0, x3, y3, z3, 1;
x4, y4, z4, 1, 0 , 0 , 0, 0, 0, 0, 0, 0;
0 , 0 , 0, 0, x4, y4, z4, 1, 0 , 0 ,0, 0;
0 , 0 , 0, 0, 0 , 0 , 0, 0, x4, y4, z4, 1
];
cbp = A\B; % calculating best parameters of the model (affine transform)
T = [reshape(cbp',[4,3])'; 0, 0, 0, 1]; % Current affine transform matrix
% Computing other points in the dataset that their distance from the
% calculated model is less than the threshold.
numOthers = size(others,1);
inliers = [];
for j = 1:numOthers
% b = T a
d = others(j,:); % Explanation: d = [ax, ay, az, bx, by, bz]
a = [d(1,1:3), 1]'; % Explanation a = [ax, ay, az]'
b = [d(1,4:6),1]'; % b = [bx, by, bz]'
cb = T*a; % Calculated b
dist = sum((cb-b).^2);
if(dist<=distThresh)
inliers = [inliers; d];
end
end
numinliers = size(inliers,1);
% Update the number of inliers and fitting model if better model is found
if (numinliers >= bestInNum)
% Better model is estimated
bestInNum = numinliers;
bp1 = cbp(1,1); bp2 = cbp(2,1); bp3 = cbp(3,1); bp4 = cbp(4,1);
bp5 = cbp(5,1); bp6 = cbp(6,1); bp7 = cbp(7,1); bp8 = cbp(8,1);
bp9 = cbp(9,1); bp10 = cbp(10,1); bp11 = cbp(11,1); bp12 = cbp(12,1);
bp = [bp1, bp2, bp3, bp4, bp5, bp6, bp7, bp8, bp9, bp10, bp11, bp12];
end
end
bp
end

Filter matrix rows depending on values in a second matrix

Given a 2x3 matrix x and a 4x2 matrix y, I'd like to use each row of y to index into x. If the value in x is not equal to -1 I'd like to remove that row from y. Here's an example that does what I'd like, except I'd like to do it in a fast, simple way without a loop.
x = [1, 2, 3; -1, 2, -1];
y = [1, 1; 1, 3; 2, 1; 2, 3];
for i=size(y,1):-1:1
if x(y(i,1), y(i,2)) ~= -1
y(i,:) = [];
end
end
This results in:
y =
2 1
2 3
A raw approach to what sub2ind follows (as used by this pretty nice-looking solution posted by Luis) inherently would be this -
y = y(x((y(:,2)-1)*size(x,1)+y(:,1))==-1,:)
Benchmarking
Benchmarking Code
N = 5000;
num_runs = 10000;
x = round(rand(N,N).*2)-1;
y = zeros(N,2);
y(:,1) = randi(size(x,1),N,1);
y(:,2) = randi(size(x,2),N,1);
disp('----------------- With sub2ind ')
tic
for k = 1:num_runs
y1 = y(x(sub2ind(size(x), y(:,1), y(:,2)))==-1,:);
end
toc,clear y1
disp('----------- With raw version of sub2ind ')
tic
for k = 1:num_runs
y2 = y(x((y(:,2)-1)*size(x,1)+y(:,1))==-1,:);
end
toc
Results
----------------- With sub2ind
Elapsed time is 4.095730 seconds.
----------- With raw version of sub2ind
Elapsed time is 2.405532 seconds.
This can be easily vectorized as follows (see sub2ind):
y = y(x(sub2ind(size(x), y(:,1), y(:,2)))==-1,:);
>> x = [1, 2, 3; -1, 2, -1];
>>y = [1, 1;
1, 2;
1, 3;
2, 1;
2, 2;
2, 3];
>>row_idx = reshape((x == -1)',1,6);
>>y = y(row_idx,:);
I think you didn't include all the index of x in y. I included all of them in y. Have a look..
Generalized version:
>> x = [1, 2, 3; -1, 2, -1];
>>y = [1, 1;
1, 2;
1, 3;
2, 1;
2, 2;
2, 3];
>>row_idx = reshape((x == -1)',1,size(x,1)*size(x,2));
>>y = y(row_idx,:);

Finding an equation of linear classifier for two separable sets of points using perceptron learning

I would like to write a matlab function to find an equation of a linear classifier for 2 separable sets of points using one single-layer perceptron. I have got 2 files:
script file - run.m:
x_1 = [3, 3, 2, 4, 5];
y_1 = [3, 4, 5, 2, 2];
x_2 = [6, 7, 5, 9, 8];
y_2 = [3, 3, 4, 2, 5];
target_array = [0 0 0 0 0 1 1 1 1 1];
[ func ] = classify_perceptron([x_1 x_2; y_1 y_2], target_array);
x = -2:10;
y = arrayfun(func, x);
plot(x_1, y_1, 'o', x_2, y_2, 'X', x, y);
axis([-2, 10, -2, 10]);
classify_perceptron.m
function [ func ] = classify_perceptron( points, target )
% points - matrix of x,y coordinates
% target - array of expected results
% func - function handler which appropriately classifies a point
% given by x, y arguments supplied to this function
target_arr = target;
weights = rand(1, 2);
translation = rand();
for i=1:size(points, 2)
flag = true;
while flag
result = weights * points(:, i) + translation;
y = result > 0;
e = target_arr(1, i) - y;
if e ~= 0
weights = weights + (e * points(:, i))';
translation = translation + e;
else
flag = false;
end
end
end
func = #(x)(-(translation + (weights(1, 1) * x)) / weights(1, 2));
return
end
The problem is that I don't know where I am making the mistake that leads to incorrect result. It looks like the slope of the line is right, however translation should be a bit bigger. I would be really thankful for pointing me in the right direction. The result I get is presented in the picture below:
Ok, so I have made a significant progress. In case someone runs into the same problem I present to you the solution. The problem has been solved by adding a variable learning_rate = 0.1 and packing the loop iterating over points into another loop iterating as many times as specified in the variable epochs (e.g. 300) .

equationsToMatrix: how do I get the values of the variables?

When using equationsToMatrix you solve a set of linear equations as in the example (the solution is included)
syms x y z;
[A, b] = equationsToMatrix([x + y - 2*z == 0, x + y + z == 1, 2*y - z + 5 == 0], [x, y, z])
%solution of the equation set
A =
[ 1, 1, -2]
[ 1, 1, 1]
[ 0, 2, -1]
b =
0
1
-5
The vector b returns the values of the variables at issue: x,y, and z. However if I type x then MATLAB returns x and not 0, which is the solution of the equation in this case. This also occurs without adding the syms option.
The other problem is that if I type b(1) or b(2), I don't get any value: I would expect b to contain the values of x,y and z.
What I would need is to get something like this in the end
b(1) = 0
or
x = 0
What should I do to get the values of x,y,z by just typing x,y,z?
What you have is a way of converting symbolic linear equations into a numeric system by extracting the coefficient matrices. To solve the system you need to do
sol = A\b;
and now you can use the values in another expression with
subst(expr, {x,y,z}, {sol(1),sol(2),sol(3));
for example
A =
1 1 -2
1 1 1
0 2 -1
b =
0
1
-5
>> A\b
ans =
3.0000
-2.3333
0.3333

Abnormal behavior algorithm implemented in matlab depending of the input

I'm doing a homework assignment for scientific computing, specifically the iterative methods Gauss-Seidel and SOR in matlab, the problem is that for a matrix gives me unexpected results (the solution does not converge) and for another matrix converges.
Heres the code of sor, where:
A: Matrix of the system A * x = b
Xini: array of initial iteration
b: array independent of the system A * x = b
maxiter: Maximum Iterations
tol: Tolerance;
In particular, the SOR method, will receive a sixth parameter called w which corresponds to the relaxation parameter.
Here´s the code for sor method:
function [x2,iter] = sor(A,xIni, b, maxIter, tol,w)
x1 = xIni;
x2 = x1;
iter = 0;
i = 0;
j = 0;
n = size(A, 1);
for iter = 1:maxIter,
for i = 1:n
a = w / A(i,i);
x = 0;
for j = 1:i-1
x = x + (A(i,j) * x2(j));
end
for j = i+1:n
x = x + (A(i,j) * x1(j));
end
x2(i) = (a * (b(i) - x)) + ((1 - w) * x1(i));
end
x1 = x2;
if (norm(b - A * x2) < tol);
break;
end
end
Here´s the code for Gauss-seidel method:
function [x, iter] = Gauss(A, xIni, b, maxIter, tol)
x = xIni;
xnew = x;
iter = 0;
i = 0;
j = 0;
n = size(A,1);
for iter = 1:maxIter,
for i = 1:n
a = 1 / A(i,i);
x1 = 0;
x2 = 0;
for j = 1:i-1
x1 = x1 + (A(i,j) * xnew(j));
end
for j = i+1:n
x2 = x2 + (A(i,j) * x(j));
end
xnew(i) = a * (b(i) - x1 - x2);
end
x= xnew;
if ((norm(A*xnew-b)) <= tol);
break;
end
end
For this input:
A = [1 2 -2; 1 1 1; 2 2 1];
b = [1; 2; 5];
when call the function Gauss-Seidel or sor :
[x, iter] = gauss(A, [0; 0; 0], b, 1000, eps)
[x, iter] = sor(A, [0; 0; 0], b, 1000, eps, 1.5)
the output for gauss is:
x =
1.0e+304 *
1.6024
-1.6030
0.0011
iter =
1000
and for sor is:
x =
NaN
NaN
NaN
iter =
1000
however for the following system is able to find the solution:
A = [ 4 -1 0 -1 0 0;
-1 4 -1 0 -1 0;
0 -1 4 0 0 -1;
-1 0 0 4 -1 0;
0 -1 0 -1 4 -1;
0 0 -1 0 -1 4 ]
b = [1 0 0 0 0 0]'
Solution:
[x, iter] = sor(A, [0; 0; 0], b, 1000, eps, 1.5)
x =
0.2948
0.0932
0.0282
0.0861
0.0497
0.0195
iter =
52
The behavior of the methods depends on the conditioning of both matrices? because I noticed that the second matrix is better conditioned than the first. Any suggestions?
From the wiki article on Gauss-Seidel:
convergence is only guaranteed if the matrix is either diagonally dominant, or symmetric and positive definite
Since SOR is similar to Gauss-Seidel, I expect the same conditions to hold for SOR, but you might want to look that one up.
Your first matrix is definitely not diagonally dominant or symmetric. Your second matrix however, is symmetric and positive definite (because all(A==A.') and all(eig(A)>0)).
If you use Matlab's default method (A\b) as the "real" solution, and you plot the norm of the difference between each iteration and the "real" solution, then you get the two graphs below. It is obvious the first matrix is not ever going to converge, while the second matrix already produces acceptable results after a few iterations.
Always get to know the limitations of your algorithms before applying them in the wild :)