106 lines
3.3 KiB
Matlab
Executable File
106 lines
3.3 KiB
Matlab
Executable File
function [Fhull,t,y] = hull(varargin)
|
|
% HULL Construct a model of the convex hull
|
|
%
|
|
% H = hull(F1,F2,...)
|
|
%
|
|
% OUTPUT
|
|
% H : Constraint object describing the convex hull of the input constraints
|
|
%
|
|
% INPUT
|
|
% Fi : Constraint objects with constraints
|
|
%
|
|
% Note that the convex representation of the convex hull requires a lifting
|
|
% (introduction of auxially variables). Hence, if you have many set of
|
|
% constraints, your problem rapidly grows large.
|
|
%
|
|
% If you intend to use the hull operator in a parameterized fashion in an
|
|
% optimizer setting, you can declare the parameters in the last argument.
|
|
% These variables will then be considered as if the were constants
|
|
%
|
|
% H = hull(F1,F2,...,Parameters)
|
|
|
|
|
|
|
|
% Pull out the parameter if one is given
|
|
ParameterVariables = [];
|
|
if isa(varargin{end},'sdpvar')
|
|
Parameter = varargin{end};
|
|
ParameterVariables = getvariables(Parameter);
|
|
varargin = {varargin{1:end-1}};
|
|
end
|
|
N = length(varargin);
|
|
|
|
if N==1
|
|
Fhull = varargin{1};
|
|
t = [];
|
|
y = [];
|
|
end
|
|
|
|
% Pre-process to convert convex quadratic constraints to socp constraints.
|
|
% This makes the perspective code easier.
|
|
% We also wexpand all graph-operators etc to find out all involved
|
|
% variables and constraints
|
|
for i = 1:N
|
|
varargin{i} = convertquadratics(varargin{i});
|
|
varargin{i} = expandmodel(varargin{i},[]);
|
|
end
|
|
|
|
variables = [];
|
|
for i = 1:N
|
|
% quick fix
|
|
if isa(varargin{i},'constraint')
|
|
varargin{i} = lmi(varargin{i});
|
|
end
|
|
if ~(isa(varargin{i},'lmi') | isa(varargin{i},'socc'))
|
|
error('Hull can only be applied to linear constraints');
|
|
elseif ~(islinear(varargin{i}))
|
|
error('Hull can only be applied to linear and convex quadratic constraints');
|
|
end
|
|
variables = unique([variables depends(varargin{i})]);
|
|
variables = setdiff(variables,ParameterVariables);
|
|
end
|
|
|
|
if N == 1
|
|
Fhull = varargin{1};
|
|
return
|
|
end
|
|
|
|
% Define variables. To allow users to easily plot convex hulls, we mark the
|
|
% internally defined variables as auxilliary. YALMIP will then not plot
|
|
% w.r.t these variables
|
|
nInitial = yalmip('nvars');
|
|
y = sdpvar(repmat(length(variables),1,N),repmat(1,1,N));
|
|
t = sdpvar(N,1);
|
|
nNow = yalmip('nvars');
|
|
yalmip('addauxvariables',nInitial+1:nNow);
|
|
|
|
Fhull = lmi([]);
|
|
for i = 1:N
|
|
Fi = flatten(varargin{i});
|
|
tvariable = getvariables(t(i));
|
|
for j = 1:length(Fi.clauses)
|
|
Xi = Fi.clauses{j}.data;
|
|
if ~isempty(ParameterVariables)
|
|
Xitrue = Xi;
|
|
Xi = replace(Xi,Parameter,0);
|
|
end
|
|
local_variables = getvariables(Xi);
|
|
local_index = find(ismember(variables,local_variables));
|
|
new_variables = getvariables(y{i}(local_index));
|
|
Xipersp = brutepersp(Xi,tvariable,new_variables);
|
|
if ~isempty(ParameterVariables)
|
|
Fi.clauses{j}.data = Xipersp + t(i)*(Xitrue-Xi);
|
|
else
|
|
Fi.clauses{j}.data = Xipersp;
|
|
end
|
|
Fi.clauses{j}.handle = ['F(y_' num2str(i) ')'];
|
|
end
|
|
Fhull = Fhull + Fi;
|
|
end
|
|
Fhull = Fhull + [(sum([y{:}],2) == recover(variables)):'sum y_i == x'];
|
|
Fhull = Fhull + [(sum(t)==1):'Multipliers sum to 1'] + [(t>=0):'Positive multiplier'];
|
|
Fhull = expanded(Fhull,1);
|
|
yalmip('setdependence',[reshape([y{:}],[],1);t(:)],recover(variables));
|
|
%yalmip('setdependence',recover([10 11]),recover(variables));
|
|
yalmip('addauxvariables',getvariables([reshape([y{:}],[],1);t(:)]));
|
|
y = [y{:}]; |