source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/opt/yalmip/solvesdp.m @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 12.1 KB
Line 
1function diagnostic = solvesdp(varargin)
2%SOLVESDP Computes solution to optimization problem
3%
4%   DIAGNOSTIC = SOLVESDP(F,h,options) is the common command to
5%   solve optimization problems of the following kind
6%
7%    min        h
8%    subject to
9%            F >(=) 0
10%
11%   NOTES
12%    Desptite the name, SOLVESDP is the interface for solving all
13%    supported problem classes (LP, QP, SOCP, SDP, BMI, MILP, MIQP,...)
14%
15%    To obtain solution for a variable, use DOUBLE.
16%
17%    To obtain dual variable for a constraint, use DUAL.
18%
19%    See YALMIPERROR for error codes returned in output.
20%
21%   OUTPUT
22%     diagnostic : Diagnostic information
23%
24%   INPUT
25%     F          : SET object describing the constraints. Can be [].
26%     h          : SDPVAR object describing the objective h(x). Can be [].
27%     options    : Options structure. See SDPSETTINGS. Can be [].
28%
29%   EXAMPLE
30%    A = randn(15,5);b = rand(15,1)*5;c = randn(5,1);
31%    x = sdpvar(5,1);
32%    solvesdp(set(A*x<b),c'*x);double(x)
33%
34%   See also @SDPVAR/SET, DUAL, @SDPVAR/DOUBLE, SDPSETTINGS, YALMIPERROR
35
36% Author Johan Löfberg
37% $Id: solvesdp.m,v 1.58 2006/08/17 23:11:46 joloef Exp $
38
39yalmiptime = clock; % Let us see how much time we spend
40
41% Avoid warning
42if length(varargin)>=2 & isa(varargin{2},'double')
43        varargin{2} = [];
44end
45
46% Arrrgh, new format with logdet much better, but we have to
47% take care of old code, requires some testing...
48varargin = combatible({varargin{:}});
49nargin = length(varargin);
50
51% *********************************
52% CHECK INPUT
53% *********************************
54if nargin<1
55    help solvesdp
56    return
57else
58    F = varargin{1};
59    if isa(F,'constraint')
60        F = set(F);
61    end
62    if ~(isempty(F) | isa(F,'lmi'))
63        error('First argument (F) should be an lmi object.');
64    end   
65end
66
67if nargin>=2
68    h = varargin{2};
69    if isa(h,'double')
70        h = [];
71    end
72    if ~(isempty(h) | isa(h,'sdpvar') | isa(h,'logdet'))
73        error('Second argument (the objective function h) should be an sdpvar or logdet object (or empty).');
74    end
75    if isa(h,'logdet')
76        P  = getP(h);
77        g  = getgain(h);
78        if g>0
79            warning('Perhaps you mean -logdet(P)...')
80            diagnostic.yalmiptime = etime(clock,yalmiptime);
81            diagnostic.solvertime = 0;
82            diagnostic.info = yalmiperror(-2,'YALMIP');
83            diagnostic.problem = -2;
84            return
85        end
86        h = getcx(h);
87        if isempty(F)
88            F = set([]);
89        end
90    else
91        P = [];
92    end
93else
94    P = [];
95    h = [];   
96end
97   
98if nargin>=3
99    options = varargin{3};
100    if ~(isempty(options) | isa(options,'struct'))
101        error('Third argument (options) should be an sdpsettings struct (or empty).');
102    end
103    if isempty(options)
104        options = sdpsettings;
105    end
106else
107    options = sdpsettings;
108end
109options.solver = lower(options.solver);
110
111% Call robust solver?
112if length(F) > 0
113    unc_declarations = is(F,'uncertain');
114    if any(unc_declarations)
115        diagnostic = solverobust(F(find(~unc_declarations)),h,options,recover(getvariables(sdpvar(F(find(unc_declarations))))));
116        return
117    end
118end
119   
120if isequal(options.solver,'mpt') | nargin>=4
121    solving_parametric = 1;
122else
123    solving_parametric = 0;
124end
125   
126% Just for safety
127if isempty(F) & isempty(P)
128    F = lmi;
129end
130
131if any(is(F,'sos'))
132    error('You have SOS constraints. Perhaps you meant to call SOLVESOS.');
133end
134
135% Super stupido
136if length(F) == 0 & isempty(h)
137   diagnostic.yalmiptime = 0;
138   diagnostic.solvertime = 0;
139   diagnostic.info = 'No problems detected (YALMIP)';
140   diagnostic.problem = 0;
141   diagnostic.dimacs = [NaN NaN NaN NaN NaN NaN];
142   return
143end
144
145% Dualize the problem?
146if options.dualize
147    if ~isempty(P)
148        error('Cannot dualize problems with logaritmic objective')
149    end
150    [Fd,objd] = dualize(F,h);
151    options.dualize = 0;
152    diagnostic = solvesdp(Fd,-objd,options);
153    return
154end
155
156% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
157% DID WE SELECT THE MOMENT SOLVER
158% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
159if isequal(options.solver,'moment')
160    if ~isempty(P)
161        error('Cannot dualize problems with logaritmic objective')
162    end
163    options.solver = options.moment.solver;
164    [diagnostic,x,momentdata] = solvemoment(F,h,options,options.moment.order);
165    diagnostic.momentdata = momentdata;
166    diagnostic.xoptimal = x;
167    return
168end
169
170% ******************************************
171% COMPILE IN GENERALIZED YALMIP FORMAT
172% ******************************************
173[interfacedata,recoverdata,solver,diagnostic,F,Fremoved] = compileinterfacedata(F,[],P,h,options,0,solving_parametric);
174
175% ******************************************
176% FAILURE?
177% ******************************************
178if ~isempty(diagnostic)
179    diagnostic.yalmiptime = etime(clock,yalmiptime);
180    return
181end
182
183% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
184% DID WE SELECT THE LMILAB SOLVER WITH A KYP
185% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
186if  strcmpi(solver.tag,'lmilab') & any(is(F,'kyp'))
187    [diagnostic,failed] = calllmilabstructure(F,h,options);
188    if ~failed % Did this problem pass (otherwise solve using unstructured call)
189        diagnostic.yalmiptime = etime(clock,yalmiptime)-diagnostic.solvertime;
190        return
191    end
192end
193
194% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
195% DID WE SELECT THE KYPD SOLVER
196% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
197if strcmpi(solver.tag,'kypd')
198    diagnostic = callkypd(F,h,options);
199    diagnostic.yalmiptime = etime(clock,yalmiptime)-diagnostic.solvertime;
200    return
201end
202
203% ******************************************
204% DID WE SELECT THE BMILIN SOLVER (obsolete)
205% ******************************************
206if strcmpi(solver.tag,'bmilin')
207    diagnostic = callbmilin(F,h,options);
208    return
209end
210
211% ******************************************
212% DID WE SELECT THE BMIALT SOLVER (obsolete)
213% ******************************************
214if strcmp(solver.tag,'bmialt')
215    diagnostic = callbmialt(F,h,options);
216    return
217end
218
219%******************************************
220% DID WE SELECT THE MPT solver (backwards comb)
221%******************************************
222if strcmpi(solver.tag,'mpt') | strcmpi(solver.tag,'mpcvx') | strcmpi(solver.tag,'mplcp')
223    actually_save_output = interfacedata.options.savesolveroutput;
224    interfacedata.options.savesolveroutput = 1;
225    if isempty(interfacedata.parametric_variables)
226        if (nargin < 4 | ~isa(varargin{4},'sdpvar'))
227            error('You must specify parametric variables.')
228        else
229            interfacedata.parametric_variables = find(ismember(recoverdata.used_variables,getvariables(varargin{4})));
230            if isempty(varargin{5})
231                interfacedata.requested_variables = [];
232            else
233                interfacedata.requested_variables = [];
234                for i = 1:length(varargin{5})
235                    interfacedata.requested_variables = [interfacedata.requested_variables;find(ismember(recoverdata.used_variables,getvariables(varargin{5}(i))))];
236                end
237            end
238        end
239    end
240end
241
242% ********************************
243% TRY TO SOLVE PROBLEM
244% ********************************
245if options.debug
246    eval(['output = ' solver.call '(interfacedata);']);
247else
248    try
249        eval(['output = ' solver.call '(interfacedata);']);
250    catch
251        output.Primal = zeros(length(interfacedata.c),1)+NaN;
252        output.Dual  = [];
253        output.Slack = [];
254        output.solvertime   = nan;
255        output.solverinput  = [];
256        output.solveroutput = [];
257        output.problem = 9;
258        output.infostr = yalmiperror(output.problem,lasterr);
259    end
260end
261
262if options.dimacs
263    try       
264        b = -interfacedata.c;
265        c = interfacedata.F_struc(:,1);
266        A = -interfacedata.F_struc(:,2:end)';
267        x = output.Dual;
268        y = output.Primal; 
269        % FIX this nonlinear crap (return variable type in
270        % compileinterfacedata)
271        if options.relax == 0 & any(full(sum(interfacedata.monomtable,2)~=0))
272            if ~isempty(find(sum(interfacedata.monomtable | interfacedata.monomtable,2)>1))
273                for i = 1:size(interfacedata.monomtable,1)
274                    z(i,1) = prod(y(find(interfacedata.monomtable(i,:))));
275                end
276                y = z;
277            end
278        end
279       
280        if isfield(output,'Slack')
281            s = output.Slack;
282        else
283            s = [];
284        end
285                   
286        dimacs = computedimacs(b,c,A,x,y,s,interfacedata.K);
287    catch
288        dimacs = [nan nan nan nan nan nan];
289    end
290else
291    dimacs = [nan nan nan nan nan nan];
292end
293
294% ********************************
295% ORIGINAL COORDINATES
296% ********************************
297output.Primal = recoverdata.x_equ+recoverdata.H*output.Primal;
298
299% ********************************
300% OUTPUT
301% ********************************
302diagnostic.yalmiptime = etime(clock,yalmiptime)-output.solvertime;
303diagnostic.solvertime = output.solvertime;
304diagnostic.info = yalmiperror(output.problem,solver.tag);
305diagnostic.problem = output.problem;
306diagnostic.dimacs = dimacs;
307
308% Some more info is saved internally
309solution_internal = diagnostic;
310solution_internal.variables = recoverdata.used_variables(:);
311solution_internal.optvar = output.Primal;
312
313if ~isempty(interfacedata.parametric_variables)
314    diagnostic.mpsol = output.solveroutput;
315    options.savesolveroutput = actually_save_output;
316end;
317
318if interfacedata.options.savesolveroutput
319    diagnostic.solveroutput = output.solveroutput;
320end
321if interfacedata.options.savesolverinput
322    diagnostic.solverinput = output.solverinput;
323end
324
325if options.warning & warningon & isempty(findstr(output.infostr,'No problems detected'))
326    disp(['Warning: ' output.infostr]);
327end
328
329if ismember(output.problem,options.beeponproblem)
330    try
331        beep; % does not exist on all ML versions
332    catch
333    end
334end
335
336% And we are done! Save the result
337if ~isempty(output.Primal)
338    yalmip('setsolution',solution_internal);
339end
340if interfacedata.options.saveduals & solver.dual
341    if isempty(interfacedata.Fremoved) | (nnz(interfacedata.Q)>0)
342        setduals(F,output.Dual,interfacedata.K);
343    else
344        try
345            % Duals related to equality constraints/free variables
346            % have to be recovered b-A*x-Ht == 0
347            b = -interfacedata.oldc;         
348            A = -interfacedata.oldF_struc(1+interfacedata.oldK.f:end,2:end)';
349            H = -interfacedata.oldF_struc(1:interfacedata.oldK.f,2:end)';
350            x = output.Dual;
351            b_equ = b-A*x;
352            newdual =  H\b_equ;
353            setduals(interfacedata.Fremoved + F,[newdual;output.Dual],interfacedata.oldK);
354        catch
355             % this is a new feature...
356            disp('Dual recovery failed. Please report this issue.');
357        end
358    end
359end
360
361function newinputformat = combatible(varargin)
362
363varargin = varargin{1};
364
365classification = 0;
366% 0 : Ambigious
367% 1 : Old
368% 2 : New
369
370% Try some fast methods to determine...
371m = length(varargin);
372if m==1
373    classification = 2;
374elseif m>=3 & isstruct(varargin{3})
375    classification = 2;
376elseif m>=4 & isstruct(varargin{4})
377    classification = 1;
378elseif m>=2 & isa(varargin{2},'lmi')
379    classification = 1;
380elseif m>=3 & isa(varargin{3},'sdpvar')
381    classification = 1;
382elseif m>=2 & isa(varargin{2},'sdpvar') & min(size(varargin{2}))==1
383    classification = 2;
384elseif m>=2 & isa(varargin{2},'sdpvar') & prod(size(varargin{2}))>=1
385    classification = 1;
386elseif m>=2 & isa(varargin{2},'logdet')
387    classification = 2;
388elseif m==2 & isempty(varargin{2})
389    classification = 2;
390end
391
392if classification==0
393    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');
394    classification = 2;
395end
396
397if classification==2
398    newinputformat = varargin;
399else
400    newinputformat = varargin;
401    P = varargin{2};
402    % 99.9% of the cases....
403    if isempty(P)
404        newinputformat = {newinputformat{[1 3:end]}};
405    else
406        if isa(P,'lmi')
407            P = sdpvar(P);
408        end
409        if m>=3
410            cxP = newinputformat{3}-logdet(P);
411            newinputformat{3}=cxP;
412        else
413            cxP = -logdet(P);
414            newinputformat{3}=cxP;
415        end
416        newinputformat = {newinputformat{[1 3:end]}};
417    end
418end
419
420function yesno = warningon
421
422s = warning;
423yesno = isequal(s,'on');
Note: See TracBrowser for help on using the repository browser.