function [x,v,opt] = quadprog2(varargin) % QUADPROG2 - Convex Quadratic Programming Solver % Featuring the SOLVOPT freeware optimizer % % New for version 1.1: * Significant Speed Improvement % * Geometric Preconditioning % * Improved Error Checking % % USAGE: % [x,v] = quadprog2(H,f,A,b) % [x,v] = quadprog2(H,f,A,b,guess) % [x,v,opt] = ... % % Minimizes the function v = 0.5*x'*H*x + f*x % subject to the constraint A*x <= b. % Initial guess is optional. % % ("opt" returns SOLVOPT data for advanced use. Details are available in % the SOLVOPT documentation at the website identified below.) % % Notes: (1) For a problem with 100 variables and 300 constraints, you will % often get a result in under 5 seconds. However, sometimes % the optimizer has to work longer (see below) for difficult % optimizations. Alerts are provided. (Note: The calculation % time is more sensitive to the number of variables than it is % to the number of contraints.) % (2) Geometric preconditioning is undertaken for 10 or more % dimensions to greatly reduce calculation time. (With fewer % than 10 dimensions, there is negligible benefit, so the % preconditioning calculations are omitted.) % (3) Geometric preconditioning can impair the convergence of some % difficult optimizations. When this occurs, the optimization % is attempted again without the preconditioning. % (4) x and guess are column vectors. f is a row vector. % They will be converted if necessary. % (5) This m-file incorporates the SOLVOPT version 1.1 freeware % optimizer, which has been wholly reproduced, except for % a few slight modifications for convenience in parameter passing. % (6) SolvOpt is a general nonlinear local optimizer, % written by Alexei Kuntsevich & Franz Kappel, and % is available (as of this writing) as freeware from: % http://www.uni-graz.at/imawww/kuntsevich/solvopt/ % (7) This Matlab function requires a convex QP problem % with a positive-definite symmetric matrix H. % This is a somewhat trivial application of % a general solver like SOLVOPT, but the use of precomputed % gradient vectors herein makes the solution fast enough % to warrant use. % (8) Any local solution of a convex QP is also a global solution. % Hence, your results will be globally optimal. % (9) Relative precision in the objective function is set to 1e-6. % (10) Absolute precision in constraint violation is 1e-6 or better. % (11) This program does not require the Optimization Toolbox % (12) ver 1.0: intial writing, Michael Kleder, June 2005 % (13) ver 1.1: geometric preconditioning, Michael Kleder, July 2005 % % EXAMPLE: % % Convex QP with 100 variables and 300 constraints: % n = 100; % c = 300; % H = rand(n); % H=H*H'; % f=rand(1,n); % A=rand(c,n)*2-1; % b=ones(c,1); % tic % x = quadprog2(H,f,A,b) % toc [H,f,A,b]=deal(varargin{1:4}); if any(eig(H)<=0) error('Non-convex. (Quadratic form is not positive definite.)') end if any(H~=H') error('Quadratic form must be symmetric.') end f=f(:)'; n=size(H,2); % try a quick check on unconstrained solution HI=inv(H); mqf=-HI*f'; % inverse exists since H is positive definite if all(A*mqf<=b(:)) x=mqf; v = .5*x'*H*x + f*x; opt=[]; return end if nargin < 5 x=mqf+(rand(n,1)-.5); else x=varargin{5}; x=x(:); end if n>=10 % geometric pre-conditioning: bn = b - A*mqf; fn = 0*f; T = sqrtm(HI); An = A*T; nA=sqrt(sum(An.^2,2)); An = An ./ repmat(nA,[1 size(An,2)]); bn = bn ./ nA; Hn = eye(size(H)); % invoke nonlinear solver: pass={Hn,fn,An,bn}; %opt=[-1,1e-4,1e-6,15000,0,1e-8,2.5,1e-11]; % defaults opt=[-1,1e-6,1e-8,15e5,0,1e-8,2.5,1e-11]; % increase precision %opt=[-1,1e-14,1e-14,15e5,0,1e-14,2.5,1e-12]; % very high precision %[x,v,opt] = solvopt2(x,@obj,[],opt,[],[],pass); opt(6) = opt(6) * .1; % precondition needs constraint tolerance reduced [x,v,opt] = solvopt2(x,@obj,@gobj,opt,@pen,@gpen,pass); opt(6) = opt(6) * .1; x = T*x+mqf; v = .5*x'*H*x + f*x; if max(A*x-b) <= 1e-6 return else disp('Difficult optimization. Omitting geometric preconditioning.') pass={H,f,A,b}; [x,v,opt] = solvopt2(x,@obj,@gobj,opt,@pen,@gpen,pass); if max(A*x-b) > opt(6) disp('Feasible optimum not found. Searching again.') x=mqf+(rand(n,1)-.5); [x,v,opt] = solvopt2(x,@obj,@gobj,opt,@pen,@gpen,pass); if max(A*x-b) > opt(6) error('Optimization failure: Feasible optimum not found.') end end return end else % low-dimensional pass={H,f,A,b}; %opt=[-1,1e-4,1e-6,15000,0,1e-8,2.5,1e-11]; % defaults opt=[-1,1e-6,1e-8,15e5,0,1e-8,2.5,1e-11]; % increase precision %opt=[-1,1e-14,1e-14,15e5,0,1e-14,2.5,1e-12]; % very high precision [x,v,opt] = solvopt2(x,@obj,@gobj,opt,@pen,@gpen,pass); if max(A*x-b) > opt(6) disp('Feasible optimum not found. Searching again.') x=mqf+(rand(n,1)-.5); [x,v,opt] = solvopt2(x,@obj,@gobj,opt,@pen,@gpen,pass); if max(A*x-b) > opt(6) error('Optimization failure: feasible optimum not found.') end end end return function q = obj(x,pass) % objective function H=pass{1}; f=pass{2}; q = .5*x'*H*x+f*x; return function q = gobj(x,pass); % gradient of objective function H=pass{1}; f=pass{2}; q = H*x+f'; return function q=pen(x,pass) % contraint penalty A=pass{3}; b=pass{4}; q=max(0,A*x-b); q=sum(q(:)); return function q=gpen(x,pass) % gradient of contraint penalty A=pass{3}; b=pass{4}; q=A*x-b; q(q<0)=0; q = q'*A/sqrt(q'*q); return function [x,f,options]=solvopt2(x,fun,grad,options,func,gradc,pass) % added 'pass' input to pass params to fun/func/grad/gradc; also quieted warnings % Usage: % [x,f,options]=solvopt(x,fun,grad,options,func,gradc) % The function SOLVOPT performs a modified version of Shor's r-algorithm in % order to find a local minimum resp. maximum of a nonlinear function % defined on the n-dimensional Euclidean space % or % a solution of a nonlinear constrained problem: % min { f(x): g(x) (<)= 0, g(x) in R(m), x in R(n) } % Arguments: % x is the n-vector (row or column) of the coordinates of the starting % point, % fun is the name of an M-file (M-function) which computes the value % of the objective function at a point x, % synopsis: f=fun(x) % grad is the name of an M-file (M-function) which computes the gradient % vector of the function at a point x, % synopsis: g=grad(x) % func is the name of an M-file (M-function) which computes the MAXIMAL % RESIDUAL(!) for a set of constraints at a point x, % synopsis: fc=func(x) % gradc is the name of an M-file (M-function) which computes the gradient % vector for the maximal residual consyraint at a point x, % synopsis: gc=gradc(x) % options is a row vector of optional parameters: % options(1)= H, where sign(H)=-1 resp. sign(H)=+1 means minimize % resp. maximize (valid only for unconstrained problem) % and H itself is a factor for the initial trial step size % (options(1)=-1 by default), % options(2)= relative error for the argument in terms of the % infinity-norm (1.e-4 by default), % options(3)= relative error for the function value (1.e-6 by default), % options(4)= limit for the number of iterations (15000 by default), % options(5)= control of the display of intermediate results and error % resp. warning messages (default value is 0, i.e., no intermediate % output but error and warning messages, see more in the manual), % options(6)= admissible maximal residual for a set of constraints % (options(6)=1e-8 by default, see more in the manual), % *options(7)= the coefficient of space dilation (2.5 by default), % *options(8)= lower bound for the stepsize used for the difference % approximation of gradients (1e-12 by default, see more in the manual). % (* ... changes should be done with care) % Returned values: % x is the optimizer (row resp. column), % f is the optimum function value, % options returns the values of the counters % options(9), the number of iterations, if positive, % or an abnormal stop code, if negative (see more in the manual), % options(10), the number of objective % options(11), the number of gradient evaluations, % options(12), the number of constraint function evaluations, % options(13), the number of constraint gradient evaluations. % ____________________________________________________________________________ shhh = 1; % silence warnings (not errors) % strings: ----{ errmes='SolvOpt error:'; wrnmes='SolvOpt warning:'; error1='No function name and/or starting point passed to the function.'; error2='Argument X has to be a row or column vector of dimension > 1.'; error30=' returns an empty string.'; error31='Function value does not exist (NaN is returned).'; error32='Function equals infinity at the point.'; error40=' returns an improper matrix. Check the dimension.'; error41='Gradient does not exist (NaN is returned by ).'; error42='Gradient equals infinity at the starting point.'; error43='Gradient equals zero at the starting point.'; error50=' returns an empty string.'; error51=' returns NaN at the point.'; error52=' returns infinite value at the point.'; error60=' returns an improper vector. Check the dimension'; error61=' returns NaN at the point.'; error62=' returns infinite vector at the point.'; error63=' returns zero vector at an infeasible point.'; error5='Function is unbounded.'; error6='Choose another starting point.'; warn1= 'Gradient is zero at the point, but stopping criteria are not fulfilled.'; warn20='Normal re-setting of a transformation matrix.' ; warn21='Re-setting due to the use of a new penalty coefficient.' ; warn4= 'Iterations limit exceeded.'; warn31='The function is flat in certain directions.'; warn32='Trying to recover by shifting insensitive variables.'; warn09='Re-run from recorded point.'; warn08='Ravine with a flat bottom is detected.'; termwarn0='SolvOpt: Normal termination.'; termwarn1='SolvOpt: Termination warning:'; appwarn='The above warning may be reasoned by inaccurate gradient approximation'; endwarn=[... 'Premature stop is possible. Try to re-run the routine from the obtained point. ';... 'Result may not provide the optimum. The function apparently has many extremum points. ';... 'Result may be inaccurate in the coordinates. The function is flat at the optimum. ';... 'Result may be inaccurate in a function value. The function is extremely steep at the optimum.']; % ----} % ARGUMENTS PASSED ----{ if nargin<2 % Function and/or starting point are not specified options(9)=-1; disp(errmes); disp(error1); return end if nargin<3, app=1; % No user-supplied gradients elseif isempty(grad), app=1; else, app=0; % Exact gradients are supplied end % OPTIONS ----{ doptions=[-1,1.e-4,1.e-6,15000,0,1.e-8,2.5,1e-11]; if nargin<4, options=doptions; elseif isempty(options), options=doptions; else, % Replace default options by user specified options: ii=find(options~=0);doptions(ii)=options(ii); options=doptions; end % Check the values: options([2:4,6:8])=abs(options([2:4,6:8])); options(2:3)=max(options(2:3),[1.e-12,1.e-12]); options(2)=max(options(8)*1.e2,options(2)); options(2:3)=min(options(2:3),[1,1]); options(6)=max(options(6),1e-12); options(7)=max([options(7),1.5]); options(8)=max(options(8),1e-11); % ----} if nargin<5, constr=0; % Unconstrained problem elseif isempty(func), constr=0; else, constr=1; % Constrained problem if nargin<6, appconstr=1; t=3; % No user-supplied gradients for constraints elseif isempty(gradc), appconstr=1; else, appconstr=0; % Exact gradients of constraints are supplied end end % ----} % STARTING POINT ----{ if max(size(x))<=1, disp(errmes); disp(error2); options(9)=-2; return elseif size(x,2)==1, n=size(x,1); x=x'; trx=1; elseif size(x,1)==1, n=size(x,2); trx=0; else, disp(errmes); disp(error2); options(9)=-2; return end % ----} % WORKING CONSTANTS AND COUNTERS ----{ options(10)=0; options(11)=0; % function and gradient calculations if constr options(12)=0; options(13)=0; % same for constraints end epsnorm=1.e-15;epsnorm2=1.e-30; % epsilon & epsilon^2 if constr, h1=-1; % NLP: restricted to minimization cnteps=options(6); % Max. admissible residual else, h1=sign(options(1)); % Minimize resp. maximize a function end k=0; % Iteration counter wdef=1/options(7)-1; % Default space transf. coeff. %Gamma control ---{ ajb=1+.1/n^2; % Base I ajp=20; ajpp=ajp; % Start value for the power ajs=1.15; % Base II knorms=0; gnorms=zeros(1,10); % Gradient norms stored %---} %Display control ---{ if options(5)<=0, dispdata=0; if options(5)==-1, dispwarn=0; else, dispwarn=1; end else, dispdata=round(options(5)); dispwarn=1; end, ld=dispdata; %---} %Stepsize control ---{ dq=5.1; % Step divider (at f_{i+1}>gamma*f_{i}) du20=2;du10=1.5;du03=1.05; % Step multipliers (at certain steps made) kstore=3;nsteps=zeros(1,kstore); % Steps made at the last 'kstore' iterations if app, des=6.3; % Desired number of steps per 1-D search else, des=3.3; end mxtc=3; % Number of trial cycles (steep wall detect) %---} termx=0; limxterm=50; % Counter and limit for x-criterion ddx =max(1e-11,options(8)); % stepsize for gradient approximation low_bound=-1+1e-4; % Lower bound cosine used to detect a ravine ZeroGrad=n*1.e-16; % Lower bound for a gradient norm nzero=0; % Zero-gradient events counter % Lower bound for values of variables taking into account lowxbound=max([options(2),1e-3]); % Lower bound for function values to be considered as making difference lowfbound=options(3)^2; krerun=0; % Re-run events counter detfr=options(3)*100; % relative error for f/f_{record} detxr=options(2)*10; % relative error for norm(x)/norm(x_{record}) warnno=0; % the number of warn.mess. to end with kflat=0; % counter for points of flatness stepvanish=0; % counter for vanished steps stopf=0; % ----} End of setting constants % ----} End of the preamble % COMPUTE THE FUNCTION ( FIRST TIME ) ----{ if trx, f=feval(fun,x',pass); else, f=feval(fun,x,pass); end options(10)=options(10)+1; if isempty(f), if dispwarn,disp(errmes);disp(error30);end options(9)=-3; if trx, x=x';end, return elseif isnan(f), if dispwarn,disp(errmes);disp(error31);disp(error6);end options(9)=-3; if trx, x=x';end, return elseif abs(f)==Inf, if dispwarn,disp(errmes);disp(error32);disp(error6);end options(9)=-3; if trx, x=x';end, return end xrec=x; frec=f; % record point and function value % Constrained problem if constr, fp=f; kless=0; if trx, fc=feval(func,x',pass); else, fc=feval(func,x,pass); end if isempty(fc), if dispwarn,disp(errmes);disp(error50);end options(9)=-5; if trx, x=x';end, return elseif isnan(fc), if dispwarn,disp(errmes);disp(error51);disp(error6);end options(9)=-5; if trx, x=x';end, return elseif abs(fc)==Inf, if dispwarn,disp(errmes);disp(error52);disp(error6);end options(9)=-5; if trx, x=x';end, return end options(12)=options(12)+1; PenCoef=1; % first rough approximation if fc<=cnteps, FP=1; fc=0; % feasible point else, FP=0; % infeasible point end f=f+PenCoef*fc; end % ----} % COMPUTE THE GRADIENT ( FIRST TIME ) ----{ if app, deltax=h1*ddx*ones(size(x)); if constr, if trx, g=apprgrdn2(x',fp,fun,pass,deltax',1); else, g=apprgrdn2(x ,fp,fun,pass,deltax,1); end else, if trx, g=apprgrdn2(x',f,fun,pass,deltax',1); else, g=apprgrdn2(x ,f,fun,pass,deltax,1); end end, options(10)=options(10)+n; else, if trx, g=feval(grad,x',pass); else, g=feval(grad,x,pass); end options(11)=options(11)+1; end if size(g,2)==1, g=g'; end, ng=norm(g); if size(g,2)~=n, if dispwarn,disp(errmes);disp(error40);end options(9)=-4; if trx, x=x';end, return elseif isnan(ng), if dispwarn,disp(errmes);disp(error41);disp(error6);end options(9)=-4; if trx, x=x';end, return elseif ng==Inf, if dispwarn,disp(errmes);disp(error42);disp(error6);end options(9)=-4; if trx, x=x';end, return elseif ng2*kd, kd=kd+1; warnno=1; if any(abs(x-xx)epsnorm*norm(gt)) z=z/nrmz; g1=gt+w*(z*gt')*z; B=B+w*(B*z')*z; else z=zeros(1,n); nrmz=0; g1=gt; end d1=norm(g1); g0=(g1/d1)*B'; % ----} % RESETTING ----{ if kcheck>1 idx=find(abs(g)>ZeroGrad); numelem=size(idx,2); if numelem>0, grbnd=epsnorm*numelem^2; if all(abs(g1(idx))<=abs(g(idx))*grbnd) | nrmz==0 if dispwarn & ~shhh, disp(wrnmes); disp(warn20); end if abs(fst-f)1.2*PenCoef, PenCoef=PenCoefNew; Reset=1; kless=0; f=f+PenCoef*fc; break end end end end f=f+PenCoef*fc; end if abs(f)==Inf | isnan(f) if dispwarn & ~shhh, disp(wrnmes); if isnan(f), disp(error31); else, disp(error32); end end if ksm | kc>=mxtc, options(9)=-3; if trx, x=x';end, return else, k2=k2+1;k1=0; hp=hp/dq; x=x1;f=f1; knan=1; if constr, FP=FP1; fp=fp1; end end % STEP SIZE IS ZERO TO THE EXTENT OF EPSNORM elseif all(abs(x-x1)=5, options(9)=-14; if dispwarn, disp(termwarn1); disp(endwarn(4,:)); end if trx,x=x';end, return else, x=x1; f=f1; hp=hp*10; ksm=1; if constr, FP=FP1; fp=fp1; end end % USE SMALLER STEP elseif h1*f=mxtc, break, end % 1-D OPTIMIZER IS LEFT BEHIND else if h1*f<=h1*f1, break, end % USE LARGER STEP k1=k1+1; if k2>0, kc=kc+1; end, k2=0; if k1>=20, hp=du20*hp; elseif k1>=10, hp=du10*hp; elseif k1>=3, hp=du03*hp; end end end % ----} End of 1-D search % ADJUST THE TRIAL STEP SIZE ----{ dx=norm(xopt-x); if kg=2, nsteps(2:kg)=nsteps(1:kg-1); end nsteps(1)=dx/(abs(h)*norm(g0)); kk=sum(nsteps(1:kg).*[kg:-1:1])/sum([kg:-1:1]); if kk>des, if kg==1, h=h*(kk-des+1); else, h=h*sqrt(kk-des+1); end elseif kk=20, PenCoef=PenCoef/10; Reset=1; kless=0; end else, kless=0; end if appconstr, deltax=sign(x); idx=find(deltax==0); deltax(idx)=ones(size(idx)); deltax=ddx*deltax; if trx, gc=apprgrdn2(x',fc,func,pass,deltax',0); else, gc=apprgrdn2(x ,fc,func,pass,deltax ,0); end options(12)=options(12)+n; else, if trx, gc=feval(gradc,x',pass); else, gc=feval(gradc,x ,pass); end options(13)=options(13)+1; end if size(gc,2)==1, gc=gc'; end, ngc=norm(gc); if isnan(ngc), if dispwarn,disp(errmes);disp(error61);end options(9)=-6; if trx, x=x';end, return elseif ngc==Inf, if dispwarn,disp(errmes);disp(error62);end options(9)=-6; if trx, x=x';end, return elseif ngch1*frec, frec=f; xrec=x; grec=g; end % ----} if ng>ZeroGrad, if knorms<10, knorms=knorms+1; end if knorms>=2, gnorms(2:knorms)=gnorms(1:knorms-1); end gnorms(1)=ng; nng=(prod(gnorms(1:knorms)))^(1/knorms); end % DISPLAY THE CURRENT VALUES ----{ if k==ld disp('Iter.# ..... Function ... Step Value ... Gradient Norm '); disp(sprintf('%5i %13.5e %13.5e %13.5e',k,f,dx,ng)); ld=k+dispdata; end %----} % CHECK THE STOPPING CRITERIA ----{ termflag=1; if constr, if ~FP, termflag=0; end, end if kcheck<=5, termflag=0; end if knan, termflag=0; end if kc>=mxtc, termflag=0; end % ARGUMENT if termflag idx=find(abs(x)>=lowxbound); if isempty(idx) | all(abs(xopt(idx)-x(idx))<=options(2)*abs(x(idx))) termx=termx+1; % FUNCTION if abs(f-frec)> detfr * abs(f) & ... abs(f-fopt)<=options(3)*abs(f) & ... krerun<=3 & ... ~constr if any(abs(xrec(idx)-x(idx))> detxr * abs(x(idx))) if dispwarn & ~shhh,disp(wrnmes);disp(warn09);end x=xrec; f=frec; g=grec; ng=norm(g); krerun=krerun+1; h=h1*max([dx,detxr*norm(x)])/krerun; warnno=2; break else, h=h*10; end elseif abs(f-frec)> options(3)*abs(f) & ... norm(x-xrec)=limxterm ) if stopf if dx<=laststep if warnno==1 & ng=limxterm options(9)=-14; if dispwarn, disp(termwarn1); disp(endwarn(4,:)); if app, disp(appwarn); end end x=xrec; f=frec; if trx,x=x';end, return else, stopf=0; end end end % ITERATIONS LIMIT if(k==options(4)) options(9)=-9; if trx, x=x'; end, if dispwarn & ~shhh, disp(wrnmes); disp(warn4); end return end % ----} % ZERO GRADIENT ----{ if constr if ng<=ZeroGrad, if dispwarn, disp(termwarn1); disp(warn1); end options(9)=-8; if trx,x=x';end,return end else if ng<=ZeroGrad, nzero=nzero+1; if dispwarn & ~shhh, disp(wrnmes); disp(warn1); end if nzero>=3, options(9)=-8; if trx,x=x';end,return, end g0=-h*g0/2; for i=1:10, x=x+g0; if trx, f=feval(fun,x',pass); else, f=feval(fun,x ,pass); end options(10)=options(10)+1; if abs(f)==Inf if dispwarn, disp(errmes); disp(error32); end options(9)=-3;if trx,x=x';end,return elseif isnan(f), if dispwarn, disp(errmes); disp(error32); end options(9)=-3;if trx,x=x';end,return end if app, deltax=sign(g0); idx=find(deltax==0); deltax(idx)=ones(size(idx)); deltax=h1*ddx*deltax; if trx, g=apprgrdn2(x',f,fun,pass,deltax',1); else, g=apprgrdn2(x ,f,fun,pass,deltax ,1); end options(10)=options(10)+n; else if trx, g=feval(grad,x',pass); else, g=feval(grad,x ,pass); end options(11)=options(11)+1; end if size(g,2)==1, g=g'; end, ng=norm(g); if ng==Inf if dispwarn, disp(errmes); disp(error42); end options(9)=-4; if trx, x=x'; end, return elseif isnan(ng) if dispwarn, disp(errmes); disp(error41); end options(9)=-4; if trx, x=x'; end, return end if ng>ZeroGrad, break, end end if ng<=ZeroGrad, if dispwarn, disp(termwarn1); disp(warn1); end options(9)=-8; if trx,x=x';end,return end h=h1*dx; break end end % ----} % FUNCTION IS FLAT AT THE POINT ----{ if ~constr & abs(f-fopt)5 & ng<1 idx=find(abs(g)<=epsnorm2); ni=size(idx,2); if ni>=1 & ni<=n/2 & kflat<=3, kflat=kflat+1; if dispwarn & ~shhh, disp(wrnmes); disp(warn31); end, warnno=1; x1=x; fm=f; for j=idx, y=x(j); f2=fm; if y==0, x1(j)=1; elseif abs(y)<1, x1(j)=sign(y); else, x1(j)=y; end for i=1:20, x1(j)=x1(j)/1.15; if trx, f1=feval(fun,x1',pass); else, f1=feval(fun,x1 ,pass); end options(10)=options(10)+1; if abs(f1)~=Inf & ~isnan(f1), if h1*f1>h1*fm, y=x1(j); fm=f1; elseif h1*f2>h1*f1, break elseif f2==f1, x1(j)=x1(j)/1.5; end, f2=f1; end end x1(j)=y; end if h1*fm>h1*f if app, deltax=h1*ddx*ones(size(deltax)); if trx, gt=apprgrdn2(x1',fm,fun,pass,deltax',1); else, gt=apprgrdn2(x1 ,fm,fun,pass,deltax ,1); end options(10)=options(10)+n; else if trx, gt=feval(grad,x1',pass); else, gt=feval(grad,x1 ,pass); end options(11)=options(11)+1; end if size(gt,2)==1, gt=gt'; end, ngt=norm(gt); if ~isnan(ngt) & ngt>epsnorm2, if dispwarn, disp(warn32); end options(3)=options(3)/5; x=x1; g=gt; ng=ngt; f=fm; h=h1*dx/3; break end end end end % ----} end % iterations end % restart % end of the function % function g = apprgrdn2(x,f,fun,pass,deltax,obj) % added 'pass' input to pass params to called function % Usage: % g = apprgrdn(x,f,fun,deltax,obj) % Function apprgrdn.m performs the finite difference approximation % of the gradient at a point . % is the calculated function value at a point , % is the name of the Matlab function, which calculates function values % is a vector of the relative stepsizes, % is the flag indicating whether the gradient of the objective % function (1) or the constraint function (0) is to be calculated. % n=max(size(x)); ee=ones(size(x)); di=abs(x); idx=find(di<5e-15); di(idx)=5e-15*ee(idx); di=deltax.*di; if obj, idx=find(abs(di)<2e-10); di(idx)=2e-10*sign(di(idx)); else, idx=find(abs(di)<5e-15); di(idx)=5e-15*sign(di(idx)); end y=x; for i=1:n y(i)=x(i)+di(i); fi=feval(fun,y,pass); if obj, if fi==f, for j=1:3 di(i)=di(i)*10; y(i)=x(i)+di(i); fi=feval(fun,y,pass); if fi~=f, break, end end end, end g(i)=(fi-f)/di(i); if obj, if any(idx==i) y(i)=x(i)-di(i); fi=feval(fun,y,pass); g(i)=.5*(g(i)+(f-fi)/di(i)); end, end y(i)=x(i); end