function [x,fval] = trustregprob(Q,b,w,doEquality)
if ~exist('doEquality','var')
doEquality=true;
end
if w<0, error 'Arguemnt ''w'' must be non-negative.'; end
if ~w
x=zeros(size(b));x=x(:);
fval=0;
return
end
N=size(Q,1);
[V,H]=eig((Q+Q)/2);
h=diag(H);
posdefIneq=all(h>=0) & ~doEquality;
if ~isreal(h) || ~isreal(V),
disp 'Q not symmetric?'
keyboard;
end
if ~any(b)
if posdefIneq
x=b;
else
[lambda,imin] = min(h);
x=w*V(:,imin);
end
if nargout>1, fval=(x.'*(h.*x))/2; end
elseif posdefIneq
Vt=V.';
g=Vt*b;
x=g./h;
if norm(x)<w
if nargout>1,
fval=(x.'*(h.*x))/2 - dot(g,x);
end
x=V*x;
else
[x,fval]= trustregprob(spdiags(h,0),g,w);
end
else
Vt=V.';
g=Vt*b;
hmin=min(h);
idx=logical(g);
gnz=g(idx);
hnz=h(idx);
[him,im]=min(hnz);
gim=gnz(im);
fun=@(lambda) norm( gnz./(hnz-lambda) ) - w;
ub=him-abs(gim)/w;
i=0;
lb=ub-10^i;
while fun(lb)>=0
i=i+1;
lb=ub-10^i;
end
lambda=fzero(fun,[lb,ub]);
if lambda>hmin
x=g;
x(idx)=g(idx)./(h(idx)-hmin);
cc=w-norm(x)^2;
nidx=~idx;
nn=sum(nidx);
x(nidx)=sqrt(cc/nn);
else
x=g;
x(idx)=g(idx)./(h(idx)-lambda);
end
if nargout>1,
fval=(x.'*(h.*x))/2 - dot(g,x);
end
x=V*x;
end
Best Answer