187 lines
4.7 KiB
Mathematica
187 lines
4.7 KiB
Mathematica
|
|
function output = callbonmin(model)
|
||
|
|
|
||
|
|
model = yalmip2nonlinearsolver(model);
|
||
|
|
options = [];
|
||
|
|
try
|
||
|
|
options.bonmin = optiRemoveDefaults(model.options.bonmin,bonminset());
|
||
|
|
catch
|
||
|
|
options.bonmin = model.options.bonmin;
|
||
|
|
end
|
||
|
|
options.ipopt = model.options.ipopt;
|
||
|
|
options.display = model.options.verbose;
|
||
|
|
|
||
|
|
if ~model.derivative_available
|
||
|
|
disp('Derivate-free call to bonmin/ipopt not yet implemented')
|
||
|
|
error('Derivate-free call to bonmin/ipopt not yet implemented')
|
||
|
|
end
|
||
|
|
|
||
|
|
if model.options.savedebug
|
||
|
|
save bonmindebug model
|
||
|
|
end
|
||
|
|
|
||
|
|
Fupp = [ repmat(0,length(model.bnonlinineq)+length(model.K.q)*(model.K.q(1)>0),1);
|
||
|
|
repmat(0,length(model.bnonlineq),1);
|
||
|
|
repmat(0,length(model.b),1);
|
||
|
|
repmat(0,length(model.beq),1)];
|
||
|
|
|
||
|
|
Flow = [ repmat(-inf,length(model.bnonlinineq)+length(model.K.q)*(model.K.q(1)>0),1);
|
||
|
|
repmat(0,length(model.bnonlineq),1);
|
||
|
|
repmat(-inf,length(model.b),1);
|
||
|
|
repmat(0,length(model.beq),1)];
|
||
|
|
|
||
|
|
if isempty(Flow)
|
||
|
|
Flow = [];
|
||
|
|
Fupp = [];
|
||
|
|
end
|
||
|
|
|
||
|
|
% Since ipopt react strangely on lb>ub, we should bail if that is detected
|
||
|
|
% (ipopt creates an exception)
|
||
|
|
if ~isempty(model.lb)
|
||
|
|
if any(model.lb>model.ub)
|
||
|
|
problem = 1;
|
||
|
|
solverinput = [];
|
||
|
|
solveroutput = [];
|
||
|
|
output = createoutput(model.lb*0,[],[],problem,'BONMIN',solverinput,solveroutput,0);
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
% These are needed to avoid recomputation due to ipopts double call to get
|
||
|
|
% f and df, and g and dg
|
||
|
|
global latest_x_f
|
||
|
|
global latest_x_g
|
||
|
|
global latest_df
|
||
|
|
global latest_f
|
||
|
|
global latest_G
|
||
|
|
global latest_g
|
||
|
|
global latest_xevaled
|
||
|
|
global latest_x_xevaled
|
||
|
|
latest_G= [];
|
||
|
|
latest_g = [];
|
||
|
|
latest_x_f = [];
|
||
|
|
latest_x_g = [];
|
||
|
|
latest_xevaled = [];
|
||
|
|
latest_x_xevaled = [];
|
||
|
|
|
||
|
|
funcs.objective = @(x)ipopt_callback_f(x,model);
|
||
|
|
funcs.gradient = @(x)ipopt_callback_df(x,model);
|
||
|
|
if ~isempty(Fupp)
|
||
|
|
funcs.constraints = @(x)ipopt_callback_g(x,model);
|
||
|
|
funcs.jacobian = @(x)ipopt_callback_dg(x,model);
|
||
|
|
end
|
||
|
|
|
||
|
|
options.lb = model.lb(:)';
|
||
|
|
options.ub = model.ub(:)';
|
||
|
|
if ~isempty(Fupp)
|
||
|
|
options.cl = Flow;
|
||
|
|
options.cu = Fupp;
|
||
|
|
end
|
||
|
|
|
||
|
|
if ~isempty(Fupp)
|
||
|
|
m = length(model.lb);
|
||
|
|
allA=[model.Anonlinineq];
|
||
|
|
if size(model.F_struc,1) > 0
|
||
|
|
% These are SOCP cones
|
||
|
|
top = 1;
|
||
|
|
for i = 1:length(model.K.q)
|
||
|
|
rows = model.F_struc(top:top + model.K.q(i)-1,2:end)
|
||
|
|
allA = [allA;any(rows,1)];
|
||
|
|
end
|
||
|
|
end
|
||
|
|
allA = [allA;model.Anonlineq];
|
||
|
|
jacobianstructure = spalloc(size(allA,1),m,0);
|
||
|
|
depends = allA | allA;
|
||
|
|
for i = 1:size(depends,1)
|
||
|
|
vars = find(depends(i,:));
|
||
|
|
[ii,vars] = find(model.deppattern(vars,:));
|
||
|
|
vars = unique(vars);
|
||
|
|
s = size(jacobianstructure,1);
|
||
|
|
for j = 1:length(vars)
|
||
|
|
jacobianstructure(i,find(vars(j) == model.linearindicies)) = 1;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
allA=[model.A; model.Aeq];
|
||
|
|
depends = allA | allA;
|
||
|
|
jacobianstructure = [jacobianstructure;depends];
|
||
|
|
|
||
|
|
Z = sparse(jacobianstructure);
|
||
|
|
funcs.jacobianstructure = @() Z;
|
||
|
|
end
|
||
|
|
|
||
|
|
if ~model.options.usex0
|
||
|
|
model.x0 = (options.lb+options.ub)/2;
|
||
|
|
model.x0(isinf(options.ub)) = options.lb(isinf(options.ub))+1;
|
||
|
|
model.x0(isinf(options.lb)) = options.ub(isinf(options.lb))-1;
|
||
|
|
model.x0(isinf(model.x0)) = 0;
|
||
|
|
end
|
||
|
|
|
||
|
|
if ~isempty(model.binary_variables) | ~isempty(model.integer_variables)
|
||
|
|
options.var_type = zeros(length(model.linearindicies),1);
|
||
|
|
options.var_type(model.binary_variables) = -1;
|
||
|
|
options.var_type(model.integer_variables) = 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
showprogress('Calling BONMIN',model.options.showprogress);
|
||
|
|
solvertime = tic;
|
||
|
|
[xout,info] = bonmin(model.x0,funcs,options);
|
||
|
|
solvertime = toc(solvertime);
|
||
|
|
|
||
|
|
x = RecoverNonlinearSolverSolution(model,xout);
|
||
|
|
|
||
|
|
switch info.status
|
||
|
|
case {0,2}
|
||
|
|
problem = 0;
|
||
|
|
case 1
|
||
|
|
problem = 1;
|
||
|
|
case {-1}
|
||
|
|
problem = 3;
|
||
|
|
case {3}
|
||
|
|
problem = 15;
|
||
|
|
otherwise
|
||
|
|
problem = -1;
|
||
|
|
end
|
||
|
|
|
||
|
|
% Duals currently not supported
|
||
|
|
D_struc = [];
|
||
|
|
|
||
|
|
% Save all data sent to solver?
|
||
|
|
if model.options.savesolverinput
|
||
|
|
solverinput.x0 = model.x0;
|
||
|
|
solverinput.model = model;
|
||
|
|
solverinput.options = options;
|
||
|
|
else
|
||
|
|
solverinput = [];
|
||
|
|
end
|
||
|
|
|
||
|
|
% Save all data from the solver?
|
||
|
|
if model.options.savesolveroutput
|
||
|
|
solveroutput.x = xout;
|
||
|
|
solveroutput.info = info;
|
||
|
|
else
|
||
|
|
solveroutput = [];
|
||
|
|
end
|
||
|
|
|
||
|
|
% Standard interface
|
||
|
|
output = createoutput(x,D_struc,[],problem,'BONMIN',solverinput,solveroutput,solvertime);
|
||
|
|
|
||
|
|
|
||
|
|
% Code supplied by Jonatan Currie
|
||
|
|
function opts = removeDefaults(opts,defs)
|
||
|
|
oFn = fieldnames(opts);
|
||
|
|
for i = 1:length(oFn)
|
||
|
|
label = oFn{i};
|
||
|
|
if(isfield(defs,label))
|
||
|
|
if(ischar(opts.(label)))
|
||
|
|
if(strcmpi(defs.(label),opts.(label)))
|
||
|
|
opts = rmfield(opts,label);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
if(defs.(label) == opts.(label))
|
||
|
|
opts = rmfield(opts,label);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|