205 lines
6.3 KiB
Matlab
Executable File
205 lines
6.3 KiB
Matlab
Executable File
function output = call_cplexibm_miqp(interfacedata)
|
|
|
|
% Author Johan Löfberg
|
|
|
|
%Turn on support for nonconvex QP if required and user hasn't touched this
|
|
if interfacedata.ProblemClass.objective.quadratic.nonconvex
|
|
if isfield(interfacedata.options.cplex,'solutiontarget')
|
|
if ~interfacedata.options.cplex.solutiontarget
|
|
interfacedata.options.cplex.solutiontarget = 3;
|
|
end
|
|
else
|
|
interfacedata.options.cplex.solutiontarget = 3;
|
|
end
|
|
end
|
|
|
|
options = interfacedata.options;
|
|
[model,nonlinearremain] = yalmip2cplex(interfacedata);
|
|
|
|
if nonlinearremain
|
|
error('Nonlinear monomials remain when calling CPLEX. If you are using OPTIMIZER, ensure your model really is solvable by CPLEX for fixed parameters. If you still think so, please report this and ask for a feature improvement.');
|
|
end
|
|
if interfacedata.options.savedebug
|
|
save cplexdebug model
|
|
end
|
|
|
|
solvertime = tic;
|
|
[x,fval,exitflag,output,lambda] = localSolverCall(model);
|
|
solvertime = toc(solvertime);
|
|
if output.cplexstatus == 4 | output.cplexstatus == 119
|
|
% CPLEX reports infeasible OR unbounded
|
|
% Remove objective and resolve
|
|
model.H = model.H*0;
|
|
model.f = model.f*0;
|
|
solvertime = tic;
|
|
[x,fval,exitflag,output,lambda] = localSolverCall(model);
|
|
solvertime = toc(solvertime);
|
|
switch output.cplexstatus
|
|
case {1,101,102} % It was ok, hence it must have been unbounded
|
|
output.cplexstatus = 2;
|
|
case {3,103,106} % Infeasible, so original was infeasible
|
|
output.cplexstatus = 3; % Infeasible
|
|
otherwise
|
|
output.cplexstatus = 4; % I give up
|
|
end
|
|
end
|
|
|
|
% Inconstency in early version of CPLEX
|
|
dots = find(interfacedata.solver.subversion == '.');
|
|
if length(dots)>1
|
|
interfacedata.solver.subversion(dots(2:end))=[];
|
|
end
|
|
if str2num(interfacedata.solver.subversion)>=12.3
|
|
the_sign = 1;
|
|
else
|
|
the_sign = -1;
|
|
end
|
|
if ~isempty(lambda)
|
|
D_struc = [the_sign*lambda.eqlin;the_sign*lambda.ineqlin];
|
|
else
|
|
D_struc = [];
|
|
end
|
|
|
|
if size(x,1) == length(model.f)
|
|
if ~isempty(model.NegativeSemiVar)
|
|
x(model.NegativeSemiVar,:) = -x(model.NegativeSemiVar,:);
|
|
end
|
|
end
|
|
|
|
showprogress('Calling CPLEX-IBM',options.showprogress);
|
|
% Check, currently not exhaustive...
|
|
switch output.cplexstatus
|
|
case {1,101,102}
|
|
problem = 0;
|
|
case {3,103,106}
|
|
problem = 1; % Infeasible
|
|
case {2,20,21,118,133}
|
|
problem = 2; % Unbounded
|
|
case {4,119}
|
|
problem = 15;
|
|
case {10,11,104,105,107,108,111,112}
|
|
problem = 3; % Iteration/time
|
|
case 119
|
|
problem = 15;
|
|
case {5,6,109,110}
|
|
problem = 4; % Numerics
|
|
case 24
|
|
problem = 11;
|
|
otherwise
|
|
problem = -1;
|
|
end
|
|
|
|
infostr = yalmiperror(problem,'CPLEX-IBM');
|
|
|
|
% Save all data sent to solver?
|
|
if options.savesolverinput
|
|
solverinput.model = model;
|
|
else
|
|
solverinput = [];
|
|
end
|
|
|
|
% Save all data from the solver?
|
|
if options.savesolveroutput
|
|
solveroutput.x = x;
|
|
solveroutput.fval = fval;
|
|
solveroutput.exitflag = exitflag;
|
|
solveroutput.lambda = lambda;
|
|
solveroutput.output = output;
|
|
else
|
|
solveroutput = [];
|
|
end
|
|
|
|
if isempty(x)
|
|
x = zeros(length(model.f),1);
|
|
end
|
|
|
|
% Standard interface
|
|
output = createOutputStructure(x,D_struc,[],problem,infostr,solverinput,solveroutput,solvertime);
|
|
|
|
function [x,fval,exitflag,output,lambda] = localSolverCall(model)
|
|
|
|
H = model.H;
|
|
f = model.f;
|
|
Aineq = model.Aineq;
|
|
bineq = model.bineq;
|
|
Aeq = model.Aeq;
|
|
beq = model.beq;
|
|
lb = model.lb;
|
|
ub = model.ub;
|
|
x0 = model.x0;
|
|
options.cplex = model.options;
|
|
options.verbose = model.verbose;
|
|
integer_variables = model.integer_variables;
|
|
binary_variables = model.binary_variables;
|
|
semicont_variables = model.semicont_variables;
|
|
K = model.K;
|
|
ctype = model.ctype;
|
|
|
|
fixedAineqBug = 0;
|
|
if isempty(Aineq) & isempty(Aeq)
|
|
Aineq = zeros(1,length(f)) ;
|
|
bineq = 1;
|
|
fixedAineqBug = 1;
|
|
end
|
|
if isempty(integer_variables) & isempty(binary_variables) & isempty(semicont_variables) & isempty(K.sos.type)
|
|
if options.verbose
|
|
if isempty(H)
|
|
[x,fval,exitflag,output,lambda] = cplexlp(f,Aineq,bineq,Aeq,beq,lb,ub,x0,options.cplex);
|
|
else
|
|
[x,fval,exitflag,output,lambda] = cplexqp(H,f,Aineq,bineq,Aeq,beq,lb,ub,x0,options.cplex);
|
|
end
|
|
else
|
|
if isempty(H)
|
|
evalc('[x,fval,exitflag,output,lambda] = cplexlp(f,Aineq,bineq,Aeq,beq,lb,ub,x0,options.cplex);');
|
|
else
|
|
evalc('[x,fval,exitflag,output,lambda] = cplexqp(H,f,Aineq,bineq,Aeq,beq,lb,ub,x0,options.cplex);');
|
|
end
|
|
end
|
|
if ~isempty(lambda) & fixedAineqBug
|
|
lambda.ineqlin = [];
|
|
end
|
|
else
|
|
if options.verbose
|
|
if isempty(H)
|
|
[x,fval,exitflag,output] = cplexmilp(f,Aineq,bineq,Aeq,beq,K.sos.type,K.sos.variables,K.sos.weight,lb,ub,ctype,x0,options.cplex);
|
|
else
|
|
[x,fval,exitflag,output] = cplexmiqp(H,f,Aineq,bineq,Aeq,beq,K.sos.type,K.sos.variables,K.sos.weight,lb,ub,ctype,x0,options.cplex);
|
|
end
|
|
else
|
|
if isempty(H)
|
|
evalc('[x,fval,exitflag,output] = cplexmilp(f,Aineq,bineq,Aeq,beq,K.sos.type,K.sos.variables,K.sos.weight,lb,ub,ctype,x0,options.cplex);');
|
|
else
|
|
evalc('[x,fval,exitflag,output] = cplexmiqp(H,f,Aineq,bineq,Aeq,beq,K.sos.type,K.sos.variables,K.sos.weight,lb,ub,ctype,x0,options.cplex);');
|
|
end
|
|
end
|
|
lambda = [];
|
|
end
|
|
|
|
function [x,fval,exitflag,output] = cplexmilpInternal(f,Aineq,bineq,Aeq,beq,sostype,sosvariables,sosweight,lb,ub,ctype,x0,options)
|
|
|
|
cplex = Cplex;
|
|
cplex.Model.sense = 'minimize';
|
|
cplex.Model.obj = f;
|
|
cplex.Model.lb = lb;
|
|
cplex.Model.ub = ub;
|
|
cplex.Model.ctype = ctype;
|
|
cplex.Model.A = [Aeq;Aineq];
|
|
cplex.Model.lhs = [beq;-inf(length(bineq),1)];
|
|
cplex.Model.rhs = [beq;bineq];
|
|
if options.mip.pool.intensity
|
|
cplex.Param.mip.pool.intensity.Cur = options.mip.pool.intensity;
|
|
cplex.Param.mip.pool.capacity.Cur = options.mip.pool.capacity;
|
|
cplex.Param.mip.pool.absgap.Cur = options.mip.pool.absgap;
|
|
cplex.Param.mip.pool.relgap.Cur = options.mip.pool.relgap;
|
|
cplex.Param.mip.pool.replace.Cur = options.mip.pool.replace;
|
|
end
|
|
temp = cplex.solve();
|
|
output.cplexstatus = temp.status;
|
|
fval = cplex.Solution.objval;
|
|
x = cplex.Solution.x;
|
|
if options.mip.pool.intensity
|
|
for i = 2:1:length(temp.pool.solution)
|
|
x = [x temp.pool.solution(i).x];
|
|
end
|
|
end
|
|
exitflag = temp.statusstring; |