Dynamic-Calibration/utils/YALMIP-master/extras/yalmip2nonlinearsolver.m

242 lines
6.8 KiB
Matlab
Executable File

function model = yalmip2nonlinearsolver(model)
global newmodel
newmodel = 1;
model.dense = 0;
if ~model.equalitypresolved
model = propagate_bounds_from_equalities(model);
end
K = model.K;
lb = model.lb;
ub = model.ub;
x0 = model.x0;
c = model.c;
% Pick out the positive conditions from cones ||Ax+b|| <= c'*x+d which will
% be treated as (Ax+b)'*(ax+b) <= (c'*x+d)^2, c'*x+d >= 0
if any(K.q)
aux = [];
top = 1 + K.f + K.l;
for i = 1:length(K.q)
row = model.F_struc(top,:);
if any(row(2:end))
aux = [aux;row];
end
top = top + model.K.q(i);
end
model.F_struc = [model.F_struc(1:K.f+K.l,:);aux;model.F_struc(K.f+K.l+1:end,:)];
model.K.l = model.K.l + size(aux,1);
end
if isempty(model.evaluation_scheme)
model = build_recursive_scheme(model);
end
model = compress_evaluation_scheme(model);
% Do some pre-calc to be used in calls from fmincon
nonlinearindicies = union(find(model.variabletype~=0),model.evalVariables);
linearindicies = setdiff(find(model.variabletype==0),nonlinearindicies);
model.nonlinearindicies = nonlinearindicies;
model.linearindicies = linearindicies;
model.Anonlinineq = [];
model.bnonlinineq = [];
model.Anonlineq = [];
model.bnonlineq = [];
% Extract linear and nonlinear equality constraints
if K.f>0
Aeq = -model.F_struc(1:1:K.f,2:end);
beq = model.F_struc(1:1:model.K.f,1);
nonlinear_equalities_indicies = find(any(Aeq(:,nonlinearindicies),2));
model.Anonlineq = Aeq(nonlinear_equalities_indicies,:);
model.bnonlineq = beq(nonlinear_equalities_indicies);
Aeq(nonlinear_equalities_indicies,:) = [];
beq(nonlinear_equalities_indicies,:) = [];
Aeq(:,nonlinearindicies) = [];
model.F_struc(1:model.K.f,:) = [];
model.K.f = 0;
else
Aeq = [];
beq = [];
end
% Find nonlinear eualities implied by lower and upper bounds
if ~isempty(ub) && ~isempty(lb)
nonlinearequality = find(lb(nonlinearindicies) == ub(nonlinearindicies));
if ~isempty(nonlinearequality)
for i = 1:length(nonlinearequality)
model.Anonlineq = [model.Anonlineq;eyev(length(c),nonlinearindicies(nonlinearequality(i)))'];
model.bnonlineq = [model.bnonlineq;lb(nonlinearindicies(nonlinearequality(i)))];
end
end
end
% Extract linear and nonlinear inequality constraints
if model.K.l>0
A = -model.F_struc(1:model.K.l,2:end);
b = model.F_struc(1:model.K.l,1);
nonlinear_inequalities_indicies = find(any(A(:,nonlinearindicies),2));
model.Anonlinineq = A(nonlinear_inequalities_indicies,:);
model.bnonlinineq = b(nonlinear_inequalities_indicies);
A(nonlinear_inequalities_indicies,:) = [];
b(nonlinear_inequalities_indicies,:) = [];
A(:,nonlinearindicies) = [];
model.F_struc(1:model.K.l,:) = [];
model.K.l = 0;
else
A = [];
b = [];
end
% This helps with robustness in bnb in some cases
x0candidate = zeros(length(c),1);
if ~isempty(lb) && ~isempty(ub)
bounded = find(~isinf(lb) & ~isinf(ub));
x0candidate(bounded) = (lb(bounded) + ub(bounded))/2;
bounded_below = find(~isinf(lb) & isinf(ub));
x0candidate(bounded_below) = lb(bounded_below) + 0.5;
bounded_above = find(~isinf(lb) & isinf(ub));
x0candidate(bounded_above) = lb(bounded_above) + 0.5;
end
if isempty(x0)
x0 = x0candidate(linearindicies);
else
if ~isempty(lb) && ~isempty(ub)
x0((x0 < lb) | (x0 > ub)) = x0candidate((x0 < lb) | (x0 > ub));
end
x0 = x0(linearindicies);
end
if ~isempty(lb)
lb = lb(linearindicies);
end
if ~isempty(ub)
ub = ub(linearindicies);
end
lb_old = lb;
ub_old = ub;
[lb,ub,A,b] = remove_bounds_from_Ab(A,b,lb,ub);
[lb,ub,Aeq,beq] = remove_bounds_from_Aeqbeq(Aeq,beq,lb,ub);
if any(model.variabletype == 4)
problematic = find(any(model.monomtable(:,linearindicies) < 0 ,1));
if ~isempty(problematic)
problematic = problematic(find(x0(problematic)==0));
Oneisfeas = problematic(find(ub(problematic) > 1));
x0(Oneisfeas) = 1;
end
problematic = find(any(model.monomtable(:,linearindicies)~=fix(model.monomtable(:,linearindicies)) ,1));
lb(problematic) = max(lb(problematic),0);
end
x0(find(lb==ub)) = lb(find(lb==ub));
if size(A,1) == 0
A = [];
end
if size(b,1) == 0
b = [];
end
if size(Aeq,1) == 0
Aeq = [];
end
if size(beq,1) == 0
beq = [];
end
if model.presolveequalities
if ~isempty(beq) & (~model.equalitypresolved | ~(isequal(lb,lb_old) & isequal(ub,ub_old)))
% This helps when there are artificial variables introduced to model
% nonlinear operators such as log(2*x+1)
p.F_struc = [beq -Aeq];
p.K.f = size(beq,1);
p.lb = lb;
p.ub = ub;
p.variabletype = zeros(1,length(lb));
p.binary_variables = [];
p.integer_variables = [];
p = propagate_bounds_from_equalities(p);
lb = p.lb;
ub = p.ub;
end
end
model.A = A;
model.b = b;
model.Aeq = Aeq;
model.beq = beq;
model.lb = lb;
model.ub = ub;
model.x0 = x0;
model = setup_fmincon_params(model);
% Check if all derivatives are available
model.derivative_available = 1;
for i = 1:length(model.evalMap)
if isempty(model.evalMap{i}.properties.derivative)
model.derivative_available = 0;
break
end
end
% Some precomputation of computational scheme for Jacobian
allA = [model.Anonlineq;model.Anonlinineq];
if any(model.K.q)
allA = [allA;model.F_struc(1+model.K.f + model.K.f:end,2:end)];
end
requested = any(allA',2);
[i,j] = find((model.deppattern(find(requested),:)));
requested(j) = 1;
if ~isempty(model.evalMap)
% Recursive stuff is only possible if we have evaluation-based
% operators
model.Crecursivederivativeprecompute = precomputeDerivative(model,requested);
end
% Some precomputation of computational scheme for gradient
requested = model.c | any(model.Q,2);
[i,j,k] = find((model.deppattern(find(requested),:)));
requested(j) = 1;
model.frecursivederivativeprecompute = precomputeDerivative(model,requested);
% Precomputed list of bilinear expressions, used in
% apply_recursive_differentiation
Bilinears = find(model.variabletype==1);
BilinearsList = zeros(length(model.c),2);
for i = Bilinears
vars = find(model.monomtable(i,:));
BilinearsList(i,:) = vars(:)';
end
model.Bilinears = Bilinears;
model.BilinearsList = BilinearsList;
% Precomputed list of quadratic expressions, used in
% apply_recursive_differentiation
Quadratics = find(model.variabletype==2);
QuadraticsList = zeros(length(model.c),2);
for i = Quadratics
vars = find(model.monomtable(i,:));
QuadraticsList(i,:) = vars(:)';
end
model.Quadratics = Quadratics;
model.QuadraticsList = QuadraticsList;
model.binary_variables = find(ismember(linearindicies,model.binary_variables));
model.integer_variables = find(ismember(linearindicies,model.integer_variables));
model.semicont_variables = find(ismember(linearindicies,model.semicont_variables));