function F = lmi(X,handlestring,dummy,noprune,symmetryKnown) superiorto('sdpvar') persistent temp persistent F0 fast = 0; noprune = 0; symmetryKnown = 0; switch nargin case 0 F.clauses={}; F.LMIid = []; F.savedata = []; F.dualized = 0; F = class(F,'lmi'); F0 = F; return case 1 handlestring = ''; % ok probably, check later case 2 if ~isa(handlestring,'char') error('The handle must be a string') end case 4 handlestring = ''; noprune = 1; case 5 handlestring = ''; symmetryKnown = 1; otherwise error('Wrong number of arguments') end if isempty(F0) F.clauses = {}; F.LMIid = []; F.savedata = []; F.dualized = 0; try F = class(F,'lmi'); catch disp('Failure in creating SET object. Restart MATLAB and try again, or type clear classes') end F0 = F; else F = F0; end % Return empty LMI in degenerate case if isempty(X) % A bit inconsitently, we create a constraint, which is empty. We count % the number of ocnstraints by looking at LMIid, which still is zero F.clauses{1}.data=[]; F.clauses{1}.type = []; F.clauses{1}.symbolic=[]; F.clauses{1}.handle=[]; F.clauses{1}.strict = []; F.clauses{1}.cut = []; F.clauses{1}.expanded = []; F.clauses{1}.lift = []; F.clauses{1}.schurfun = []; F.clauses{1}.schurdata = []; F.clauses{1}.jointprobabilistic = []; F.clauses{1}.confidencelevel = []; F.clauses{1}.extra = []; return end % 0 : Nothing (i.e error) % 1 : LMI % 2 : Elementwise % 3 : Equality % 4 : SOCC % 5 : Rotated Lorentz % 9 : KYP constraint %10 : Eigenvalue constraint %11 : Sum of square constraint %12 : Logic CNF %15 : Deterministic uncertain variable %16 : Random uncertain variable %20 : Power cone %21 : EXP %22 : Stacked EXPCONE %30 : User generated Schur %40 : Generalized KYP %50 : SOS2 %51 : SOS1 %52 : semivar %53 : semiintvar %54 : Stacked SOCP %55 : Complementary %56 : Meta constraint to be expanded (implies, iff) %60 : Chance constraint switch class(X) case 'lmi' F = X; return case 'char' try % Parse (check for old notation, take care of ||...|| notation) sdpvarExpr = parseLMI(X); % Old notation X = strrep(X,'.>','>'); X = strrep(X,'.<','<'); catch error(lasterr) end % Evaluate try Fi=evalin('caller',sdpvarExpr); switch class(Fi) case 'sdpvar' Fi = {Fi}; strict = 0; case 'constraint' [Fi,strict] = getlist(Fi); case 'lmi' F = Fi; return; otherwise error('The string does not define an SDPVAR object') end catch error(lasterr) end case 'sdpvar' Fi = {X}; strict = 0; X='Numeric value'; case 'logic' Fi = {X}; strict = 0; X = 'Numeric value'; case {'struct','constraint'} [Fi,strict,LMIIdentifiers,tags] = getlist(X); if isempty(handlestring) || length(handlestring)==0 handlestring = tags{1}; end X='Numeric value'; otherwise error('The first argument should be an sdpvar object or string.') end % Return empty LMI in degenerate case if all(cellfun('isempty',Fi)) return end TypeofConstraint = zeros(length(Fi),1)-1; % support for SOS constraints placed in vector if length(Fi) == 1 if isa(Fi{1},'sdpvar')% is(Fi{1},'sos') if gethackflag(Fi{1})==1 % Expand to a set of SOS constraints if ~issymmetric(Fi{1}) p = Fi{1}(:); for i = 1:length(p) Fi{i} = p(i); end TypeofConstraint = zeros(length(Fi),1)-1; strict = zeros(length(Fi),1)-1; end end end end i = 1; while i <= length(Fi) thisFi = Fi{i}; if ~isempty(thisFi) if isa(thisFi,'logic') TypeofConstraint(i) = 12; else TypeofConstraint(i) = gethackflag(Fi{i}); end % User just sent a sdpvar object, interpret as X>0 if (TypeofConstraint(i)==0) TypeofConstraint(i) = 1; end if (TypeofConstraint(i)==1) && (symmetryKnown == 0) [n,m]=size(thisFi); if (n~=m) || ((TypeofConstraint(i) == 1) && (n*m==1)) || ~ishermitian(thisFi) TypeofConstraint(i) = 2; end end if TypeofConstraint(i) == 2 % remove constraint of the type set(0 >= 0) B = getbase(thisFi); if ~noprune Bv = B(:,2:end); notused = find((~any(Bv,2)) & (B(:,1)>=0)); if ~isempty(notused) used = setdiff(1:size(Bv,1),notused); thisFi = thisFi(used); end end end % save cleaned version Fi{i} = thisFi; switch TypeofConstraint(i) case {1,2,3,4,5,7,8,9,10,11,12,13,15,16,20,21,22,30,40,50,51,52,53,54,57} i = i + 1; otherwise error('Error in argument in LMI. Please report bug'); end end end % Special case for x1 vecF = []; sizes = zeros(length(Fi),1); % Speed up concatenation of merging for i = 1:length(Fi) sizes(i) = prod(size(Fi{i})); end if all(sizes == 1) vecF = [Fi{:}]'; else for i = 1:length(Fi) fi = Fi{i}; if sizes(i) > 1 fi = reshape(fi,prod(size(fi)),1); end vecF = [vecF;fi]; end end else vecF = Fi{1}; if prod(size(vecF))>1 vecF = vecF(:); end end if isempty(temp) temp.data=vecF; temp.type = 2; temp.symbolic=X; temp.handle=handlestring; temp.strict = strict(1); temp.cut = 0; temp.expanded = 0; temp.lift = 0; temp.schurfun = ''; temp.schurdata = []; temp.jointprobabilistic = []; temp.confidencelevel = []; temp.extra = []; else temp.data=vecF; temp.symbolic=X; temp.handle=handlestring; temp.strict = strict(1); end F.clauses{1}{1} = temp; % F.clauses{1}{1}.data=vecF; % F.clauses{1}{1}.type = 2; % F.clauses{1}{1}.symbolic=X; % F.clauses{1}{1}.handle=handlestring; % F.clauses{1}{1}.strict = strict(1); % F.clauses{1}{1}.cut = 0; % F.clauses{1}{1}.expanded = 0; % F.clauses{1}{1}.lift = 0; % F.clauses{1}{1}.schurfun = ''; % F.clauses{1}{1}.schurdata = []; % F.clauses{1}{1}.jointprobabilistic = []; % F.clauses{1}{1}.confidencelevel = []; % F.clauses{1}{1}.extra = []; F.LMIid = [F.LMIid LMIIdentifiers(1)]; else for i = 1:length(Fi) switch TypeofConstraint(i) case {1,2,3,4,5,7,8,9,10,11,12,13,15,16,20,21,22,30,40,50,51,52,53,54,57} F.clauses{1}{i}.data=Fi{i}; F.clauses{1}{i}.type = TypeofConstraint(i); F.clauses{1}{i}.symbolic=X; F.clauses{1}{i}.handle=handlestring; F.clauses{1}{i}.strict = strict(i); F.clauses{1}{i}.cut = 0; F.clauses{1}{i}.expanded = 0; F.clauses{1}{i}.lift = 0; F.clauses{1}{i}.schurfun = ''; F.clauses{1}{i}.schurdata = []; F.clauses{1}{i}.jointprobabilistic = []; F.clauses{1}{i}.confidencelevel = []; F.clauses{1}{i}.extra = []; F.LMIid = [F.LMIid LMIIdentifiers(i)]; i = i + 1; otherwise error('Error in argument in LMI. Please report bug'); end end end