176 lines
4.8 KiB
Matlab
Executable File
176 lines
4.8 KiB
Matlab
Executable File
function output = callipopt(model)
|
|
|
|
options = [];
|
|
try
|
|
options.ipopt = optiRemoveDefaults(model.options.ipopt,ipoptset());
|
|
catch
|
|
options.ipopt = model.options.ipopt;
|
|
end
|
|
options.ipopt.print_level = 2+model.options.verbose;
|
|
|
|
model = yalmip2nonlinearsolver(model);
|
|
|
|
if ~model.derivative_available
|
|
disp('Derivate-free call to ipopt not yet implemented')
|
|
error('Derivate-free call to ipopt not yet implemented')
|
|
end
|
|
if model.options.savedebug
|
|
save ipoptdebug model
|
|
end
|
|
showprogress('Calling IPOPT',model.options.showprogress);
|
|
|
|
% Figure out which variables are artificially introduced to normalize
|
|
% arguments in callback operators to simplify chain rules etc. We can do
|
|
% our function evaluations and gradient computations in our lifted world,
|
|
% but only expose the model in the original variables to the nonlinear
|
|
% solver.
|
|
% model = compressLifted(model);
|
|
|
|
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.c*0,[],[],problem,'IPOPT',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)
|
|
Z = jacobiansparsityfromnonlinear(model);
|
|
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;
|
|
if any(model.variabletype == 4)
|
|
problematic = find(any(model.monomtable(:,model.linearindicies) < 0 ,1));
|
|
if ~isempty(problematic)
|
|
problematic = problematic(find(model.x0(problematic)==0));
|
|
Oneisfeas = problematic(find(model.ub(problematic) > 1));
|
|
model.x0(Oneisfeas) = 1;
|
|
end
|
|
end
|
|
model.x0(find(model.lb==model.ub)) = model.lb(find(model.lb==model.ub));
|
|
end
|
|
|
|
% If quadratic objective and no nonlinear constraints, we can supply an
|
|
% Hessian of the Lagrangian
|
|
usedinObjective = find(model.c | any(model.Q,2));
|
|
if ~any(model.variabletype(usedinObjective)) & any(model.Q)
|
|
if length(model.bnonlinineq)==0 & length(model.bnonlineq)==0
|
|
H = model.Q(:,model.linearindicies);
|
|
H = H(model.linearindicies,:);
|
|
funcs.hessian = @(x,s,l) tril(2*H);
|
|
funcs.hessianstructure = @()tril(sparse(double(H | H)));
|
|
options.ipopt.hessian_approximation = 'exact';
|
|
end
|
|
end
|
|
|
|
solvertime = tic;
|
|
[xout,info] = ipopt(model.x0,funcs,options);
|
|
solvertime = toc(solvertime);
|
|
|
|
% Duals currently not supported
|
|
lambda = [];
|
|
|
|
if ~isempty(xout) && ~isempty(model.lift);
|
|
x = zeros(length(model.linearindicies),1);
|
|
x(model.lift.linearIndex) = xout(:);
|
|
x(model.lift.liftedIndex) = model.lift.T*xout(:) + model.lift.d;
|
|
x = RecoverNonlinearSolverSolution(model,x);
|
|
else
|
|
x = RecoverNonlinearSolverSolution(model,xout);
|
|
end
|
|
|
|
switch info.status
|
|
case {0,1}
|
|
problem = 0;
|
|
case {2}
|
|
problem = 1;
|
|
case {-1}
|
|
problem = 3;
|
|
case {3,4,-2,-3}
|
|
problem = 4;
|
|
case {-11,-12,-13}
|
|
problem = 7;
|
|
case {-10,-100,-101,-102,-199}
|
|
problem = 11;
|
|
otherwise
|
|
problem = -1;
|
|
end
|
|
|
|
% Internal format for duals
|
|
D_struc = [];
|
|
|
|
% Save all data sent to solver?
|
|
if model.options.savesolverinput
|
|
solverinput.model = model;
|
|
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,'IPOPT',solverinput,solveroutput,solvertime);
|
|
|
|
|