0001
0002
0003 classdef penlab < handle
0004
0005 properties
0006
0007 probname = 'No problem loaded';
0008 comment = '';
0009
0010
0011 userdata = [];
0012
0013
0014 opts = struct();
0015
0016
0017 xinit = [];
0018 Yinit = [];
0019
0020 end
0021
0022 properties (SetAccess = private)
0023
0024 phase = 0;
0025
0026
0027 Nx = 0;
0028
0029 NY = 0;
0030
0031 NYnnz = 0;
0032
0033 Ymap = [];
0034
0035
0036 NgNLN = 0;
0037
0038 NgLIN = 0;
0039
0040 NANLN = 0;
0041
0042 NALIN = 0;
0043
0044
0045
0046 x = [];
0047 Y = [];
0048
0049
0050
0051
0052
0053 stats_ncall_alx = 0;
0054 stats_time_alx = 0;
0055 stats_ncall_aldx = 0;
0056 stats_time_aldx = 0;
0057 stats_ncall_alddx = 0;
0058 stats_time_alddx = 0;
0059 stats_time_fact_last = 0;
0060 stats_time_fact = 0;
0061 stats_time_miter_last = 0;
0062 stats_time_miters = 0;
0063 stats_time_total = 0;
0064 miter = 0;
0065 miter_last = 0;
0066 initer = 0;
0067 initer_last = 0;
0068 lsiter = 0;
0069 lsiter_last = 0;
0070
0071
0072
0073
0074 solveflag = [];
0075 rFeas = [];
0076 rCompl = [];
0077 rNormG = [];
0078
0079
0080
0081 objfun = [];
0082 objgrad = [];
0083 objhess = [];
0084 confun = [];
0085 congrad = [];
0086 conhess = [];
0087 lagrhess = [];
0088 mconfun = [];
0089 mcongrad = [];
0090 mconhess = [];
0091 mconlagrhess = [];
0092
0093
0094
0095
0096 allopts = penlab.defopts(1);
0097
0098
0099
0100
0101
0102 Nxbox = 0;
0103
0104 xboxmap = [];
0105 xboxmlt = [];
0106 xboxshift = [];
0107
0108 NYbox = 0;
0109
0110 vec2Ymap = [];
0111
0112 Yboxmap = [];
0113 Yboxmlt = [];
0114 Yboxshift = [];
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 Nineq = 0;
0129 ineqmap = [];
0130 ineqmlt = [];
0131 ineqshift = [];
0132
0133 Neq = 0;
0134 eqmap = [];
0135 eqshift = [];
0136
0137 NA = 0;
0138 Amap = [];
0139 Amlt = [];
0140 Ashift = [];
0141
0142
0143 Adep=[];
0144
0145
0146 xboxtype = [];
0147 ineqtype = [];
0148 Yboxtype = [];
0149 Atype = [];
0150
0151
0152 xboxindbar = [];
0153 xboxindphi = [];
0154
0155 ineqindphi = [];
0156 Yboxindbar = [];
0157 Yboxindphi = [];
0158
0159 Aindphi = [];
0160
0161
0162 end
0163
0164 properties
0165
0166
0167 ticker = 1;
0168
0169 xYtck = 0;
0170
0171
0172
0173 xall = [];
0174
0175
0176
0177 uxbox = [];
0178 uxboxnew = [];
0179 uineq = [];
0180 uineqnew = [];
0181 ueq = [];
0182
0183
0184 UYbox = [];
0185 UYboxnew = [];
0186 UA = [];
0187 UAnew = [];
0188
0189
0190 pxbox = [];
0191 pineq = [];
0192 PYbox = [];
0193 PA = [];
0194
0195
0196
0197 objx = 0;
0198 xboxx = [];
0199 ineqx = [];
0200 eqx = [];
0201
0202 eqdxtck = 0;
0203 eqdx = [];
0204
0205
0206
0207 ALxtck = 0;
0208 ALx = 0;
0209
0210
0211 ALdxtck = 0;
0212 ALdx = [];
0213
0214
0215 ALddxtck = 0;
0216 ALddx = [];
0217
0218
0219 fid = -1;
0220
0221
0222 chol_lmlast = 0;
0223 chol_factperm = [];
0224
0225 ls_small_cnt = 0;
0226 ls_rnu = [];
0227 end
0228
0229 properties (Constant)
0230
0231 solvername = 'PenLab 1.04 (20140125)';
0232
0233
0234 solvermsg = {'converged: optimal solution', ...
0235 'converged: suboptimal solution', ...
0236 'finished: solution primal infeasible', ...
0237 'finished: objective function seems to be unbounded', ...
0238 'didn''t converge: unconstrained minimization failed', ...
0239 'didn''t converge: no progress, iteration process terminated', ...
0240 'didn''t converge: outer iterations reached', ...
0241 'didn''t converge: unknown error', ...
0242 'hasn''t finished yet'};
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 defopts = struct(...
0254 'outlev', {2, 'I', [0, Inf]}, ...
0255 'outlev_file', {5, 'I', [0, Inf]}, ...
0256 'out_filename', {'penm_log.txt', 'S', []}, ...
0257 'user_prn', {[], 'O', []}, ...
0258 'maxotiter', {100, 'I', [0, Inf]}, ...
0259 'maxiniter', {100, 'I', [0, Inf]}, ...
0260 ...
0261 'penalty_update', {0.5, 'R', [0, 1]}, ...
0262 'penalty_update_bar', {0.3, 'R', [0, 1]}, ...
0263 'mpenalty_update', {0.5, 'R', [0, 1]}, ...
0264 'mpenalty_min', {1e-6, 'R', [0, 1]}, ...
0265 'mpenalty_border', {1e-6, 'R', [0, 1]}, ...
0266 'max_outer_iter', {100, 'I', [0, Inf]}, ...
0267 'outer_stop_limit', {1e-6, 'R', [1e-20, 1]}, ...
0268 'kkt_stop_limit', {1e-4, 'R', [1e-20, 1]}, ...
0269 'mlt_update', {0.3, 'R', [0, 1]}, ...
0270 'mmlt_update', {0.1, 'R', [0, 1]}, ...
0271 'uinit', {1, 'R', [-Inf, Inf]}, ...
0272 'uinit_box', {1, 'R', [-Inf, Inf]}, ...
0273 'uinit_eq', {0, 'R', [-Inf, Inf]}, ...
0274 'umin', {1e-10, 'R', [0, 1]}, ...
0275 'pinit', {1, 'R', [0, 1]}, ...
0276 'pinit_bar', {1, 'R', [0, 1]}, ...
0277 'usebarrier', {0, 'M', [0, 1]}, ...
0278 'xinit_mod', {0, 'M', [0, 1]}, ...
0279 ...
0280 'max_inner_iter', {100, 'I', [0, Inf]}, ...
0281 'inner_stop_limit', {1e-2, 'R', [0, 1]}, ...
0282 'unc_dir_stop_limit', {1e-2, 'R', [0, 1]}, ...
0283 'unc_solver', {0, 'M', [0, 1, 2, 3, 4, 5]}, ...
0284 'unc_linesearch', {3, 'M', [0, 1, 2, 3]}, ...
0285 ...
0286 'eq_dir_stop_limit', {1e-2, 'R', [0, 1]}, ...
0287 'eq_solver', {0, 'M', [0, 1]}, ...
0288 'eq_linesearch', {3, 'M', [0, 1, 2, 3]}, ...
0289 'eq_solver_warn_max', {4, 'I', [0, 10]}, ...
0290 'ls_short_max', {3, 'I', [0, 10]}, ...
0291 'min_recover_strategy', {0, 'M', [0, 1]}, ...
0292 'min_recover_max', {3, 'I', [0, 10]}, ...
0293 ...
0294 'phi_R', {-0.5, 'R', [-1, 1]}, ...
0295 ...
0296 'max_ls_iter', {20, 'I', [0, Inf]}, ...
0297 'max_lseq_iter', {20, 'I', [0, Inf]}, ...
0298 'armijo_eps', {1e-2, 'R', [0, 1]}, ...
0299 ...
0300 'ldl_pivot', {1e-5, 'R', [0, 1]}, ...
0301 'pert_update', {2., 'R', [0, 100]}, ...
0302 'pert_min', {1e-6, 'R', [0, 1]}, ...
0303 'pert_try_max', {50, 'I', [0, Inf]}, ...
0304 'pert_faster', {1, 'M', [0, 1]}, ...
0305 ...
0306 'chol_ordering', {1, 'M', [0, 1]}, ...
0307 ...
0308 'luk3_diag', {1., 'R', [0, Inf]} ...
0309 );
0310
0311
0312
0313 end
0314
0315 methods
0316 Y = vec2Y(obj, vec);
0317 vec = Y2vec(obj, Y, Ydefault);
0318 [errmsg] = print(obj, minlev, maxlev, msg, varargin);
0319 [errmsg] = print_opts(obj, minlev, maxlev);
0320 []=setpentype(obj,lbxbar,ubxbar,lbYbar,ubYbar);
0321 [] = init(obj, forceupdate);
0322 [ret] = phi2(obj,t);
0323 [ret] = phi2_D(obj,t);
0324 [ret] = phi2_D2(obj,t);
0325 [ret] = phibar(obj,t);
0326 [ret] = phibar_D(obj,t);
0327 [ret] = phibar_D2(obj,t);
0328 [status] = eval_alx(obj);
0329 [status] = eval_aldx(obj);
0330 [status] = eval_alddx(obj);
0331 [] = clearstats(obj);
0332 [dir,nFlag]=solve_chol(obj,matrix,rhs);
0333 [x_dir,ueq_dir,nFlag,pert]=solvekkt_ldl(obj,H,A,rhs1,rhs2);
0334 [rRelStep, nFlag]=ls_pennon(obj, dir);
0335 [rRelStep, nFlag]=lseq_pen(obj, dir, udir, miter);
0336 [nFlag,rResults]=unconstr_min(obj);
0337 [nFlag,rResults]=eqconstr_min(obj);
0338 [] = logfile(obj,task);
0339 disp(obj);
0340 [mfeas] = feas_ay(obj);
0341
0342
0343 function obj = penlab(penm)
0344 if (nargin > 0)
0345 if (isstruct(penm))
0346
0347
0348 penm=defaultsfiller(penm);
0349
0350
0351 obj.logfile(1);
0352
0353
0354
0355
0356 obj.probname=penm.probname;
0357 obj.comment=penm.comment;
0358
0359 obj.userdata=penm.userdata;
0360
0361
0362 if (penm.Nx<0)
0363 error('ERR: wrong Nx');
0364 else
0365 obj.Nx=penm.Nx;
0366
0367 [obj.xboxmap, obj.xboxmlt, obj.xboxshift]= ...
0368 boundschecker(penm.Nx,penm.lbx,penm.ubx,false,true,[]);
0369 obj.Nxbox = length(obj.xboxmap);
0370 end
0371
0372 if (penm.NY<0)
0373 error('ERR: wrong NY')
0374 else
0375 obj.NY=penm.NY;
0376 obj.NYnnz=0;
0377 filterout=[];
0378
0379 for k=1:penm.NY
0380 [mapper, obj.NYnnz]=createY1map(penm.Y{k}, obj.NYnnz);
0381 obj.vec2Ymap{k}=mapper;
0382 if (isempty(mapper.xmap))
0383
0384 filterout = [filterout, k];
0385 end
0386 end
0387
0388
0389
0390
0391
0392 lbYxvec=obj.Y2vec(penm.lbYx,-Inf);
0393 ubYxvec=obj.Y2vec(penm.ubYx,Inf);
0394
0395
0396 [ineqmap, ineqmlt, ineqshift]= ...
0397 boundschecker(obj.NYnnz,lbYxvec,ubYxvec,-1,true,[]);
0398 ineqmap=ineqmap+obj.Nx;
0399 obj.xboxmap = [obj.xboxmap, ineqmap];
0400 obj.xboxmlt = [obj.xboxmlt, ineqmlt];
0401 obj.xboxshift = [obj.xboxshift, ineqshift];
0402 obj.Nxbox = obj.Nxbox + length(ineqmap);
0403
0404
0405 [obj.Yboxmap, obj.Yboxmlt, obj.Yboxshift]= ...
0406 boundschecker(penm.NY,penm.lbY,penm.ubY,false,true,filterout);
0407 obj.NYbox = length(obj.Yboxmap);
0408
0409
0410 obj.Ymap = obj.vec2Y([obj.Nx+1:obj.Nx+obj.NYnnz]);
0411 end
0412
0413
0414 if (obj.Nx+obj.NYnnz==0)
0415 error('ERR: no decision variables set!');
0416 end
0417
0418
0419 obj.xall=zeros(obj.Nx+obj.NYnnz,1);
0420 if (isfield(penm,'xinit'))
0421 obj.xinit=penm.xinit;
0422 end
0423 if (isfield(penm,'Yinit'))
0424 obj.Yinit=penm.Yinit;
0425 end
0426
0427 if (penm.NgNLN<0 || penm.NgLIN<0)
0428 error('Ng*<0 error');
0429 else
0430 obj.NgNLN=penm.NgNLN;
0431 obj.NgLIN=penm.NgLIN;
0432
0433
0434 [obj.ineqmap, obj.ineqmlt, obj.ineqshift, obj.eqmap, obj.eqshift]= ...
0435 boundschecker(penm.NgNLN+penm.NgLIN,penm.lbg,penm.ubg,true,false,[]);
0436 obj.Nineq = length(obj.ineqmap);
0437 obj.Neq = length(obj.eqmap);
0438
0439 end
0440
0441 if (penm.NANLN<0 || penm.NALIN<0)
0442 error('NA*<0 error');
0443 else
0444 obj.NANLN=penm.NANLN;
0445 obj.NALIN=penm.NALIN;
0446
0447 [obj.Amap, obj.Amlt, obj.Ashift]= ...
0448 boundschecker(penm.NANLN+penm.NALIN,penm.lbA,penm.ubA,false,false,[]);
0449 obj.NA = length(obj.Amap);
0450
0451
0452 end
0453
0454
0455 if (~isfield(penm,'objfun') || ~isfield(penm,'objgrad'))
0456
0457
0458 error('objfun and/or objgrad not defined');
0459 end
0460 obj.objfun=penm.objfun;
0461 obj.objgrad=penm.objgrad;
0462 if (obj.NgNLN+obj.NgLIN>0)
0463 if (~isfield(penm,'confun') || ~isfield(penm,'congrad'))
0464 error('confun and/or congrad not defined and constraint are present');
0465 end
0466 obj.confun=penm.confun;
0467 obj.congrad=penm.congrad;
0468 end
0469 if (isfield(penm,'lagrhess'))
0470
0471 obj.lagrhess=penm.lagrhess;
0472 else
0473 if (isfield(penm,'objhess'))
0474 obj.objhess=penm.objhess;
0475 else
0476 error('Neither lagrhess nor objhess is defined.');
0477 end
0478 if (obj.NgNLN>0 && ~isfield(penm,'conhess'))
0479 error('There are nonlinear function constraints and neither lagrhess nor conhess is defined.');
0480 elseif (obj.NgNLN>0)
0481 obj.conhess=penm.conhess;
0482 end
0483 end
0484 if (obj.NALIN+obj.NANLN>0)
0485 if (~isfield(penm,'mconfun') || ~isfield(penm,'mcongrad'))
0486 error('mconfun and/or mcongrad not defined and matrix constraints present');
0487 end
0488 obj.mconfun=penm.mconfun;
0489 obj.mcongrad=penm.mcongrad;
0490 end
0491 if (obj.NANLN>0)
0492 if (isfield(penm,'mconlagrhess'))
0493 obj.mconlagrhess=penm.mconlagrhess;
0494 elseif (isfield(penm,'mconhess'))
0495 obj.mconhess=penm.mconhess;
0496 else
0497 error('Neither mconlagrhess nor mconhess is defined and nonlinear matrix constraints present');
0498 end
0499 end
0500
0501
0502 if (isfield(penm,'Adep'))
0503 obj.Adep=penm.Adep;
0504 else
0505 obj.Adep=cell(obj.NANLN+obj.NALIN,1);
0506 for kuser=[1:obj.NANLN+obj.NALIN]
0507 xh=rand(size(obj.x));
0508 if length(obj.Y)>0
0509 for iY=1:length(obj.Y), Yh{iY}=rand(size(obj.Y{iY}));end
0510 else Yh{1}=[];end
0511 [Akx,obj.userdata] = obj.mconfun(xh, Yh, kuser, obj.userdata);
0512 list=[];
0513 for i=[1:obj.Nx+obj.NYnnz]
0514 [Akdx, obj.userdata] = obj.mcongrad(xh,Yh,kuser,i,obj.userdata);
0515 if (~isempty(Akdx)&& nnz(Akdx)>0)
0516 list=[list,i];
0517 end
0518 end
0519 obj.Adep{kuser}=list;
0520 end
0521 end
0522
0523
0524
0525
0526
0527 obj.setpentype(penm.lbxbar,penm.ubxbar,penm.lbYbar,penm.ubYbar);
0528
0529 else
0530 error('ERR: provide a penm struct!');
0531 end
0532 else
0533 disp('WARNING: Empty object! Call with "penm" structure!');
0534 end
0535 obj.phase = 1;
0536 end
0537
0538
0539 function delete(obj)
0540
0541 obj.logfile(0);
0542 end
0543
0544
0545
0546
0547 function set.opts(obj, newopts)
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557 if (isempty(newopts) || ~isstruct(newopts) || isempty(fieldnames(newopts)))
0558
0559
0560 obj.allopts = penlab.defopts(1);
0561 obj.opts = struct();
0562 obj.logfile(1);
0563 disp('Restoring all option settings to their defaults.');
0564 else
0565
0566 names=fieldnames(newopts);
0567 discard=find(~isfield(penlab.defopts(1),names));
0568 if (~isempty(discard))
0569 str = sprintf(' %s',names{discard});
0570 fprintf('Warning: these options don''t exist and are ignored:%s\n',str);
0571 end
0572
0573
0574 keep=find(isfield(penlab.defopts(1),names));
0575 reopenlog=0;
0576 for i=keep'
0577 defvalue=getfield(penlab.defopts(1),names{i});
0578 value=getfield(newopts,names{i});
0579 if (isfield(obj.opts, names{i}))
0580 origvalue=getfield(obj.opts,names{i});
0581 else
0582 origvalue=[];
0583 end
0584 oldvalue=getfield(obj.allopts,names{i});
0585 newvalue=oldvalue;
0586
0587
0588 if (isempty(value) && ~isempty(origvalue))
0589
0590 obj.opts = rmfield(obj.opts, names{i});
0591 obj.allopts = setfield(obj.allopts, names{i}, defvalue);
0592 newvalue=defvalue;
0593 disp(sprintf('option %s set back to defautls',names{i}));
0594
0595 elseif (isempty(origvalue) || origvalue~=value)
0596
0597
0598 obj.opts=setfield(obj.opts, names{i}, value);
0599 obj.allopts=setfield(obj.allopts, names{i}, value);
0600 newvalue=value;
0601
0602
0603 end
0604
0605
0606 if (strcmp(names{i},'out_filename') || ...
0607 strcmp(names{i},'outlev_file') && oldvalue*newvalue==0)
0608 reopenlog=1;
0609 end
0610 end
0611 if (reopenlog)
0612 obj.logfile(1);
0613 end
0614 end
0615 end
0616
0617
0618
0619
0620 function set.xall(obj, xall)
0621
0622
0623 obj.ticker=obj.ticker+1;
0624 obj.xall=xall;
0625 end
0626
0627
0628 function x=get.x(obj)
0629 if (obj.xYtck<obj.ticker)
0630
0631 obj.x=obj.xall(1:obj.Nx);
0632 obj.Y=obj.vec2Y(obj.xall(obj.Nx+1:end));
0633 obj.xYtck=obj.ticker;
0634 end
0635 x=obj.x;
0636 end
0637
0638
0639 function Y=get.Y(obj)
0640 if (obj.xYtck<obj.ticker)
0641
0642 obj.x=obj.xall(1:obj.Nx);
0643 obj.Y=obj.vec2Y(obj.xall(obj.Nx+1:end));
0644 obj.xYtck=obj.ticker;
0645 end
0646 Y=obj.Y;
0647 end
0648
0649
0650 function set.xinit(obj,x)
0651 if (obj.phase==2)
0652 error('Changing x during computation is not allowed.');
0653 end
0654
0655
0656 if (length(x)~=obj.Nx)
0657 error('wrong dimension of x');
0658 end
0659 obj.xall(1:obj.Nx) = x;
0660 if (obj.phase==3)
0661
0662 obj.phase=1;
0663 end
0664 end
0665
0666
0667 function set.Yinit(obj,Y)
0668 if (obj.phase==2)
0669 error('Changing Y during computation is not allowed.');
0670 end
0671
0672
0673
0674 obj.xall(obj.Nx+1:end)=obj.Y2vec(Y);
0675 if (obj.phase==3)
0676
0677 obj.phase=1;
0678 end
0679 end
0680
0681
0682 end
0683
0684 methods (Static)
0685
0686
0687 function dname = default_probname()
0688 dname = ['Pennon NLP-SDP problem ', datestr(now) ];
0689 end
0690
0691
0692
0693 function dopts = default_opts()
0694 dopts = [];
0695 dopts.outlev = 2;
0696 dopts.outlev_file = 5;
0697 dopts.out_filename = 'penm_log.txt';
0698 dopts.user_prn = [];
0699 dopts.maxotiter = 100;
0700 dopts.maxiniter = 100;
0701
0702
0703 dopts.penalty_update = 0.5;
0704 dopts.penalty_update_bar = 0.3;
0705 dopts.max_outer_iter = 100;
0706 dopts.outer_stop_limit = 1e-6;
0707 dopts.kkt_stop_limit = 1e-4;
0708 dopts.mlt_update =0.3;
0709 dopts.uinit = 1;
0710 dopts.uinit_box = 1;
0711 dopts.uinit_eq = 0;
0712 dopts.umin = 1e-10;
0713 dopts.pinit = 1;
0714 dopts.pinit_bar = 1;
0715 dopts.usebarrier = 0;
0716
0717 dopts.max_inner_iter = 100;
0718 dopts.inner_stop_limit = 1e-2;
0719 dopts.unc_dir_stop_limit = 1e-2;
0720 dopts.unc_solver = 0;
0721 dopts.unc_linesearch = 3;
0722
0723 dopts.eq_dir_stop_limit = 1e-2;
0724 dopts.eq_solver = 0;
0725 dopts.eq_linesearch = 3;
0726 dopts.eq_solver_warn_max = 4;
0727 dopts.ls_short_max = 3;
0728 dopts.min_recover_strategy = 0;
0729 dopts.min_recover_max = 3;
0730
0731 dopts.phi_R = -0.5;
0732
0733
0734 dopts.max_ls_iter = 20;
0735 dopts.max_lseq_iter = 20;
0736 dopts.armijo_eps = 1e-2;
0737
0738
0739 dopts.pert_update = 2.;
0740 dopts.pert_min = 1e-6;
0741 dopts.pert_try_max = 50;
0742 dopts.pert_faster = 1;
0743
0744
0745 dopts.chol_ordering = 1;
0746
0747
0748 dopts.luk3_diag = 1;
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759 end
0760
0761 end
0762
0763
0764 end
0765