Dynamic-Calibration/utils/YALMIP-master/extras/@ncvar/norm.m

262 lines
11 KiB
Matlab
Executable File

function varargout = norm(varargin)
%NORM (overloaded)
%
% t = NORM(x,P)
%
% The variable t can only be used in convexity preserving
% operations such as t<0, max(t,y)<1, minimize t etc.
%
% For matrices...
% NORM(X) models the largest singular value of X, max(svd(X)).
% NORM(X,2) is the same as NORM(X).
% NORM(X,1) models the 1-norm of X, the largest column sum, max(sum(abs(X))).
% NORM(X,inf) models the infinity norm of X, the largest row sum, max(sum(abs(X'))).
% NORM(X,'fro') models the Frobenius norm, sqrt(sum(diag(X'*X))).
% For vectors...
% NORM(V) = norm(V,2) = standard Euclidean norm.
% NORM(V,inf) = max(abs(V)).
% NORM(V,1) = sum(abs(V))
%
% SEE ALSO SUMK, SUMABSK
%% ***************************************************
% This file defines a nonlinear operator for YALMIP
%
% It can take three different inputs
% For DOUBLE inputs, it returns standard double values
% For SDPVAR inputs, it generates an internal variable
%
% When first input is 'model' it returns the graph
% in the first output and structure describing some
% properties of the operator.
%% ***************************************************
switch class(varargin{1})
case 'double' % What is the numerical value of this argument (needed for displays etc)
% SHOULD NEVER HAPPEN, THIS SHOULD BE CAUGHT BY BUILT-IN
error('Overloaded SDPVAR/NORM CALLED WITH DOUBLE. Report error')
case 'sdpvar' % Overloaded operator for SDPVAR objects. Pass on args and save them.
if nargin == 1
varargout{1} = yalmip('addextendedvariable',mfilename,varargin{1},2);
else
switch varargin{2}
case {1,2,inf,'inf','fro'}
varargout{1} = yalmip('addextendedvariable',mfilename,varargin{:});
otherwise
error('norm(x,P) only supported for P = 1, 2, inf and ''fro''');
end
end
case 'char' % YALMIP sends 'model' when it wants the epigraph or hypograph
switch varargin{1}
case 'graph'
t = varargin{2};
X = varargin{3};
p = varargin{4};
% Code below complicated by two things
% 1: Absolute value for complex data -> cone constraints on
% elements
% 2: SUBSREF does not call SDPVAR subsref -> use extsubsref.m
% FIX : Exploit symmetry to create smaller problem
switch p
case 1
z = sdpvar(size(X,1),size(X,2),'full');
if min(size(X))>1
if isreal(X)
F = (-z <= X <= z);
else
F = ([]);
for i = 1:size(X,1)
for j = 1:size(X,2)
xi = extsubsref(X,i,j);
zi = extsubsref(z,i,j);
F = F + (cone([real(xi);imag(xi)],zi));
end
end
end
F = F + (sum(z,1) <= t);
else
if isreal(X)
F = (-z <= X <= z) + (sum(z) <= t);
[M,m] = derivebounds(X);
bounds(z,0,max(abs([M -m]),[],2));
bounds(t,0,sum(max(abs([M -m]),[],2)));
else
F = ([]);
for i = 1:length(X)
xi = extsubsref(X,i);
zi = extsubsref(z,i);
F = F + (cone([real(xi);imag(xi)],zi));
end
F = F + (sum(z) <= t);
end
end
case 2
z = sdpvar(size(X,1),size(X,2));
if min(size(X))>1
F = ([t*eye(size(X,1)) X;X' t*eye(size(X,2))])>=0;
else
F = (cone(X(:),t));
end
case {inf,'inf'}
if min(size(X))>1
z = sdpvar(size(X,1),size(X,2),'full');
if isreal(X)
F = (-z <= X <= z);
else
F = ([]);
for i = 1:size(X,1)
for j = 1:size(X,2)
xi = extsubsref(X,i,j);
zi = extsubsref(z,i,j);
F = F + (cone([real(xi);imag(xi)],zi));
end
end
end
F = F + (sum(z,2) <= t);
else
if isreal(X)
F = (-t <= X <= t);
[M,m,infbound] = derivebounds(X);
if ~infbound
F = F + (0<=t<=max(M));
end
else
F = ([]);
for i = 1:length(X)
xi = extsubsref(X,i);
F = F + (cone([real(xi);imag(xi)],t));
end
end
end
case 'fro'
X.dim(1)=X.dim(1)*X.dim(2);
X.dim(2)=1;
F = (cone(X,t));
otherwise
end
varargout{1} = F;
varargout{2} = struct('convexity','convex','monotonicity','none','definiteness','positive');
varargout{3} = X;
case 'milp'
t = varargin{2};
X = varargin{3};
p = varargin{4};
if ~isreal(X) | isequal(p,2) | isequal(p,'fro') | min(size(X))>1 % Complex valued data, matrices and 2-norm not supported
varargout{1} = [];
varargout{2} = [];
varargout{3} = [];
else
if p==1
X = reshape(X,length(X),1);
absX = sdpvar(length(X),1);
d = binvar(length(X),1);
[M,m] = derivebounds(X);
F = ([]);
positive = find(m >= 0);
negative = find(M <= 0);
% d(find(positive)) = 1;
% d(find(negative)) = 0;
if ~isempty(positive)
d = subsasgn(d,struct('type','()','subs',{{positive}}),1);
end
if ~isempty(negative)
d = subsasgn(d,struct('type','()','subs',{{negative}}),0);
end
F = F + (X <= M.*d) + (2*m.*d <= absX+X <= 2*M.*d);
F = F + (X >= m.*(1-d)) + (2*m.*(1-d) <= absX-X <= 2*M.*(1-d));
F = F + (t - sum(absX) == 0);
else
if 0
%2^n cases
%e.g in 2d,
%norm([x;y],inf) = y, y>0, y>x.y>-x
% = x, x>0, x>y.x>-y
n = length(X);
X = reshape(X,n,1);
absX = sdpvar(n,1);
d = binvar(n,1);
[M,m] = derivebounds(X);
F = (sum(d)==0);
top = 1;
for i = 1:n
xi = extsubsref(X,i);
y = extsubsref(X,setdiff(1:n,i));
for sign_abs_largest_variable = -1:2:1
di = extsubsref(d,top);
for j = setdiff(1:n,i)
y = extsubsref(X,j);
for sign_other = -1:2:1
F = F + (xi*sign_abs_largest_variable >= sign_other*y);
F = F + (-M*100*(1-di) <= xi*sign_abs_largest_variable-t <= t+M*100*(1-di));
end
end
top = top + 1;
end
end
else
% OLD
n = length(X);
X = reshape(X,n,1);
absX = sdpvar(n,1);
d = binvar(n,1);
[M,m] = derivebounds(X);
F = ([]);
F = F + (X <= M.*d) + (2*m.*d <= absX+X <= 2*M.*d);
F = F + (X >= m.*(1-d)) + (2*m.*(1-d) <= absX-X <= 2*M.*(1-d));
M = max(M,-m);
d = binvar(n,1);
F = F + (sum(d)==1);
F = F + (absX <= t <= absX + M.*(1-d));
kk = [];
ii = [];
for i = 1:n
k = [1:1:i-1 i+1:1:n]';
ii = [ii;repmat(i,n-1,1)];
kk = [kk;k];
Mm = M(k);
end
xii = extsubsref(absX,ii);
dii = extsubsref(d,ii);
xkk = extsubsref(absX,kk);
F = F + (xkk <= xii+(M(kk)-m(ii)).*(1-dii));
end
% for i = 1:n
% xi = extsubsref(absX,i);
% di = extsubsref(d,i);
% for k = [1:1:i-1 i+1:1:n]
% xk = extsubsref(absX,k);
% F = F + (xk <= xi+M(k)*(1-di));
% end
% end
end
varargout{1} = F;
varargout{2} = struct('convexity','milp','monotonicity','milp','definiteness','positive');
varargout{3} = X;
end
otherwise
error('SDPVAR/NORM called with CHAR argument?');
end
otherwise
error('Strange type on first argument in SDPVAR/NORM');
end