Gurobi solver in matlab - matlab

I want to use Gurobi solver in Matlab, but I don't know how to calculate the required matrices (qrow and qcol).
For your reference I am copying the example provided in documentation.
0.5 x^2 - xy + y^2 - 2x - 6y
subject to
x + y <= 2
-x + 2y <= 2, 2x + y <= 3, x >= 0, y >= 0
c = [-2 -6]; % objective linear term
objtype = 1; % minimization
A = sparse([1 1; -1 2; 2 1]); % constraint coefficients
b = [2; 2; 3]; % constraint right-hand side
lb = []; % [ ] means 0 lower bound
ub = []; % [ ] means inf upper bound
contypes = '$<<
vtypes = [ ]; % [ ] means all variables are continuous
QP.qrow = int32([0 0 1]); % indices of x, x, y as in (0.5 x^2 - xy + y^2); use int64 if sizeof(int) is 8 for you system
QP.qcol = int32([0 1 1]); % indices of x, y, y as in (0.5 x^2 - xy + y^2); use int64 if sizeof(int) is 8 for you system
QP.qval = [0.5 -1 1]; % coefficients of (0.5 x^2 - xy + y^2)
Does it mean that if I have 4 decision variables than i should use 0,1,2,3 as indices for my decision variables x_1, x_2, x_3, x_4.?
Thanks
Note: I tried to use mathurl.com but I don't get how to write in proper format show that it will appear as latex text. Sorry for the notation.

This seems to be your reference. However your question seems to relate different example. You may need to show that one.
Anyway according Gurobi documentation:
The quadratic terms in the objective function should be specified by opts.QP.qrow, opts.QP.qcol, and opts.QP.qval, which correspond to the input arguments qrow, qcol, and qval of function GRBaddqpterms. They are all 1D arrays. The first two arguments, qrow and qcol, specify the row and column indices (starting from 0) of 2nd-order terms such as and . The third argument, qval, gives their coefficients.
So the answer is yes use indicies [0 1 2 3] for your decision variables x0, x1, x2, x3.

Related

How use the generic optimization program of Octave / MATLAB

Sorry to bother you, but I'm fighting with the manual of Octave without any result.
I would like to maximize a function a little bit complex with some constraint :
The function is mathemathically similar to this one (I write this one to simplify the explanations) :
f(x, y, z, t) = arcsin (x/2t)/(y + x + max (1, z/t))
with z, t between 0 and 1, x between 1 and 2, and y greater than 1/x^2.
Could you give me the code to compute the numerical value for x, y, z and t to maximize this function. From this code, I will derive how the optimisation function should be used.
It will help me a lot.
Thank you very much
you can use fmincon and minimize the additive inverse of your objective function. your constraint ("y greater than 1/x^2") is nonlinear so you should use the nonlcon argument of fmincon:
% function definition (minus sign to maximize instead of minimize)
f = #(x) - asin(x(1)/(2*x(4)))/(x(2) + x(1) + max(1, x(3)/x(4)) );
lb = [1 -inf 0 0];% lower bound for [x y z t]
ub = [2 inf 1 1];% upper bound for [x y z t]
x0 = [1.5 0 0.5 0.9]; % initial vector
% minimization
x = fmincon(f,x0,[],[],[],[],lb,ub,#mycon);
where mycon defines your constraint:
function [c,ceq] = mycon(x)
% y > 1/x^2
% 1/x^2 - y < 0
c = 1/x(1)^2 - x(2);
ceq = 0;
end
you can also pass an options argument to specify optimization options.

How to fit data with piecewise linear function in matlab with some constraints on slope

I am trying to fit a piecewise linear equation for my (xdata, ydata) data. I have to challenges, the first one is how to convert the equation in the form of the function handle and the second one is how to put a constraint on the slope, for instance, a2>a1 and a2>0 and a1>0.
xdata = 5:0.2:40;
ydata = max(18,xdata) + 0.5*randn(size(xdata));
a1 = (y1-y0)/(x1-x0); a2 = (y2-y1)/(x2-x1);
if x < x1;
f(x) = y0 + a1*(x-x0);
else
f(x) = y0 + a1*(x1-x0) + a2*(x-x1);
end
FU = matlabFunction(f)
x0 = 5; y0 = 16;
x = lsqcurvefit(FU,[x0,y0],xdata,ydata)
The key to creating the piece-wise function is to replace the if condition by a vectorized >. By calling y = x > 1 on some array x, the output y will be an array of the same size as x, with a logical True if the corresponding element in x is larger than 1, and a False otherwise. For example
>> x = [1, 2, 4; 3, 1, 2];
>> y = x > 2
y =
2×3 logical array
0 0 1
1 0 0
You can utilize this to create a piece-wise linear function, as follows:
>> fun = #(theta, xdata) theta(1) + ...
(xdata<=theta(2)) .* theta(3) .* xdata + ...
(xdata>theta(2)) .* (theta(3) * theta(2) + ...
theta(4) .* (xdata-theta(2)))
The parameter vector theta will be 4-dimensional: the first element is a constant offset from zero, the second element is the corner point, and the third and fourth elements are the two slopes.
By multiplying theta(3).*xdata with the result of xdata<=theta(2), you get theta(3).*xdata for each point in xdata which is smaller than theta(2), and 0 for all others.
Then, calling lsqcurvefit is as simple as
>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata)
theta =
18.3793
17.9639
-0.0230
0.9943
The lsqcurvefit function also allows you to specify a lower bound lb and an upper bound ub for the variables you want to estimate. For variables where you don't want to specify a bound, you can use e.g. inf as bound. To make sure that your a1 and a2, i.e. theta(3) and theta(4) are positive, we can specify the lower bound to be [-inf, -inf, 0, 0].
However, the lsqcurvefit function doesn't allow you to add the constraint a2 > a1 (or any linear inequality constraints). In the example data, this constraint probably isn't even necessary as this is obvious from the data. Otherwise, a possible solution would be to replace a2 by a1 + da, and use a lower bound of 0 for da. This makes sure that a2 >= a1.
>> fun = #(theta, xdata) theta(1) + ...
(xdata<=theta(2)) .* theta(3) .* xdata + ...
(xdata>theta(2)) .* (theta(3) * theta(2) + ...
(theta(3)+theta(4)) .* (xdata-theta(2)))
>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata, [-Inf, -Inf, 0, 0], [])
theta =
18.1162
18.1159
0.0000
0.9944

Plotting equation in Matlab using for loop

I want to plot an equation using a for-loop. I have tried several different ways, but keep getting the apparently common error "Subscript indices must either be real positive integers or logicals". The equation I want to plot is y(x) = (x^4)-(4*x^3)-(6*x^2)+15.
The last code I tried was the following:
y(0) = 15;
for x = [-3 -2 -1 0 1 2 3 4 5 6];
y(x) = (x^4)-(4*x^3)-(6*x^2)+15;
end
plot(x,y)
To start from the beginning,
y(0) = 15;
will give you the following error:
Subscript indices must either be real positive integers or logicals.
This is because Matlab's indexing starts at 1. Other languages like C and Python start at 0.
Matlab can work directly with vectors. So in your code, there is no need for a loop at all.
You can do it like this:
x = [-3 -2 -1 0 1 2 3 4 5 6];
y = (x.^4) - (4*x.^3) - (6*x.^2) + 15;
plot(x, y);
Note that we need to use element-wise operators like .* and .^ to calculate the values vectorized for every element. Therefore a point . is written in front of the operator.
Additionally, we can improve the code substantially by using the colon operator to generate x:
x = -3:6; % produces the same as [-3 -2 -1 0 1 2 3 4 5 6]
y = (x.^4) - (4*x.^3) - (6*x.^2) + 15;
plot(x, y);
If you want finer details for your graph, use linspace as suggested by #Yvon:
x = linspace(-3, 6, 100); % produces a vector with 100 points between -3 and 6.
y = x.^4-4*x.^3-6*x.^2+15;
plot(x,y)
x = linspace(-3, 6, 100);
y = x.^4-4*x.^3-6*x.^2+15;
plot(x,y)

how to plot x,y,z in matlab?

I am making the Gauss-Jordan method in matlab and I want to plot these equations
x + y + 4*z = -1
-2*x – y + z= -5
3*x-2*y+3*z=-4
To see in what point of the graph they intersect, but I do not know how to plot in matlab
Is this what you are looking for?
clc
clear
close all
%// Generate x and y values to plot from.
[x,y] = meshgrid(linspace(0,10,100),linspace(0,10,100));
%// Get equation for plane; i.e. z position
z1 = 0.25.*(-1-x-y);
z2 = -5+y+2*x;
z3 = (-4-3.*x+2.*y)./3;
%// Use surf to generate surface plots
figure;
surf(x,y,z1,'linestyle','none','facealpha',0.4)
hold on
surf(x,y,z2,'linestyle','none','facealpha',0.4)
surf(x,y,z3,'linestyle','none','facealpha',0.4)
hold off
%// Use to manually rotate the plot
rotate3d on
Which gives this:
You can play around with the 'FaceAlpha' property of course to make things clearer. Have a look at the surf function for more options.
EDIT:
Alternatively to #rayryeng solution to solve for x,y and z you can use mldivide:
A = [1 1 4;-2 -1 1;3 -2 3];
B = [-1;-5;-4];
X = mldivide(A,B)
X =
1.0000
2.0000
-1.0000
Here is how i would plot those planes.
The 4-th argument of surf lets you specify the color.
% // create function handles of form z = f(x,y)
f1 = #(X,Y) 1/4*(-1 - X -Y);
f2 = #(X,Y) -5 + 2*X + Y;
f3 = #(X,Y) 1/3*(-4 -3*X + 2*Y);
% // create a 2d-grid to plot the functions over
x = linspace(-5, 5, 10);
y = linspace(-10, 10, 20);
[X,Y] = meshgrid(x,y);
% // plot the planes in different colors (4th argument) and without edges
figure
surf(X, Y, f1(X,Y), ones(size(f1(X,Y))), 'EdgeColor', 'None');
hold on
surf(X, Y, f2(X,Y), ones(size(f2(X,Y)))*2, 'EdgeColor', 'None');
surf(X, Y, f3(X,Y), ones(size(f3(X,Y)))*3, 'EdgeColor', 'None');
legend('plane1', 'plane2', 'plane3')
xlabel('x'), ylabel('y'), zlabel('z')
Though this is not plotting, perhaps this is also something you can use. If you want to determine the simultaneous solution to those equations, consider using solve
syms x y z
A = solve('x + y + 4*z == -1', '-2*x - y + z == -5', '3*x - 2*y + 3*z == -4')
disp([A.x A.y A.z]);
[ 1, 2, -1]
This will check to see whether your Gauss-Jordan elimination is correct. If you don't like using solve, you can use linear algebra to help you solve this for you. Simply place your coefficients for your system in a matrix and vector, then find the inverse of the matrix and multiply by the vector.
A = [1 1 4; -2 -1 1; 3 -2 3];
b = [-1;-5;-4];
x = A \ b
x =
1.0000
2.0000
-1.0000
... and even another method is to use rref to reduce your system into row-reduced echelon form. This would be the result after you successfully apply Gauss-Jordan elimination to your linear system. As such:
A = [1 1 4; -2 -1 1; 3 -2 3];
b = [-1;-5;-4];
rref([A b])
ans =
1 0 0 1
0 1 0 2
0 0 1 -1
Reading the above answer, x = 1, y = 2, z = -1. This represents the augmented system where the first 3 columns denote the coefficients of your system and the fourth column denotes the right hand side of your linear system of equations.

Using MATLAB to write a function that implements Newton's method in two dimensions

I am trying to write a function that implements Newton's method in two dimensions and whilst I have done this, I have to now adjust my script so that the input parameters of my function must be f(x) in a column vector, the Jacobian matrix of f(x), the initial guess x0 and the tolerance where the function f(x) and its Jacobian matrix are in separate .m files.
As an example of a script I wrote that implements Newton's method, I have:
n=0; %initialize iteration counter
eps=1; %initialize error
x=[1;1]; %set starting value
%Computation loop
while eps>1e-10&n<100
g=[x(1)^2+x(2)^3-1;x(1)^4-x(2)^4+x(1)*x(2)]; %g(x)
eps=abs(g(1))+abs(g(2)); %error
Jg=[2*x(1),3*x(2)^2;4*x(1)^3+x(2),-4*x(2)^3+x(1)]; %Jacobian
y=x-Jg\g; %iterate
x=y; %update x
n=n+1; %counter+1
end
n,x,eps %display end values
So with this script, I had implemented the function and the Jacobian matrix into the actual script and I am struggling to work out how I can actually create a script with the input parameters required.
Thanks!
If you don't mind, I'd like to restructure your code so that it is more dynamic and more user friendly to read.
Let's start with some preliminaries. If you want to make your script truly dynamic, then I would recommend that you use the Symbolic Math Toolbox. This way, you can use MATLAB to tackle derivatives of functions for you. You first need to use the syms command, followed by any variable you want. This tells MATLAB that you are now going to treat this variable as "symbolic" (i.e. not a constant). Let's start with some basics:
syms x;
y = 2*x^2 + 6*x + 3;
dy = diff(y); % Derivative with respect to x. Should give 4*x + 6;
out = subs(y, 3); % The subs command will substitute all x's in y with the value 3
% This should give 2*(3^2) + 6*3 + 3 = 39
Because this is 2D, we're going to need 2D functions... so let's define x and y as variables. The way you call the subs command will be slightly different:
syms x, y; % Two variables now
z = 2*x*y^2 + 6*y + x;
dzx = diff(z, 'x'); % Differentiate with respect to x - Should give 2*y^2 + 1
dzy = diff(z, 'y'); % Differentiate with respect to y - Should give 4*x*y + 6
out = subs(z, {x, y}, [2, 3]); % For z, with variables x,y, substitute x = 2, y = 3
% Should give 56
One more thing... we can place equations into vectors or matrices and use subs to simultaneously substitute all values of x and y into each equation.
syms x, y;
z1 = 3*x + 6*y + 3;
z2 = 3*y + 4*y + 4;
f = [z1; z2];
out = subs(f, {x,y}, [2, 3]); % Produces a 2 x 1 vector with [27; 25]
We can do the same thing for matrices, but for brevity I won't show you how to do that. I will defer to the code and you can see it then.
Now that we have that established, let's tackle your code one piece at a time to truly make this dynamic. Your function requires the initial guess x0, the function f(x) as a column vector, the Jacobian matrix as a 2 x 2 matrix and the tolerance tol.
Before you run your script, you will need to generate your parameters:
syms x y; % Make x,y symbolic
f1 = x^2 + y^3 - 1; % Make your two equations (from your example)
f2 = x^4 - y^4 + x*y;
f = [f1; f2]; % f(x) vector
% Jacobian matrix
J = [diff(f1, 'x') diff(f1, 'y'); diff(f2, 'x') diff(f2, 'y')];
% Initial vector
x0 = [1; 1];
% Tolerance:
tol = 1e-10;
Now, make your script into a function:
% To run in MATLAB, do:
% [n, xout, tol] = Jacobian2D(f, J, x0, tol);
% disp('n = '); disp(n); disp('x = '); disp(xout); disp('tol = '); disp(tol);
function [n, xout, tol] = Jacobian2D(f, J, x0, tol)
% Just to be sure...
syms x, y;
% Initialize error
ep = 1; % Note: eps is a reserved keyword in MATLAB
% Initialize counter
n = 0;
% For the beginning of the loop
% Must transpose into a row vector as this is required by subs
xout = x0';
% Computation loop
while ep > tol && n < 100
g = subs(f, {x,y}, xout); %g(x)
ep = abs(g(1)) + abs(g(2)); %error
Jg = subs(J, {x,y}, xout); %Jacobian
yout = xout - Jg\g; %iterate
xout = yout; %update x
n = n + 1; %counter+1
end
% Transpose and convert back to number representation
xout = double(xout');
I should probably tell you that when you're doing computation using the Symbolic Math Toolbox, the data type of the numbers as you're calculating them are a sym object. You probably want to convert these back into real numbers and so you can use double to cast them back. However, if you leave them in the sym format, it displays your numbers as neat fractions if that's what you're looking for. Cast to double if you want the decimal point representation.
Now when you run this function, it should give you what you're looking for. I have not tested this code, but I'm pretty sure this will work.
Happy to answer any more questions you may have. Hope this helps.
Cheers!