Dynamic-Calibration/utils/YALMIP-master/@sdpvar/nonlineartocone.m

67 lines
1.8 KiB
Mathematica
Raw Permalink Normal View History

2019-12-18 11:25:45 +00:00
function [Fconv,info] = nonlineartocone(F)
%NONLINEARTOCONE Convert nonlinear constraint to second order cone
if islinear(F)
Fconv = F;
info = 0;
return
end
[n,m]=size(F);
if (n*m==1)
Fconv = [];
% Involved in polynomial constraints
sqrList = yalmip('nonlinearvariables');
h = sort(unique(sqrList));
% % SDP relaxation
for i = 1:size(sqrList,1)
left_index = find(h==sqrList(i,1));
x1_index = find(h==sqrList(i,2));
x2_index = find(h==sqrList(i,3));
Z{i}=zeros(length(h),length(h));
if x1_index==x2_index
Z{i}(x2_index,x1_index) = 1;
else
Z{i}(x1_index,x2_index) = 0.5;
Z{i}(x2_index,x1_index) = 0.5;
end
end
vars = getvariables(F);
base = getbase(F);
nonlinvars = find(ismember(vars,sqrList(:,1)));
linvars = find(~ismember(vars,sqrList(:,1)));
% Construct quadratic
Q = zeros(length(h));
for i = 1:length(nonlinvars)
indexinlist = find(vars(nonlinvars(i))==sqrList(:,1));
indexinh = find(vars(nonlinvars(i))==h);
Q = Q-Z{indexinlist}*base(1+find(h(indexinh)==vars));
end
used = find(any(Q));
[B,r] = chol(Q(used,used));
if r==0
linear = base(1);
if ~isempty(linvars)
linear = linear+base(1+find(ismember(linvars,vars)))*recover(linvars);
end
ConesAxb=[2*B*recover(h(used));1-linear];
Conescxd=1+linear;
Fconv = cone(ConesAxb,Conescxd);
info = 0;
else
Fconv = F;
if nargout == 2
info = 1;
else
warning('Cannot re-write to second order cone constraint');
end
end
else
if nargout == 2
Fconv = F;
info = 1;
else
error('nonlineartocone can only be applied to scalar inequalities')
end
end