Arbitrary dimension for CVXGEN program - matlab

I would like to solve a QP/LP problem in MatLab using CVXGEN. I have preference for CVXGEN over CVX, since CVXGEN is much faster. In particular, I would like to solve
min f(x) s.t. x in X
where f(x) is in quadratic form and X is compact, convex, and defined by linear functions. The size of the problem varies depending on the run. I would like to automate the procedure as much as possible. To illustrate, an example of a CVXGEN code is:
dimensions
n = 10
end
parameters
Q (n,n) psd # quadratic penalty.
end
variables
x (n)
end
minimize
quad(x, Q)
end​​​​​​​​​​​​​
​This code is inputted at cvxgen.com. On this website, I can then generate the C code which gives me a unique number. I can then compile this into MEX code using the unique number. Last, I can call this MEX code (csolve) from MatLab by running the following code
n=10; % dimension of the problem
params.Q = eye(n,n); % assume that the Hessian is the identity
[vars, status] = csolve(params); % this outputs optimal x* = 0.
This procedure, however, requires for each dimension of the problem n that I want to run, I need to go to cvxgen.com, change n, compile code, then run my MatLab code. Is it possible to let n enter as a parameter? This way, I only need to compile the code once, then in my MatLab code set params.n = n and params.Q = eye(n,n), and then call [vars, status] = csolve(params);.

In short, I do not think it is possible to specify arbitrary dimension on cvxgen.com. I do have one solution: First, in MatLab, allow the user to specify his/her email address and password for cvxgen.com. Next, using system command in MatLab, call a python or javascript program that executes the following steps:
1) Log user into cvxgen.com
2) Goto edit tab on website
3) Copy and paste the cvxgen code
4) Goto generate c tab
5) Click generate code
6) Goto matlab tab
7) Copy unique identifying number for the compiled C code to be downloaded
8) Pass the unique identifying number back to MatLab and compile the Mex files in MatLab by calling the identifying number.
Now the Mex files can be called in MatLab by the following commands:
n=10; % dimension of the problem
params.Q = eye(n,n); % assume that the Hessian is the identity
[vars, status] = csolve(params); % this outputs optimal x* = 0.

Related

Mixed Integer Quadratic Programming with linear constraints in Matlab calling Gurobi

I have some troubles to understand how to implement the following MIQP (Mixed Integer Quadratic Programming) with linear constraints in Matlab calling Gurobi.
Let me explain in a schematic way my setting.
(1) x is the unknown and it is a column vector with size 225x1.
(2) The objective function (which should be minimised wrto x) looks like
which can be rewritten as
I have a Matlab script computing alpha, Q,c (Q,c sparse) when some_known_parameters1 are given:
function [alpha, Q,c]=matrix_objective_function(some_known_parameters1)
%...
end
(3) The constraints are linear in x, include equalities and inequalities, and are written in the form
I have a Matlab script computing Aeq,beq,Aineq,bineq (Aeq,Aineq sparse) when some_known_parameters2 is given:
function [Aeq,beq,Aineq,bineq]=constraints(some_known_parameters2)
%...
end
(4) Some components of x are restricted to be in {0,1}. I have a Matlab script producing a string of letters B (binary), C (continous) when some_known_parameters3 is given:
function type=binary_continuous(some_known_parameters3)
%...
end
Now, I need to put together (1)-(4) using Gurobi. I am struggling to understand how. I found this example but it looks very cryptic to me. Below I report some lines I have attempted to write, but they are incomplete and I would like your help to complete them.
clear
rng default
%Define some_known_parameters1,
some_known_parameters2,some_known_parameters3 [...]
%1) generate alpha,Q,c,Aeq,beq,Aineq,bineq,type with Q,c,Aeq, Aineq sparse
[alpha, Q,c]=matrix_objective_function(some_known_parameters1)
[Aeq,beq,Aineq,bineq]=constraints(some_known_parameters2)
type=binary_continuous(some_known_parameters3)
%2) Set up Gurobi
clear model;
model.A=[Aineq; Aeq];
model.rhs=full([bineq(:); beq(:)]);
model.sense=[repmat('<', size(Aineq,1),1); repmat('=', size(Aeq,1),1)];
model.Q=Q; %not sure?
model.alpha=alpha; %not sure?
model.c=c; %not sure?
model.vtype=type;
result=gurobi(model); %how do I get just the objective function here without the minimiser?
Questions:
(1) I'm not sure about
model.Q=Q;
model.alpha=alpha;
model.c=c;
I'm just trying to set the matrices of the objective function using the letters provided here but it gives me error. The example here seems to me doing
model.Q=Q;
model.obj=c;
But then how do I set alpha? Is it ignoring it because it does not change the set of solutions?
(2) How do I get as output stored in a matrix just the minimum value of the objective function without the corresponding x?
(1) You're right, there's no need to pass the constant alpha since it doesn't affect the optimal solution. Gurobi's MATLAB API only accepts sparse matrices. Furthermore model.obj is always the c vector in the problem statement:
model.Q = sparse(Q);
model.obj = c;
(2) To get the optimal objective value, you first need to pass your model to gurobi and solve it. Then you can access it via the objval attribute:
results = gurobi(model);
val = results.objval + alpha

Matlab r2016a throwing error [duplicate]

I keep trying to run this and have no idea what is going wrong. I have it saved as test.m. I click run in the editor and in the matlab command window, it states not enough input arguments. I feel like I am missing something totally obvious, but I cannot spot the issue.
function y = test(A, x)
%This function computes the product of matrix A by vector x row-wise
% define m number of rows here to feed into for loop
[ma,na] = size(A);
[mx,nx] = size(x);
% use if statement to check for proper dimensions
if(na == mx && nx == 1)
y = zeros(ma,1); % initialize y vector
for n = 1:ma
y(n) = A(n,:)*x;
end
else
disp('Dimensions of matrices do not match')
y = [];
end
end
It is a function (not an script) and it needs some input arguments to run (in this case A and x), so you cannot hit the run button and expect it to run.
The first way:
Instead you can use the command windows in MATLAB and enter the command:
A = rand(3,3); % define A here
x = ones(3,1); % define x here
test(A,x) % then run the function with its arguments
remember that A and x should be defined properly.
The second way is:
Also you can hit the little triangle besides the green run button (see the figure below), and it will show you another option, type command to run. And
there you can directly enter the same command test(A,x). After that, each time you just hit enter for this function and it runs this command instead of only the test command without any argument.
The third way:
function y = test(A, x)
%// TESTING CODE:
if nargin==0
A = default_value_for_A;
x = default_value_for_x;
end
... %// rest of the function code
This way allows you to "click the play button" and have your function run with no explicit input arguments. However, be advised that such a method should only be used:
When debugging, so as not to allow users to call the function with no arguments if this is not its intended use case.
If your function is not supposed to behave differently for a different number of inputs. See also function overloading in MATLAB based on number of input arguments.

MATLAB: Not enough input arguments [duplicate]

I keep trying to run this and have no idea what is going wrong. I have it saved as test.m. I click run in the editor and in the matlab command window, it states not enough input arguments. I feel like I am missing something totally obvious, but I cannot spot the issue.
function y = test(A, x)
%This function computes the product of matrix A by vector x row-wise
% define m number of rows here to feed into for loop
[ma,na] = size(A);
[mx,nx] = size(x);
% use if statement to check for proper dimensions
if(na == mx && nx == 1)
y = zeros(ma,1); % initialize y vector
for n = 1:ma
y(n) = A(n,:)*x;
end
else
disp('Dimensions of matrices do not match')
y = [];
end
end
It is a function (not an script) and it needs some input arguments to run (in this case A and x), so you cannot hit the run button and expect it to run.
The first way:
Instead you can use the command windows in MATLAB and enter the command:
A = rand(3,3); % define A here
x = ones(3,1); % define x here
test(A,x) % then run the function with its arguments
remember that A and x should be defined properly.
The second way is:
Also you can hit the little triangle besides the green run button (see the figure below), and it will show you another option, type command to run. And
there you can directly enter the same command test(A,x). After that, each time you just hit enter for this function and it runs this command instead of only the test command without any argument.
The third way:
function y = test(A, x)
%// TESTING CODE:
if nargin==0
A = default_value_for_A;
x = default_value_for_x;
end
... %// rest of the function code
This way allows you to "click the play button" and have your function run with no explicit input arguments. However, be advised that such a method should only be used:
When debugging, so as not to allow users to call the function with no arguments if this is not its intended use case.
If your function is not supposed to behave differently for a different number of inputs. See also function overloading in MATLAB based on number of input arguments.

What is a good substitute for matlabFunction?

I wrote a small program in MATLAB to compute the Shapley value
using the multi-linear extension of a TU game. However, I run
into trouble with the Symbolic Math Toolbox of MATLAB. In
the program I have to integrate a set of functions to get the
Shapley value. However, inside a MATLAB program I cannot use
the int() command
Error using sym/subsindex (line 663) Ivalid indexing or function definition. When defining a function, ensure that the body of the function is a SYM object. When indexing, the input must be numeric, logical or ':'.
Error in ShapleyValueML (line 65)shv(jj)=int(dfy,0,1)
as a consequence I have to use integral() instead. In this case, I
need to transcribe the set of expressions into MATLAB function handle
with matlabFunction(). However, on all Linux machines (MATLAB R2014a) on
which I have access this command does not work (see the discussion below).
As a workaround, the MATLAB program returns the set of functions
into the current workspace, there the Shapley value can be computed
using the int() command.
To make the discussion more concrete, let us consider this small
MATLAB program first.
function [shv,F,dfm]=ShapleyValueML(v)
N=length(v);
[~, n]=log2(N);
S=1:N;
int=0:-1:1-n;
mat=(rem(floor(S(:)*pow2(int)),2)==1);
cmat=(rem(floor(S(:)*pow2(int)),2)==0);
x=sym('x',[1 n]);
mx=1-x;
y = sym('y');
vy=ones(1,n)*y;
F=0;
shv=zeros(1,n);
dfm=cell(1,n);
for ss=1:N
pd1=x(mat(ss,:));
pd2=mx(cmat(ss,:));
pd=prod(pd1)*prod(pd2)*v(ss);
F=pd+F;
end
F=expand(F);
for jj=1:n
dF=diff(F,x(jj));
dfy=subs(dF,x,vy);
%% Does not work!! MATLAB bug???
% mf=matlabFunction(dfy);
% shv(jj)=integral(mf,0,1);
%%
%% The best would be to use:
%%
% shv(jj)=int(dfy,0,1)
%% but it cannot be used inside a program.
dfm{jj}=dfy;
end
end
The commented parts are the parts that do not work inside
the program, but are needed to compute the Shapley value
with that program, which is its purpose. I tested this program
up to 12 players, and I was able to successfully calculate the
Shapley value by a two step procedure. Hence, the above program
specifies correctly the considered problem. To get a better
understanding of this two step procedure and of the functionality
of the above program, let us focus on a three person game.
The values of the coalitions are given by the following data array
>> v = [0,0,90,0,100,120,220];
Notice that coalitions are ordered in accordance with their unique
integer representations. The game is defined, we can now evaluate
the multi-linear extension and the set of partial derivatives with
the above program, but not the Shapley value.
>> [shv,F,dfm]=ShapleyValueML(v);
Integration of the set of partial derivatives runs over the diagonal
of the unit-cube, but then we can set the variables from [x1,x2,x3]
to [y,y,y], and integration runs from 0 to 1.
>> for k=1:3, shv(k)=int(dfm{k},0,1);end;
The solution of the integration is the Shapley value given by:
>> shv
shv =
65 75 80
Checking that this is indeed the Shapley value can be accomplished
with a potential function approach implemented in
>> sh_v=ShapleyValue(v)
sh_v =
65 75 80
that ships with my MATLAB Game Theory Toolbox MatTuGames from
http://www.mathworks.com/matlabcentral/fileexchange/35933-mattugames
Instead of integrating with int() one can also use integral(),
but then the contents like
>> dfm{1}
ans =
- 90*y^2 + 190*y
must be rewritten with matlabFunction() into a function handle. As I
have mentioned above this does not work under Linux
(MATLAB R2013a,R2013b,R2014a). To see this let us try to reproduce
the example
>> syms x y
>> r = sqrt(x^2 + y^2);
from the documentation at the URL:
http://www.mathworks.de/de/help/symbolic/generate-matlab-functions.html?searchHighlight=matlabFunction
This should give
ht =
#(x,y)tanh(sqrt(x.^2+y.^2))
but I get
>> ht = matlabFunction(tanh(r))
Cell contents reference from a non-cell array object.
Error in vectorize (line 15)
c = cells{i};
Error in sym/matlabFunction>mup2mat (line 319)
res = vectorize(res(2:end-1)); % remove quotes
Error in sym/matlabFunction>mup2matcell (line 304)
r = mup2mat(c{1});
Error in sym/matlabFunction (line 123)
body = mup2matcell(funs);
Here comes now my question: Exists there an alternative procedure to
get from
>> dfm{1}
ans =
- 90*y^2 + 190*y
a function handle
>> df=#(y) (- 90.*y.^2 + 190.*y)
df =
#(y)(-90.*y.^2+190.*y)
to integrate it by
>> integral(df,0,1)
ans =
65
Or to put it differently. Is there an alternative method available to
change multiplication * to element-wise multiplication .*, and the
power operation ^ to element-wise power.^?
Of course, any suggestions of improvement for the above MATLAB program
are highly appreciated.
I think I know what the problem is; Towards the beginning of ShapleyValueML function, you have a variable named int which shadows the builtin integration function:
...
int=0:-1:1-n; %# <-- problem!
...
shv(jj)=int(dfy,0,1)
...
That explains the error coming from sym/subsindex, you were using a symbolic object as an index into the numeric array int.
Change the variable name to something else, and the commented code runs fine (the symbolic integration)! Simple as that :)

MATLAB not enough input arguments

I keep trying to run this and have no idea what is going wrong. I have it saved as test.m. I click run in the editor and in the matlab command window, it states not enough input arguments. I feel like I am missing something totally obvious, but I cannot spot the issue.
function y = test(A, x)
%This function computes the product of matrix A by vector x row-wise
% define m number of rows here to feed into for loop
[ma,na] = size(A);
[mx,nx] = size(x);
% use if statement to check for proper dimensions
if(na == mx && nx == 1)
y = zeros(ma,1); % initialize y vector
for n = 1:ma
y(n) = A(n,:)*x;
end
else
disp('Dimensions of matrices do not match')
y = [];
end
end
It is a function (not an script) and it needs some input arguments to run (in this case A and x), so you cannot hit the run button and expect it to run.
The first way:
Instead you can use the command windows in MATLAB and enter the command:
A = rand(3,3); % define A here
x = ones(3,1); % define x here
test(A,x) % then run the function with its arguments
remember that A and x should be defined properly.
The second way is:
Also you can hit the little triangle besides the green run button (see the figure below), and it will show you another option, type command to run. And
there you can directly enter the same command test(A,x). After that, each time you just hit enter for this function and it runs this command instead of only the test command without any argument.
The third way:
function y = test(A, x)
%// TESTING CODE:
if nargin==0
A = default_value_for_A;
x = default_value_for_x;
end
... %// rest of the function code
This way allows you to "click the play button" and have your function run with no explicit input arguments. However, be advised that such a method should only be used:
When debugging, so as not to allow users to call the function with no arguments if this is not its intended use case.
If your function is not supposed to behave differently for a different number of inputs. See also function overloading in MATLAB based on number of input arguments.