Dynamic-Calibration/utils/YALMIP-master/extras/@lmi/envelope.m

145 lines
3.9 KiB
Matlab
Executable File

function [E,P] = envelope(C,x)
%ENVELOPE Create linear approximation of envelope of nonlinear constraint
%
% [E,P] = envelope(C,x)
%
% C: Constraint object involving nonlinear expresions
% x: Optional: The linear variables of interest (projection onto these will be performed)
% E: Constraint object representing the envelope approximation
% P: Optional: Polyhedral object representing E (MPT Toolbox object)
%
% Examples
%
% In order to derive the outer approximation in the original linear
% variables, the model has to be projected onto the linear variables
% This projetion based format requires MPT3
% sdpvar x u
% E = envelope([-1 <= x <= 1, u == x^3],[x;u]);
% plot(E)
% xx = (-1:0.01:1);hold on;plot(xx,xx.^3)
%
% E = envelope([-1 <= x <= 1,x+sin(pi*x) <= u <= 4-x^2],[x;u]);
% plot(E)
% xx = (-1:0.01:1);hold on;plot(xx,xx+sin(pi*xx),xx,4-xx.^2)
%
% Alternatively, we can create a model which adds the outer approximation
% cuts for the envelopes of the nonlinear variables, but keep the nonlinear
% variables, and then plot the projection of the outer approximation,
% keeping in mind that we now have to relax the nonlinear variables (this
% is the model which thus would be used in a branch&bound scheme)
% E = envelope([-1 <= x <= 1,x+sin(pi*x) <= u <= 4-x^2]);
% plot(E,[x;u],[],[],sdpsettings('relax',1))
% xx = (-1:0.01:1);hold on;plot(xx,xx+sin(pi*xx),xx,4-xx.^2)
% Author Johan Löfberg
[aux1,aux2,aux3,p] = export(C,[],sdpsettings('solver','bmibnb'));
if isempty(p)
if ~isempty(aux3)
aux3.info
end
error('Failed to export a model')
end
% Copied from bmibnb
p.EqualityConstraintState = ones(p.K.f,1);
p.InequalityConstraintState = ones(p.K.l,1);
p = compile_nonlinear_table(p);
%p = propagatequadratics(p,inf,-inf);
p = propagatequadratics(p);
p.high_monom_model=[];
p.originalModel = p;
p = presolveOneMagicRound(p);
[p,changed] = convert_sigmonial_to_sdpfun(p);
if changed
p = compile_nonlinear_table(p);
end
[p,changed] = convert_polynomial_to_quadratic(p);
if changed
p = compile_nonlinear_table(p);
p.EqualityConstraintState = ones(p.K.f,1);
p.InequalityConstraintState = ones(p.K.l,1);
end
p = presolveOneMagicRound(p);
% Copied from solvelower
p_cut = addBilinearVariableCuts(p);
p_cut = addEvalVariableCuts(p_cut);
p_cut = addMonomialCuts(p_cut);
%p_cut = addConvexityCuts(p_cut);
p_cut = mergeBoundsToModel(p_cut);
if nargin > 1
% Now project onto the variables of interest
for i = 1:length(x)
xi(i) = find(getvariables(x(i)) == p.used_variables);
end
A = -p_cut.F_struc(:,2:end);
b = p_cut.F_struc(:,1);
Akeep = A(:,xi);
A(:,xi)=[];
A = [Akeep A];
Ae = A(1:p_cut.K.f,:);
be = b(1:p_cut.K.f,:);
A = A(1+p_cut.K.f:end,:);
b = b(1+p_cut.K.f:end,:);
P = Polyhedron('A',A,'b',b,'Ae',full(Ae),'be',full(be));
P = projection(P,1:length(xi));
E = ismember(x,P);
else
z = recover(p_cut.used_variables);
% We might have introduced some local modelling variables here
m = size(p.F_struc,2)-1-length(z);
if m>0
z = [z;sdpvar(m,1)];
end
E = [];
top = 1;
if p_cut.K.f > 0
E = [E,p_cut.F_struc(1:p_cut.K.f,:)*[1;z]==0];
end
if p_cut.K.l > 0
E = [E,p_cut.F_struc(1+p_cut.K.f:p_cut.K.f + p_cut.K.l,:)*[1;z]>=0];
end
if p_cut.K.s(1) > 0
top = 1 + p_cut.K.f + p_cut.K.l;
for i = 1:length(p_cut.K.s)
n = p_cut.K.s(i);
M = p_cut.F_struc(top:top+n^2-1,:)*[1;z];
top = top + n^2;
E = [E,reshape(M,n,n)>=0];
end
end
end
function p = mergeBoundsToModel(p);
A = [];
b = [];
if ~isempty(p.lb)
A = [eye(length(p.c))];
b = p.ub;
end
if ~isempty(p.ub)
A = [A;-eye(length(p.c))];
b = [b;-p.lb];
end
infbounds = find(isinf(b));
A(infbounds,:)=[];
b(infbounds)=[];
if length(b)>0
p.F_struc = [p.F_struc(1:p.K.f,:);[b -A];p.F_struc(p.K.f+1:end,:)];
p.K.l = p.K.l + length(b);
end