pdsco.m
来自「% Atomizer Main Directory, Version .802 」· M 代码 · 共 923 行 · 第 1/3 页
M
923 行
function [x,y,z,inform] = pdsco( Fname, Aname, b, m, n, options, x0, y0, z0 )
%
% pdsco (Primal-Dual barrier method, Separable Convex Objective)
% solves optimization problems of the form
% ----------------------------------------------------------------------
% minimize phi(x) + 1/2 norm(gamma*x)^2 + 1/2 norm(r/delta)^2
% x,r
% subject to Ax + r = b, x >= 0, r unconstrained.
% ----------------------------------------------------------------------
%
% where phi(x) is a smooth separable convex function (possibly linear),
% and A is an m x n matrix. The regularization parameters (gamma, delta)
% are typically positive and small. They ensure that the primal and dual
% solutions (x,y) are bounded and unique.
%
% FUNCTIONS:
% options = pdscoSet;
% [x,y,z,inform] = pdsco( 'pdsobj', A , b, m, n, options );
% [x,y,z,inform] = pdsco( 'pdsobj', 'pdsmat', b, m, n, options );
% [x,y,z,inform] = pdsco( 'pdsobj', 'pdsmat', b, m, n, options, x0, y0, z0 );
%[obj,grad,hess] = pdsobj( x )
% v = pdsmat( mode, m, n, x )
%
% ARGUMENTS:
% x is the primal solution.
% y is the dual solution associated with Ax + r = b.
% z is the dual solution associated with x >= 0.
% x > 0, z > 0 is always true.
% If (x,y,z,r) is optimal, r = delta^2*y and x.*z should be small.
% inform = 0 if a solution is found
% = 1 if too many iterations were required
% = 2 if the linesearch failed too often
% 'pdsobj' defines phi(x) and its gradient and diagonal Hessian.
% grad and hess are both vectors.
% A is an explicit m x n matrix (preferably sparse!).
% 'pdsmat' is used if A is not known explicitly.
% It returns v = A*x (mode=1) and v = A'*x (mode=2).
% b is the right-hand side vector.
% m, n are the dimensions of A (or the A implied by pdsmat).
% options is a structure that may be set and altered by pdscoSet.
% options.gamma may be zero or positive. A typical value is gamma = 1.0e-4.
% options.delta must be positive. Again, a typical value is delta = 1.0e-4.
% Values smaller than 1.0e-6 or 1.0e-7 may affect numerical
% reliability. Increasing delta usually improves convergence.
% For least-squares applications, delta = 1.0 is appropriate.
% help pdscoSet describes the other options.
% x0,y0,z0 (if present) provide an initial solution, probably from a
% previous call.
%-----------------------------------------------------------------------
% EXTERNAL FUNCTIONS NEEDED:
% pdscoSet.m, pdsxxx.m, lsqr.m, (provided with pdsco.m)
% pdsmat.m, pdsobj.m (provided by user -- whatever names you like)
%
% If phi(x) is the linear function c'x, pdsobj should return
% [obj,grad,hess] = [c'x, c, zeros(n,1)].
%
% NOTE:
% A, b, x are assumed to be reasonably well scaled.
% The files corresponding to pdsobj and pdsmat must not be called
% Fname.m or Aname.m !!!!
% 20 Jun 1997: Original version, derived from pdlp0.m.
% Author: Michael Saunders, Stanford University
% (saunders@stanford.edu).
%
% 05 Mar 1997: Found that low accuracy solves lead to failure unless
% dz = xinv.*(v - z.*dx) is replaced by dz = t + gamma2*dx - Ady,
% as recommended in Saunders & Tomlin, Report SOL 96-3, 1996.
% E.g. SYMMLQ with rtol = 1.0e-10 solved quite well,
% but rtol = 1.0e-9 or bigger let t diverge.
% With new dz, rtol = 1.0e-7 seems accurate enough,
% 1.0e-6 is border-line.
%
% 13 Jun 1997: LSQR installed to solve for dy.
% 18 Mar 1998: Can no longer find much difference between the above dz options.
% Will keep using dz = t + gamma2*dx - Ady (just in case).
% 19 Mar 1998: gamma, delta, wait added as parameters.
% 29 Mar 1998: LSQR's atol decreased dynamically from atol1 to atol2.
% It looks like atol1 must be 1.0e-6 or less
% (and atol2 = 1.0e-8 or less).
% 17 Mar 1998: LSproblem = 1 selects original LS problem for dy.
% This is best if delta is small.
% LSproblem = 2 converts it to a damped LS problem.
% This allows lsqr to work with the smaller operator DA'.
% It should be safe if delta = 1 say.
% 31 Mar 1998: Found that LSdamp > delta often accelerates convergence.
% 31 Mar 1998: Derived "primal" LS problem, which finds dx before dy.
% LSproblem = 11 selects "primal" LS problem.
% LSproblem = 12 converts it to a damped LS problem.
% Implemented pdsobj, pdsmat, pdsxxx to allow for explicit A.
% 09 May 1998: 2x2 KKT may be symmetrized with X^(1/2).
% LSproblem = 32 solves it via explicit K2 or SYMMLQ.
% LSproblem = 33 equilibrates first n cols of K2.
% pdsyyy.m applies operator K for SYMMLQ.
% Cond(K2) is less than cond(A*D) -- a good sign.
% 09 May 1998: Initialized mu to be the proverbial mu0*(x'z)/n.
% 14 May 1998: Regard delta as a decreasing parameter like mu
% to implement the conventional penalty function.
% LSdamp = max( sqrt(mu), delta ) does the trick.
% 23 May 1998: x0,y0,z0 are now optional input parameters. z is output.
% 03 Jun 1998: delta0 introduced to allow a choice.
% delta0 = delta fixes delta throughout (this is the default).
% delta0 = 1 allows delta to decrease with sqrt(mu).
% Thus, max( sqrt(mu), delta ) <= "delta" <= delta0.
% 13 Jun 1998: mulast = 0.1*opttol introduced. No need to let mu get smaller.
% 11 Feb 2000: Added diagonal preconditioning for LSQR when A is explicit
% (and LSproblem = 1, LSmethod = 3). Improved cond(DA') greatly.
% Seems to halve the LSQR itns as hoped.
% 12 Feb 2000: Added analogous scaling to rows of A for SYMMLQ (LSproblem = 32)
% 14 Apr 2000: Initialize mu from initial [r; t; Xz], not just from gap.
% 15 Apr 2000: Use P = symmmd(ADDA) on first iteration for later chol(ADDA)
% (if explicit A and LSmethod = 1).
% 16 Apr 2000: mulast = 0.01*opttol seems necessary on Xiaoming's LP problems.
% 28 Sep 2000: options implements as a structure.
%-----------------------------------------------------------------------
global AAA DDD1 DDD2 DDD3;
fprintf('\n pdsco.m Version of 29 Sep 2000')
fprintf('\n Primal-dual barrier algorithm --- for optimization with a')
fprintf('\n separable convex obj and linear constraints Ax = b, x > 0\n')
operator = isstr(Aname);
explicit = ~operator;
if explicit % Aname is an explicit matrix A.
[m,n] = size(Aname); % In case the user set (m,n) incorrectly.
AAA = Aname; % Explicit A = global AAA.
Aname = 'pdsmat'; % Use default Ax, A'y routine pdsmat.m.
nnzA = nnz(AAA);
if nnzA == m*n
fprintf('\nA is an explicit dense matrix')
else
fprintf('\nA is an explicit sparse matrix')
end
fprintf('\nm = %8g n = %8g nnz(A) =%9g', m,n,nnzA);
else
fprintf('\nA is an operator')
fprintf('\nm = %8g n = %8g', m,n);
end
%-----------------------------------------------------------------------
% Initialize.
%-----------------------------------------------------------------------
inform = 0;
em = ones(m,1);
en = ones(n,1);
flops0 = flops;
cgitns = 0;
true = 1;
false = 0;
nb = n + m;
nkkt = n + m;
%-----------------------------------------------------------------------
% Grab input options.
%-----------------------------------------------------------------------
gamma = options.gamma;
delta = options.delta;
maxitn = options.MaxIter;
featol = options.FeaTol;
opttol = options.OptTol;
steptol= options.StepTol;
itnlim = options.LSQRMaxIter * min(m,n);
atol1 = options.LSQRatol1; % Initial atol
atol2 = options.LSQRatol2; % Smallest atol (unless atol1
is smaller)
conlim = options.LSQRconlim;
wait = options.wait;
if nargin <= 6
x0 = en;
z0 = en;
y0 = zeros(m,1);
end
%-----------------------------------------------------------------------
% Set other parameters.
%-----------------------------------------------------------------------
kminor = 0; % 1 stops after each iteration
x0min = 0.1; % Minimum size of initial x if x0 is provided
z0min = 0.1; % Minimum size of initial z if z0 is provided
mu0 = 0.1; % Scales initial mu
delta0 = delta; % Initial value of delta
eta = 1e-4; % Linesearch tolerance for "sufficient descent"
maxf = 10; % Linesearch backtrack limit (function evaluations)
maxfail = 4; % Linesearch failure limit (consecutive iterations)
LSproblem = 1; % 1 = dy 2 = dy shifted, DLS
% 11 = s 12 = s shifted, DLS (dx = Ds)
% 21 = dx
% 31 = 3x3 system, symmetrized by Z^{1/2}
% 32 = 2x2 system, symmetrized by X^{1/2}
LSmethod = 3; % 1 = Cholesky 2 = QR 3 = LSQR or SYMMLQ
%if delta >= 0.1, LSproblem = 2; end
% More parameters for lsqr.
atolmin= eps; % Smallest atol if linesearch back-tracks
btol = atol2; % Should be small (zero is ok)
show = false; % Controls lsqr iteration log
% Parameters for symmlq.
precon = false; shift = 0;
showsym = false; check = false;
itnsym = 15*(m+n); % rtol = atol; % Use lsqr's atol below
fprintf('\nx0min = %8g featol = %8.1e', x0min, featol)
fprintf( ' gamma = %8.1e', gamma)
fprintf('\nz0min = %8g opttol = %8.1e', z0min, opttol)
fprintf( ' delta = %8.1e', delta)
fprintf('\nmu0 = %8.1e steptol = %8g', mu0 , steptol)
fprintf( ' delta0 = %8.1e', delta0)
fprintf('\n\nLSproblem=%3g', LSproblem)
fprintf( ' ( 1 = dy, LS 2 = dybar, DLS)')
fprintf('\n (11 = s , LS 12 = sbar , DLS) (dx = Ds)')
fprintf('\n (21 = dx, LS)')
fprintf('\n (31 = K3 sym-izd 32 = K2 symmetrized by X^(1/2))')
fprintf( '\nLSmethod =%3g', LSmethod)
fprintf( ' ( 1 = Cholesky 2 = QR 3 = LSQR or SYMMLQ)')
fprintf('\n\nLSQR:')
fprintf('\natol1 = %8.1e atol2 = %8.1e', atol1 , atol2 )
fprintf( ' btol = %8.1e', btol )
fprintf('\nconlim = %8.1e itnlim = %8g' , conlim, itnlim)
fprintf( ' show = %8g' , show )
if wait
fprintf('\n\nReview parameters... then type the word "return"\n')
keyboard
end
if eta < 0
fprintf('\n\nLinesearch disabled by eta < 0')
end
tic;
%------------------------------------------------------------------------
% Initialize x, z, y, objective function, etc.
%------------------------------------------------------------------------
normb = norm(b,inf);
gamma2 = gamma^2;
delta2 = delta^2;
x = max( x0, x0min );
z = max( z0, z0min );
y = y0;
useChol = LSmethod == 1;
useQR = LSmethod == 2;
direct = LSmethod <= 2 & explicit;
if LSproblem < 30
solver = ' lsqr';
else
solver = 'symmlq';
end
[obj,grad,hess] = feval( Fname, x );
%------------------------------------------------------------------------
% Initialize linear residuals rlin = b - A*x,
% tlin = - z - A'*y.
%------------------------------------------------------------------------
if explicit
r = AAA*x;
else
r = feval( Aname, 1, m, n, x );
end
t = zeros( n,1 );
if norm(y,inf) > 0
if explicit, t = AAA'*y;
else t = feval( Aname, 2, m, n, y ); end
end
rlin = b - r;
tlin = - z - t;
Xz = x.*z;
%------------------------------------------------------------------------
% 09 May 1998: Initialize mu to a fraction of x'z/n (as others do).
% 14 May 1998: Make delta decrease with mu.
% 03 Jun 1998: Keep delta <= delta0.
% 13 Jun 1998: Keep mu >= mulast.
% 14 Apr 2000: mufirst = mu0 * (x'z)/n is too small if initial r, t are big.
% Revert to balancing two parts of rhs of KKT system:
% ( b - Ax ) ( 0 ) ( r )
% (g - A'y - z) = ( 0 ) + ( t ).
% (mu e - Xz) (mu e) (- Xz )
%------------------------------------------------------------------------
r = rlin - delta2 * y;
t = tlin + (gamma2 * x + grad);
f = [ r; t; Xz ];
normf = norm(f);
mufirst = mu0 * normf / n; %Replaces mufirst = mu0 * (sum(Xz) / n);
mulast = 0.01 * opttol;
mu = mufirst;
LSdamp = max( sqrt(mu), delta );
LSdamp = min( LSdamp , delta0);
LSdamp2 = LSdamp^2;
%------------------------------------------------------------------------
% Initialize nonlinear residuals r = rlin - delta^2*y,
% t = tlin + gamma^2*x + grad,
% v = mu*e - X*z.
%------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?