[37] | 1 | function [model,recoverdata,diagnostic,interfacedata] = export(varargin) |
---|
| 2 | %EXPORT Exports YALMIP problem to solver specific format |
---|
| 3 | % |
---|
| 4 | % [MODEL,RECOVERYMODEL,DIAGNOSTIC,INTERNAL] = EXPORT(F,h,options) is the common command to |
---|
| 5 | % export optimization problems of the following kind |
---|
| 6 | % |
---|
| 7 | % min h |
---|
| 8 | % subject to |
---|
| 9 | % F >(=) 0 |
---|
| 10 | % |
---|
| 11 | % |
---|
| 12 | % The MODEL is exported in the format defined by the solver chosen |
---|
| 13 | % in the options structure, or automatically chosen by YALMIP. |
---|
| 14 | % |
---|
| 15 | % If the solver format not is support by EXPORT,the YALMIP model used to |
---|
| 16 | % call the solver is returned) |
---|
| 17 | % |
---|
| 18 | % If YALMIP by some reason failed to generate a model, the DIAGNOSTIC |
---|
| 19 | % variable will be non-empty. |
---|
| 20 | % |
---|
| 21 | % The fourth output is the internal model used by YALMIP to communicate |
---|
| 22 | % with the generalized solver interfaces. |
---|
| 23 | % |
---|
| 24 | % The RECOVERYMODEL is used to relate a solution of the exported model |
---|
| 25 | % to the original variables in YALMIP. |
---|
| 26 | |
---|
| 27 | % Arrrgh, new format with logdet much better, but we have to |
---|
| 28 | % take care of old code, requires some testing... |
---|
| 29 | varargin = combatible({varargin{:}}); |
---|
| 30 | nargin = length(varargin); |
---|
| 31 | % ********************************* |
---|
| 32 | % CHECK INPUT |
---|
| 33 | % ********************************* |
---|
| 34 | if nargin<1 |
---|
| 35 | help export |
---|
| 36 | return |
---|
| 37 | else |
---|
| 38 | F = varargin{1}; |
---|
| 39 | % Check for wrong syntax |
---|
| 40 | if ~isempty(F) & ~isa(F,'lmi') & ~isa(F,'constraint') |
---|
| 41 | error('First argument should be a SET object') |
---|
| 42 | end |
---|
| 43 | |
---|
| 44 | if isa(F,'constraint') |
---|
| 45 | F = set(F); |
---|
| 46 | end |
---|
| 47 | end |
---|
| 48 | |
---|
| 49 | model = []; |
---|
| 50 | recoverdata = []; |
---|
| 51 | diagnostic = []; |
---|
| 52 | interfacedata = []; |
---|
| 53 | |
---|
| 54 | if nargin>=2 |
---|
| 55 | h = varargin{2}; |
---|
| 56 | if isa(h,'double') |
---|
| 57 | h = []; |
---|
| 58 | end |
---|
| 59 | if ~(isempty(h) | isa(h,'sdpvar') | isa(h,'logdet')) |
---|
| 60 | error('Second argument (the objective function h) should be an sdpvar or logdet object (or empty).'); |
---|
| 61 | end |
---|
| 62 | if isa(h,'logdet') |
---|
| 63 | P = getP(h); |
---|
| 64 | g = getgain(h); |
---|
| 65 | if g>0 |
---|
| 66 | warning('Perhaps you mean -logdet(P)...') |
---|
| 67 | diagnostic.yalmiptime = etime(clock,yalmiptime); |
---|
| 68 | diagnostic.solvertime = 0; |
---|
| 69 | diagnostic.info = yalmiperror(-2,'YALMIP'); |
---|
| 70 | diagnostic.problem = -2; |
---|
| 71 | return |
---|
| 72 | end |
---|
| 73 | h = getcx(h); |
---|
| 74 | G = lmi(P>0); |
---|
| 75 | F = F + G; |
---|
| 76 | else |
---|
| 77 | P = []; |
---|
| 78 | G = []; |
---|
| 79 | end |
---|
| 80 | else |
---|
| 81 | P = []; |
---|
| 82 | h = []; |
---|
| 83 | G = []; |
---|
| 84 | end |
---|
| 85 | |
---|
| 86 | |
---|
| 87 | if nargin>=3 |
---|
| 88 | options = varargin{3}; |
---|
| 89 | if ~(isempty(options) | isa(options,'struct')) |
---|
| 90 | error('Third argument (options) should be an sdpsettings struct (or empty).'); |
---|
| 91 | end |
---|
| 92 | if isempty(options) |
---|
| 93 | options = sdpsettings; |
---|
| 94 | end |
---|
| 95 | else |
---|
| 96 | options = sdpsettings; |
---|
| 97 | end |
---|
| 98 | options.solver = lower(options.solver); |
---|
| 99 | |
---|
| 100 | if nargin<6 |
---|
| 101 | if isequal(options.solver,'') |
---|
| 102 | findallsolvers = 1; |
---|
| 103 | else |
---|
| 104 | findallsolvers = 0; |
---|
| 105 | end |
---|
| 106 | else |
---|
| 107 | findallsolvers = varargin{6}; |
---|
| 108 | end |
---|
| 109 | |
---|
| 110 | % Just for safety |
---|
| 111 | if isempty(F) & isempty(G) |
---|
| 112 | F = lmi; |
---|
| 113 | end |
---|
| 114 | |
---|
| 115 | % ****************************************** |
---|
| 116 | % COMPILE IN GENERALIZED YALMIP FORMAT |
---|
| 117 | % ****************************************** |
---|
| 118 | [interfacedata,recoverdata,solver,diagnostic,F] = compileinterfacedata(F,G,P,h,options,findallsolvers); |
---|
| 119 | |
---|
| 120 | if ~isempty(diagnostic) |
---|
| 121 | model = []; |
---|
| 122 | recoverdata = []; |
---|
| 123 | return |
---|
| 124 | end |
---|
| 125 | |
---|
| 126 | % Not official yet |
---|
| 127 | if nargin == 5 |
---|
| 128 | model=interfacedata; |
---|
| 129 | return |
---|
| 130 | end |
---|
| 131 | |
---|
| 132 | % ****************************************** |
---|
| 133 | % CONVERT |
---|
| 134 | % ****************************************** |
---|
| 135 | switch lower(solver.tag) |
---|
| 136 | |
---|
| 137 | case {'sedumi-1.05','sedumi-1.1'} |
---|
| 138 | |
---|
| 139 | pars = interfacedata.options.sedumi; |
---|
| 140 | pars.fid = double(interfacedata.options.verbose); |
---|
| 141 | model.A = -interfacedata.F_struc(:,2:end); |
---|
| 142 | model.b = -interfacedata.c; |
---|
| 143 | model.C = interfacedata.F_struc(:,1); |
---|
| 144 | model.K = interfacedata.K; |
---|
| 145 | model.pars = pars; |
---|
| 146 | |
---|
| 147 | case 'csdp' |
---|
| 148 | |
---|
| 149 | pars = interfacedata.options.csdp; |
---|
| 150 | pars.printlevel=interfacedata.options.verbose; |
---|
| 151 | model.At = -interfacedata.F_struc(:,2:end); |
---|
| 152 | model.b = -interfacedata.c; |
---|
| 153 | model.C = interfacedata.F_struc(:,1); |
---|
| 154 | model.K = interfacedata.K; |
---|
| 155 | model.pars = pars; |
---|
| 156 | |
---|
| 157 | case 'dsdp' |
---|
| 158 | |
---|
| 159 | [C,A,b,blk] = sedumi2dsdp(interfacedata.F_struc,interfacedata.c,interfacedata.K); |
---|
| 160 | interfacedata.options.dsdp.dual_quadratic=spalloc(length(interfacedata.c),length(interfacedata.c),0); |
---|
| 161 | interfacedata.options.dsdp.printyes = (interfacedata.options.verbose>0); |
---|
| 162 | model.A = A; |
---|
| 163 | model.C = C; |
---|
| 164 | model.b = b; |
---|
| 165 | model.options = interfacedata.options.dsdp |
---|
| 166 | |
---|
| 167 | case 'sdpa' |
---|
| 168 | |
---|
| 169 | [mDIM,nBLOCK,bLOCKsTRUCT,c,F] = sedumi2sdpa(interfacedata.F_struc,interfacedata.c,interfacedata.K); |
---|
| 170 | if interfacedata.options.verbose==0 |
---|
| 171 | interfacedata.options.sdpa.print = 'no'; |
---|
| 172 | else |
---|
| 173 | interfacedata.options.sdpa.print = 'display'; |
---|
| 174 | end |
---|
| 175 | [objVal,x,X,Y,INFO]=sdpam(mDIM,nBLOCK,bLOCKsTRUCT,c,F,[],[],[],options.sdpa); |
---|
| 176 | model.mDIM = mDIM; |
---|
| 177 | model.nBLOCK = nBLOCK; |
---|
| 178 | model.bLOCKsTRUCT = bLOCKsTRUCT; |
---|
| 179 | model.c = c; |
---|
| 180 | model.F = F; |
---|
| 181 | model.x0 = []; |
---|
| 182 | model.X0 = []; |
---|
| 183 | model.Y0 = []; |
---|
| 184 | model.OPTIONS = interfacedata.options.sdpa |
---|
| 185 | |
---|
| 186 | case 'sdpt3-3.1' |
---|
| 187 | |
---|
| 188 | % Convert from internal (sedumi-like) format |
---|
| 189 | [blk,A,C,b,oldKs]=sedumi2sdpt3(interfacedata.F_struc(:,1),-interfacedata.F_struc(:,2:end),-interfacedata.c,interfacedata.K,30); |
---|
| 190 | interfacedata.options.sdpt3.printyes=double(interfacedata.options.verbose); |
---|
| 191 | interfacedata.options.sdpt3.expon=interfacedata.options.sdpt3.expon(1); |
---|
| 192 | |
---|
| 193 | model.blk = blk; |
---|
| 194 | model.A = A; |
---|
| 195 | model.C = C; |
---|
| 196 | model.b = b; |
---|
| 197 | model.ops = interfacedata.options.sdpt3; |
---|
| 198 | |
---|
| 199 | case 'glpk-glpkmex' |
---|
| 200 | |
---|
| 201 | n = length(interfacedata.c); |
---|
| 202 | LB=repmat(-1e6,n,1); |
---|
| 203 | UB=repmat(1e6,n,1); |
---|
| 204 | SENSE = 1; |
---|
| 205 | C = full(interfacedata.c); |
---|
| 206 | A =-interfacedata.F_struc(:,2:end); |
---|
| 207 | B = full(interfacedata.F_struc(:,1)); |
---|
| 208 | if length(B)==0; |
---|
| 209 | A = C'; |
---|
| 210 | B = 1e6; |
---|
| 211 | end |
---|
| 212 | CTYPE = [repmat('S',interfacedata.K.f,1); repmat('U',interfacedata.K.l,1)]; |
---|
| 213 | VARTYPE = repmat('C',n,1); |
---|
| 214 | VARTYPE(interfacedata.integer_variables)='I'; |
---|
| 215 | interfacedata.options.glpk.msglev = interfacedata.options.verbose; |
---|
| 216 | if interfacedata.options.glpk.msglev==1 |
---|
| 217 | interfacedata.options.glpk.msglev = 2; |
---|
| 218 | end |
---|
| 219 | model.SENSE = SENSE; |
---|
| 220 | model.C= C; |
---|
| 221 | model.A = A; |
---|
| 222 | model.B = B; |
---|
| 223 | model.CTYPE = CTYPE; |
---|
| 224 | model.LB = LB; |
---|
| 225 | model.UB = UB; |
---|
| 226 | model.VARTYPE = VARTYPE; |
---|
| 227 | model.PARAM = interfacedata.options.glpk.lpsolver; |
---|
| 228 | model.SAVE = interfacedata.options.glpk.save; |
---|
| 229 | |
---|
| 230 | case 'pensdp-penopt' |
---|
| 231 | |
---|
| 232 | penstruct = sedumi2pen(interfacedata.F_struc,interfacedata.K,interfacedata.c,interfacedata.x0); |
---|
| 233 | ops = struct2cell(interfacedata.options.pensdp);ops = [ops{1:end}]; |
---|
| 234 | penstruct.ioptions = ops(1:8); |
---|
| 235 | penstruct.foptions = ops(9:end); |
---|
| 236 | penstruct.ioptions(4) = interfacedata.options.verbose; |
---|
| 237 | penstruct.ioptions = penstruct.ioptions; |
---|
| 238 | penstruct.foptions = penstruct.foptions; |
---|
| 239 | if penstruct.mconstr == 0 |
---|
| 240 | penstruct.msizes = []; |
---|
| 241 | end |
---|
| 242 | model.penstruct = penstruct; |
---|
| 243 | |
---|
| 244 | case 'penbmi-penopt' |
---|
| 245 | |
---|
| 246 | model.penstruct = sedumi2penbmi(interfacedata.F_struc,interfacedata.c,interfacedata.Q,interfacedata.K,interfacedata.monomtable,interfacedata.options,interfacedata.x0); |
---|
| 247 | |
---|
| 248 | otherwise |
---|
| 249 | model = []; |
---|
| 250 | end |
---|
| 251 | |
---|
| 252 | |
---|
| 253 | |
---|
| 254 | function newinputformat = combatible(varargin) |
---|
| 255 | |
---|
| 256 | varargin = varargin{1}; |
---|
| 257 | |
---|
| 258 | classification = 0; |
---|
| 259 | % 0 : Ambigious |
---|
| 260 | % 1 : Old |
---|
| 261 | % 2 : New |
---|
| 262 | |
---|
| 263 | % Try some fast methods to determine... |
---|
| 264 | m = length(varargin); |
---|
| 265 | if m==1 |
---|
| 266 | classification = 2; |
---|
| 267 | elseif m>=3 & isstruct(varargin{3}) |
---|
| 268 | classification = 2; |
---|
| 269 | elseif m>=4 & isstruct(varargin{4}) |
---|
| 270 | classification = 1; |
---|
| 271 | elseif m>=2 & isa(varargin{2},'lmi') |
---|
| 272 | classification = 1; |
---|
| 273 | elseif m>=3 & isa(varargin{3},'sdpvar') |
---|
| 274 | classification = 1; |
---|
| 275 | elseif m>=2 & isa(varargin{2},'sdpvar') & min(size(varargin{2}))==1 |
---|
| 276 | classification = 2; |
---|
| 277 | elseif m>=2 & isa(varargin{2},'sdpvar') & prod(size(varargin{2}))>=1 |
---|
| 278 | classification = 1; |
---|
| 279 | elseif m>=2 & isa(varargin{2},'logdet') |
---|
| 280 | classification = 2; |
---|
| 281 | elseif m==2 & isempty(varargin{2}) |
---|
| 282 | classification = 2; |
---|
| 283 | end |
---|
| 284 | |
---|
| 285 | if classification==0 |
---|
| 286 | warning('I might have interpreted this problem wrong due to the new input format in version 3. To get rid of this warning, use an options structure'); |
---|
| 287 | classification = 2; |
---|
| 288 | end |
---|
| 289 | |
---|
| 290 | if classification==2 |
---|
| 291 | newinputformat = varargin; |
---|
| 292 | else |
---|
| 293 | newinputformat = varargin; |
---|
| 294 | P = varargin{2}; |
---|
| 295 | % 99.9% of the cases.... |
---|
| 296 | if isempty(P) |
---|
| 297 | newinputformat = {newinputformat{[1 3:end]}}; |
---|
| 298 | else |
---|
| 299 | if isa(P,'lmi') |
---|
| 300 | P = sdpvar(P); |
---|
| 301 | end |
---|
| 302 | if m>=3 |
---|
| 303 | cxP = newinputformat{3}-logdet(P); |
---|
| 304 | newinputformat{3}=cxP; |
---|
| 305 | else |
---|
| 306 | cxP = -logdet(P); |
---|
| 307 | newinputformat{3}=cxP; |
---|
| 308 | end |
---|
| 309 | newinputformat = {newinputformat{[1 3:end]}}; |
---|
| 310 | end |
---|
| 311 | end |
---|