1 | function y = max(varargin) |
---|
2 | %MAX (overloaded) |
---|
3 | % |
---|
4 | % t = max(X,Y,DIM) |
---|
5 | % |
---|
6 | % Creates an internal structure relating the variable t with convex |
---|
7 | % operator max(X). |
---|
8 | % |
---|
9 | % The variable t is primarily meant to be used in convexity preserving |
---|
10 | % operations such as t><, minimize t etc. |
---|
11 | % |
---|
12 | % If the variable is used in a non-convexity preserving operation, such as |
---|
13 | % t>0, a mixed integer model will be derived. |
---|
14 | % |
---|
15 | % See built-in MAX for syntax. |
---|
16 | |
---|
17 | % Author Johan Löfberg |
---|
18 | % $Id: max.m,v 1.1 2006/08/10 18:00:21 joloef Exp $ |
---|
19 | |
---|
20 | % MAX is implemented as a nonlinear operator. |
---|
21 | % However, for performance issues, it is not |
---|
22 | % implemented in the default high-level way. |
---|
23 | % |
---|
24 | % The return of the double value and the |
---|
25 | % construction of the epigraph/milp is done |
---|
26 | % in the file model.m |
---|
27 | % |
---|
28 | % To study a better example of how to create |
---|
29 | % your own nonlinear operator, check the |
---|
30 | % function sdpvar/norm instead |
---|
31 | |
---|
32 | % To simplify code flow, code for different #inputs |
---|
33 | switch nargin |
---|
34 | case 1 |
---|
35 | % Three cases: |
---|
36 | % 1. One scalar input, return same as output |
---|
37 | % 2. A vector input should give scalar output |
---|
38 | % 3. Matrix input returns vector output |
---|
39 | X = varargin{1}; |
---|
40 | |
---|
41 | if max(size(X))==1 |
---|
42 | y = X; |
---|
43 | return |
---|
44 | elseif min(size(X))==1 |
---|
45 | y = yalmip('addextendedvariable','max',X); |
---|
46 | return |
---|
47 | else |
---|
48 | % This is just short-hand for general command |
---|
49 | y = max(X,[],1); |
---|
50 | end |
---|
51 | |
---|
52 | case 2 |
---|
53 | |
---|
54 | X = varargin{1}; |
---|
55 | Y = varargin{2}; |
---|
56 | [nx,mx] = size(X); |
---|
57 | [ny,my] = size(Y); |
---|
58 | if ~((nx*mx==1) | (ny*my==1)) |
---|
59 | % No scalar, so they have to match |
---|
60 | if ~((nx==ny) & (mx==my)) |
---|
61 | error('Array dimensions must match.'); |
---|
62 | end |
---|
63 | end |
---|
64 | |
---|
65 | % Convert to compatible matrices |
---|
66 | if nx*mx==1 |
---|
67 | X = X*ones(ny,my); |
---|
68 | nx = ny; |
---|
69 | mx = my; |
---|
70 | elseif ny==my |
---|
71 | Y = Y*ones(nx,mx); |
---|
72 | ny = nx; |
---|
73 | my = mx; |
---|
74 | end |
---|
75 | |
---|
76 | % Ok, done with error checks etc. |
---|
77 | y = yalmip('addextendedvariable','max',[reshape(X,1,[]);reshape(Y,1,[])]); |
---|
78 | y = reshape(y,nx,mx); |
---|
79 | |
---|
80 | case 3 |
---|
81 | |
---|
82 | X = varargin{1}; |
---|
83 | Y = varargin{2}; |
---|
84 | DIM = varargin{3}; |
---|
85 | |
---|
86 | if ~(isa(X,'sdpvar') & isempty(Y)) |
---|
87 | error('MAX with two matrices to compare and a working dimension is not supported.'); |
---|
88 | end |
---|
89 | |
---|
90 | if ~isa(DIM,'double') |
---|
91 | error('Dimension argument must be 1 or 2.'); |
---|
92 | end |
---|
93 | |
---|
94 | if ~(length(DIM)==1) |
---|
95 | error('Dimension argument must be 1 or 2.'); |
---|
96 | end |
---|
97 | |
---|
98 | if ~(DIM==1 | DIM==2) |
---|
99 | error('Dimension argument must be 1 or 2.'); |
---|
100 | end |
---|
101 | |
---|
102 | if DIM==1 |
---|
103 | % Create one extended variable per column |
---|
104 | y = []; |
---|
105 | for i = 1:size(X,2) |
---|
106 | inparg = extsubsref(X,1:size(X,1),i); |
---|
107 | if isa(inparg,'sdpvar') |
---|
108 | y = [y yalmip('addextendedvariable','max',inparg)]; |
---|
109 | else |
---|
110 | y = [y max(inparg)]; |
---|
111 | end |
---|
112 | end |
---|
113 | else |
---|
114 | % Re-use code recursively |
---|
115 | y = max(X',[],1)'; |
---|
116 | end |
---|
117 | |
---|
118 | otherwise |
---|
119 | error('Too many input arguments.'); |
---|
120 | end |
---|