1 | function F = lmi(X,handlestring,dummy,noprune,symmetryKnown) |
---|
2 | % The command lmi is obsolete, see help sdpvar/set |
---|
3 | |
---|
4 | % Author Johan Löfberg |
---|
5 | % $Id: lmi.m,v 1.26 2006/09/22 08:11:45 joloef Exp $ |
---|
6 | |
---|
7 | %superiorto('sdpvar') |
---|
8 | |
---|
9 | fast = 0; |
---|
10 | noprune = 0; |
---|
11 | symmetryKnown = 0; |
---|
12 | switch nargin |
---|
13 | case 0 |
---|
14 | F.clauses={}; |
---|
15 | F.LMIid = []; |
---|
16 | F.savedata = []; |
---|
17 | F = class(F,'lmi'); |
---|
18 | return |
---|
19 | case 1 |
---|
20 | handlestring = ''; |
---|
21 | % ok probably, check later |
---|
22 | case 2 |
---|
23 | if ~isa(handlestring,'char') |
---|
24 | error('The handle must be a string') |
---|
25 | end |
---|
26 | case 4 |
---|
27 | handlestring = ''; |
---|
28 | noprune = 1; |
---|
29 | case 5 |
---|
30 | handlestring = ''; |
---|
31 | symmetryKnown = 1; |
---|
32 | |
---|
33 | otherwise |
---|
34 | error('Wrong number of arguments') |
---|
35 | end |
---|
36 | |
---|
37 | F.clauses = {}; |
---|
38 | F.LMIid = []; |
---|
39 | F.savedata = []; |
---|
40 | |
---|
41 | try |
---|
42 | F = class(F,'lmi'); |
---|
43 | catch |
---|
44 | disp('Failure in creating SET object. Restart MATLAB and try again, or type clear classes') |
---|
45 | end |
---|
46 | |
---|
47 | % Return empty LMI in degenerate case |
---|
48 | if isempty(X) |
---|
49 | return |
---|
50 | end |
---|
51 | |
---|
52 | % 0 : Nothing (i.e error) |
---|
53 | % 1 : LMI |
---|
54 | % 2 : Elementwise |
---|
55 | % 3 : Equality |
---|
56 | % 4 : SOCC |
---|
57 | % 5 : Rotated Lorentz |
---|
58 | % 9 : KYP constraint |
---|
59 | %10 : Eigenvalue constraint |
---|
60 | %11 : Sum of square constraint |
---|
61 | %12 : Logic CNF |
---|
62 | %14 : Uncertain variable |
---|
63 | switch class(X) |
---|
64 | case 'lmi' |
---|
65 | F = X; |
---|
66 | return |
---|
67 | case 'char' |
---|
68 | try |
---|
69 | % Parse (check for old notation, take care of ||...|| notation) |
---|
70 | sdpvarExpr = parseLMI(X); |
---|
71 | % Old notation |
---|
72 | X = strrep(X,'.>','>'); |
---|
73 | X = strrep(X,'.<','<'); |
---|
74 | % X = strrep(X,'=','==');X = strrep(X,'====','=='); |
---|
75 | catch |
---|
76 | error(lasterr) |
---|
77 | end |
---|
78 | % Evaluate |
---|
79 | try |
---|
80 | Fi=evalin('caller',sdpvarExpr); |
---|
81 | switch class(Fi) |
---|
82 | case 'sdpvar' |
---|
83 | Fi = {Fi}; |
---|
84 | strict = 0; |
---|
85 | case 'constraint' |
---|
86 | [Fi,strict] = getlist(Fi); |
---|
87 | otherwise |
---|
88 | error('The string does not define an SDPVAR object') |
---|
89 | end |
---|
90 | |
---|
91 | catch |
---|
92 | error(lasterr) |
---|
93 | end |
---|
94 | |
---|
95 | case 'sdpvar' |
---|
96 | Fi = {X}; |
---|
97 | strict = 0; |
---|
98 | X='Numeric value'; |
---|
99 | |
---|
100 | case 'logic' |
---|
101 | Fi = {X}; |
---|
102 | strict = 0; |
---|
103 | X = 'Numeric value'; |
---|
104 | |
---|
105 | case 'constraint' |
---|
106 | [Fi,strict] = getlist(X); |
---|
107 | X='Numeric value'; |
---|
108 | |
---|
109 | otherwise |
---|
110 | error('The first argument should be an sdpvar object or string.') |
---|
111 | end |
---|
112 | |
---|
113 | % Return empty LMI in degenerate case |
---|
114 | if all(cellfun('isempty',Fi)) |
---|
115 | return |
---|
116 | end |
---|
117 | |
---|
118 | TypeofConstraint = zeros(length(Fi),1)-1; |
---|
119 | |
---|
120 | % support for SOS constraints placed in vector |
---|
121 | if length(Fi) == 1 |
---|
122 | if is(Fi{1},'sos') |
---|
123 | % Expand to a set of SOS constraints |
---|
124 | if ~issymmetric(Fi{1}) |
---|
125 | p = Fi{1}(:); |
---|
126 | for i = 1:length(p) |
---|
127 | Fi{i} = p(i); |
---|
128 | end |
---|
129 | TypeofConstraint = zeros(length(Fi),1)-1; |
---|
130 | strict = zeros(length(Fi),1)-1; |
---|
131 | end |
---|
132 | end |
---|
133 | end |
---|
134 | |
---|
135 | i = 1; |
---|
136 | while i <= length(Fi) |
---|
137 | thisFi = Fi{i}; |
---|
138 | if ~isempty(thisFi) |
---|
139 | if isa(thisFi,'logic') |
---|
140 | TypeofConstraint(i) = 12; |
---|
141 | else |
---|
142 | TypeofConstraint(i) = gethackflag(Fi{i}); |
---|
143 | end |
---|
144 | % User just sent a sdpvar object, interpret as X>0 |
---|
145 | if (TypeofConstraint(i)==0) |
---|
146 | TypeofConstraint(i) = 1; |
---|
147 | end |
---|
148 | |
---|
149 | if (TypeofConstraint(i)==1) & (symmetryKnown == 0) |
---|
150 | [n,m]=size(thisFi); |
---|
151 | if (n~=m) | ((TypeofConstraint(i) == 1) & (n*m==1)) | ~ishermitian(thisFi) |
---|
152 | TypeofConstraint(i) = 2; |
---|
153 | end |
---|
154 | end |
---|
155 | |
---|
156 | if TypeofConstraint(i) == 2 |
---|
157 | |
---|
158 | % remove constraint of the type set(0 >= 0) |
---|
159 | B = getbase(thisFi); |
---|
160 | if 0 |
---|
161 | % Detect constraint set(negative number >= 0) |
---|
162 | % removed due to problems with mpt toolbox |
---|
163 | candidates = find(B(:,1) < 0); |
---|
164 | if ~isempty(candidates) |
---|
165 | Bv = B(candidates,2:end); |
---|
166 | dummy = any(Bv,2); |
---|
167 | used = find(dummy); |
---|
168 | if length(used) < size(Bv,1) |
---|
169 | thisFi = thisFi(candidates(used)); |
---|
170 | if any(B(candidates(find(~dummy)),1) < 0) |
---|
171 | % error('Trivially infeasible : There are negative constants in this element-wise constraint.'); |
---|
172 | end |
---|
173 | end |
---|
174 | end |
---|
175 | end |
---|
176 | if ~noprune |
---|
177 | Bv = B(:,2:end); |
---|
178 | notused = find((~any(Bv,2)) & (B(:,1)>=0)); |
---|
179 | if ~isempty(notused) |
---|
180 | used = setdiff(1:size(Bv,1),notused);%find(any(Bv,2)) |
---|
181 | % if length(used)<size(Bv,1) |
---|
182 | thisFi = thisFi(used); |
---|
183 | % end |
---|
184 | end |
---|
185 | end |
---|
186 | end |
---|
187 | |
---|
188 | % save cleaned version |
---|
189 | Fi{i} = thisFi; |
---|
190 | |
---|
191 | switch TypeofConstraint(i) |
---|
192 | case {1,2,3,4,5,7,8,9,10,11,12,13,15} |
---|
193 | i = i + 1; |
---|
194 | otherwise |
---|
195 | error('Error in argument in LMI. Please report bug'); |
---|
196 | end |
---|
197 | end |
---|
198 | end |
---|
199 | |
---|
200 | % Special case for x<y<z<... |
---|
201 | % Merge into one constraint, gives nicer displays |
---|
202 | if all(TypeofConstraint == 2) & all(strict==strict(1)) |
---|
203 | if length(Fi)>1 |
---|
204 | vecF = []; |
---|
205 | sizes = zeros(length(Fi),1); |
---|
206 | % Speed up concatenation of merging |
---|
207 | for i = 1:length(Fi) |
---|
208 | sizes(i) = prod(size(Fi{i})); |
---|
209 | end |
---|
210 | if all(sizes == 1) |
---|
211 | vecF = [Fi{:}]'; |
---|
212 | else |
---|
213 | for i = 1:length(Fi) |
---|
214 | fi = Fi{i}; |
---|
215 | if sizes(i) > 1 |
---|
216 | % fi = Fi{i};fi = reshape(fi,sizes(i),1); |
---|
217 | fi = reshape(fi,prod(size(fi)),1); |
---|
218 | end |
---|
219 | vecF = [vecF;fi]; |
---|
220 | end |
---|
221 | end |
---|
222 | else |
---|
223 | vecF = reshape(Fi{1},prod(size(Fi{1})),1); |
---|
224 | end |
---|
225 | F.clauses{1}.data=vecF; |
---|
226 | F.clauses{1}.type = 2; |
---|
227 | F.clauses{1}.symbolic=X; |
---|
228 | F.clauses{1}.handle=handlestring; |
---|
229 | F.clauses{1}.strict = strict(1); |
---|
230 | F.clauses{1}.cut = 0; |
---|
231 | F.clauses{1}.expanded = 0; |
---|
232 | F.clauses{1}.lift = 0; |
---|
233 | F.LMIid = [F.LMIid yalmip('lmiid')]; |
---|
234 | else |
---|
235 | %start = yalmip('lmiid'); |
---|
236 | for i = 1:length(Fi) |
---|
237 | switch TypeofConstraint(i) |
---|
238 | case {1,2,3,4,5,7,8,9,10,11,12,13,15} |
---|
239 | F.clauses{i}.data=Fi{i}; |
---|
240 | F.clauses{i}.type = TypeofConstraint(i); |
---|
241 | F.clauses{i}.symbolic=X; |
---|
242 | F.clauses{i}.handle=handlestring; |
---|
243 | F.clauses{i}.strict = strict(i); |
---|
244 | F.clauses{i}.cut = 0; |
---|
245 | F.clauses{i}.expanded = 0; |
---|
246 | F.clauses{i}.lift = 0; |
---|
247 | F.LMIid = [F.LMIid yalmip('lmiid')]; |
---|
248 | i = i + 1; |
---|
249 | otherwise |
---|
250 | error('Error in argument in LMI. Please report bug'); |
---|
251 | end |
---|
252 | end |
---|
253 | end |
---|
254 | |
---|