145 lines
3.9 KiB
Matlab
Executable File
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|