1 | function varargout = nnz(varargin) |
---|
2 | %NNZ (overloaded) |
---|
3 | % |
---|
4 | % n = nnz(X) |
---|
5 | % |
---|
6 | % NNZ applied to a constraint counts the number of satisfied constraints. |
---|
7 | % |
---|
8 | % The NNZ operator is implemented using the concept of nonlinear operators |
---|
9 | % in YALMIP. NNZ(X) creates a new so called derived variable that can be |
---|
10 | % treated as any other variable in YALMIP. When SOLVESDP is issued, |
---|
11 | % logic constraints are added to the problem to model the NNZ operator. |
---|
12 | |
---|
13 | |
---|
14 | % Author Johan Löfberg |
---|
15 | % $Id: nnz.m,v 1.6 2006/05/15 20:00:39 joloef Exp $ |
---|
16 | |
---|
17 | switch class(varargin{1}) |
---|
18 | |
---|
19 | case 'constraint' |
---|
20 | varargout{1} = yalmip('addextendedvariable','nnz',varargin{1}); |
---|
21 | |
---|
22 | case 'char' |
---|
23 | t = varargin{2}; |
---|
24 | x = varargin{3}; |
---|
25 | switch varargin{1} |
---|
26 | case 'graph' |
---|
27 | x = set(x); |
---|
28 | if is(x,'elementwise') |
---|
29 | x = sdpvar(x); |
---|
30 | x = x(:); |
---|
31 | [M,m] = derivebounds(x); |
---|
32 | delta = binvar(length(x),1); |
---|
33 | F = set(x >= m.*(1-delta)) + set(sum(delta) == t); |
---|
34 | elseif is(x,'equality') |
---|
35 | x = sdpvar(x); |
---|
36 | x = x(:); |
---|
37 | [M,m,infbound] = derivebounds(x); |
---|
38 | if infbound |
---|
39 | warning('You have unbounded variables in IMPLIES leading to a lousy big-M relaxation.'); |
---|
40 | end |
---|
41 | delta = binvar(length(x),1); |
---|
42 | F = set(M.*(1-delta) >= x >= m.*(1-delta)) + set(sum(delta) == t); |
---|
43 | else |
---|
44 | error('Constraint type not supported in cardinality. Make a feature request'); |
---|
45 | end |
---|
46 | varargout{1} = F; |
---|
47 | varargout{2} = struct('convexity','concave','monotonicity','none','definiteness','none'); |
---|
48 | varargout{3} = x; |
---|
49 | |
---|
50 | otherwise |
---|
51 | x = set(x); |
---|
52 | if is(x,'elementwise') |
---|
53 | x = sdpvar(x); |
---|
54 | x = x(:); |
---|
55 | [M,m,infbound] = derivebounds(x); |
---|
56 | if infbound |
---|
57 | warning('You have unbounded variables in NNZ leading to a lousy big-M relaxation.'); |
---|
58 | end |
---|
59 | n = length(x); |
---|
60 | deltaD = binvar(n,1); |
---|
61 | deltaU = binvar(n,1); |
---|
62 | if all(ismember(getvariables(x),[yalmip('intvariables') yalmip('binvariables')])) |
---|
63 | % If an integer constraint not holds, it has to be |
---|
64 | % epsilon violated |
---|
65 | F = set((M+1e-4).*(1-deltaU)-1e-4 >= x >= m.*(1-deltaD)); |
---|
66 | else |
---|
67 | % User has to think harder him self |
---|
68 | F = set((M).*(1-deltaU) >= x >= m.*(1-deltaD)); |
---|
69 | end |
---|
70 | F = F + set(sum(deltaD) == t); |
---|
71 | F = F + set(deltaU + deltaD == 1); |
---|
72 | F = F + set(0 <= t <= n); |
---|
73 | elseif is(x,'equality') |
---|
74 | x = sdpvar(x); |
---|
75 | x = x(:); |
---|
76 | n = length(x); |
---|
77 | [M,m] = derivebounds(x); |
---|
78 | deltaZ = binvar(n,1); |
---|
79 | deltaNZU = binvar(n,1); |
---|
80 | deltaNZD = binvar(n,1); |
---|
81 | eps = 1e-4; |
---|
82 | % deltaZ forces x to be zero |
---|
83 | % deltaZU 1 is x > eps |
---|
84 | % deltaZU 1 is x < -eps |
---|
85 | F = set(M.*(1-deltaZ) >= x >= m.*(1-deltaZ)); |
---|
86 | F = set((M+eps).*deltaNZU-eps>= x >= eps + (m-eps).*deltaNZD); |
---|
87 | F = F + set(sum(deltaZ) == t); |
---|
88 | F = F + set(deltaZ + deltaNZU + deltaNZD == 1); |
---|
89 | F = F + set(0 <= t <= n); |
---|
90 | else |
---|
91 | error('Constraint type not supported in cardinality. Make a feature request'); |
---|
92 | end |
---|
93 | varargout{1} = F; |
---|
94 | varargout{2} = struct('convexity','milp','monotonicity','milp','definiteness','milp'); |
---|
95 | varargout{3} = x; |
---|
96 | end |
---|
97 | otherwise |
---|
98 | end |
---|