Dynamic-Calibration/utils/YALMIP-master/solvers/callipopt.m

176 lines
4.8 KiB
Mathematica
Raw Permalink Normal View History

2019-12-18 11:25:45 +00:00
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);