function [vf eeval]=inversefov(A,z,use_eigs,tol,iters) %If possible, this function determines a solution to the %inverse field of values problem: Given a z in the field %of values of A determine a vector vf such that %z = vf'*A*vf. % Inputs: A a square matrix % z a complex number in the field of values of A % use_eigs 1 indicates whether eigs will be used rather than eig % tol tolerance used for deciding how small |vf'*A*vf-z| % must be for accepting vf as a generating vector for z % iters Maximum number of iterations % % Outputs: vf generating vector for z % eeval Number of eigenvalue computations performed % % % R. Carden June 8 2009 % warning off if nargin<2 disp('Must specify a matrix A and a point in the numerical range of A') vf=[]; eeval=0; return elseif nargin <5 iters=30; elseif nargin <4 tol=1e-14; elseif nargin <3 use_eigs=0; end if use_eigs==1 boundarypt = @eigs_boundarypt; else boundarypt = @eig_boundarypt; end opts.disp=0; opts.tol=tol/1000; err1=1000; err0=1; [ n m]=size(A); jj=1; eeval=0; %Number of eigenvalue evaluations performed Vbox=zeros(n,4); rvbox=zeros(1,4); %Determine four points on the boundary of numerical range for i=1:2 th=((i-1)*pi/2)-pi; AA=exp(-1i*th)*(A); HA=(AA+AA')/2; if use_eigs==0 [va sa]=eig(HA);eeval=eeval+1; sa=diag(sa); else [v1 s1]=eigs(HA,1,'LR',opts);eeval=eeval+1; [v2 s2]=eigs(HA,1,'SR',opts);eeval=eeval+1; va=[v1 v2]; sa=[s1 s2]; end [val I ]= max(sa); Vbox(:,1+(i-1))=va(:,I); rvbox(1+(i-1))=va(:,I)'*A*va(:,I); [val I ]= min(sa); Vbox(:,3+(i-1))=va(:,I); rvbox(3+(i-1))=va(:,I)'*A*va(:,I); end %pick a point outside the numerical range for determining if $z$ is in %polygonal approximation q=real(rvbox(3))+ max(.1,.1*real(rvbox(3)-rvbox(1)))+1i*(imag(rvbox(4))+ max(.1,.1*imag((rvbox(4)-rvbox(2))))); %Form outer approximation to numerical range x1=min(real(rvbox));y1=min(imag(rvbox)); x2=max(real(rvbox));y2=max(imag(rvbox)); obox=[x1+1i*y1 x2+1i*y1 x2+1i*y2 x1+1i*y2]; ttol=max(x2-x1,y2-y1)*tol*2; if ((x2-x1)<=1e-14*(x2+x1)/2) && ((y2-y1)<=1e-14*(y2+y1)/2) ttol=tol; end tol=ttol; %Check if matrix is skew-symmetric, symmetric or if numerical range %is a point. if ((x2-x1)tol rvf=[]; vf=[]; eeval=-eeval; % disp('Clearly not in the numerical range') end else %If we are here then the area of the outer approximation is not %negligable. Check that z is inside the outer approximation. [ni fon] =insidequad([x1+1i*y1 x2+1i*y1 x2+1i*y2 x1+1i*y2],z,q,tol); if mod(ni,2)==1 ni=0; %Determine if inner approximation is a line drvbox=[rvbox rvbox(1)]; drvbox=abs(diff(drvbox)); i=find(drvbox2 [ni fon] =insidequad(rvbox,z,q,tol); end if mod(ni,2)==1 err1=0; err0=0; %z is strictly inside the inner approximation %Problem reduces to determining a boundary point rvc of the inner %approximation such that rvbox(1)-rvc passes through z angle1=angle((z-rvbox(1))*conj(rvbox(3)-rvbox(1))); if abs(angle1)<1e-14 %If z lies on rvbox(1)-rvbox(3) Vc=orth(Vbox(:,[1 3])); rvc=z; else if angle1>0 &&length(rvbox)~=3 rvbox=rvbox([1 3 4]); Vbox=Vbox(:,[1 3 4]); end %Use law of sines to determine where ray from rvbox to z intersects. %ray from rvbox(3)to rvbox(2) angle1=angle((rvbox(3)-rvbox(1))*conj(z-rvbox(1))); angle2=angle((rvbox(2)-rvbox(3))*conj(rvbox(1)-rvbox(3))); angle3=pi-angle1-angle2; rv3torvc=sin(angle1)/(sin(angle3)/abs(rvbox(3)-rvbox(1))); rvc=rv3torvc*exp(1i*angle(rvbox(2)-rvbox(3)))+rvbox(3); Vc=orth(Vbox(:,[2 3])); end %Determine Ritz vector for rvc H=Vc'*A*Vc; Y=nearritz(H,rvc,tol); vc=Vc*Y; rvc=vc'*A*vc; %Determine a Ritz vector for z if abs(rvc-z)tol %Determine closest point on rvarvb rvd=real((z-rva)*conj(rvb-rva))/abs(rvb-rva); rvd=rvd*exp(1i*angle(rvb-rva))+rva; rvf=rvd; %The angle from x1 to z must always gives us a new point on the %boundary of the numerical range unless of %course z is on the line between rva and rvb %Might want to check if z and rvd are indeed the same point %because the angle would be undefined in that case if abs(z-rvf)>tol th=angle(z-rvd); AA=exp(-1i*th)*(A); HA=(AA+AA')/2; vc=boundarypt(); rvc=vc'*A*vc; eeval=eeval+1; %Now we have a new point and we can immediately %check whether z is in this new triangle or %if we must select a new base for our next triangle. %Outer approximation check if tolabs(rvd-z) %In this case we encountered an ill %conditioned problem (skinny triangle) in determining rvd %because rvf should have exactly generated %z. vf=vd; rvf=rvd; end break end end else %Determine Ritz vector for point nearest to z %This is the only part of the code that if possible takes %advantage of nondegenerate ellipses. Vc=orth([va vb]); H=Vc'*A*Vc; Y=nearritz(H,z,tol); vf=Vc*Y; rvf=vf'*A*vf; break end %Set things up for the next iteration %Determine side of the triangle to which z is closest %Recall triangle points should be stored in %rva rvb and rvc %Sides of concern are rva rvc and rvb rvc cm=(rva+rvc+rvb)/3; %theangles=angle(([rva rvb rvc]-cm)*exp(-1i*angle(z-cm))); theangles=myunwrap(angle([rva rvc rvb]-cm)); zangle= myunwrap([angle(rva-cm) angle(z-cm)]); zangle=zangle(2); theangles = theangles-zangle; an=sum(theangles<0); bn=an+1; if an==1 rvb=rvc; vb=vc; else rva=rvc; va=vc; end jj=jj+1; if jj>iters break end err0=err1; err1=abs(rvf-z); if abs(err0-err1)=-tol) &&(x4-x1>=-tol)&&(y2-y3>=-tol)&&(y4-y1>=-tol) if ~((abs(p3-p1)1e-15)) %The p3 falls on the line p1p2 and our work is done %fon=i; ni=ni+1; end end else %p3 is a vertex of the polygon. ni=ni+.5; fon=fon+1; end end end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function Y=nearritz(H,z,tol) %Determines the vector Y such that z=Y'*HY %H must be a 2x2 matrix %tol tolerance for determining if H is normal %Uses Horn and Johnson analysis of field of values of 2x2 matrix from %Topics in Matrix Analysis. %Things decouple nicely for 2x2 matrices of the form %[ 0 a ; b 0 ] [SH]=eig(H); cH=trace(H)/2; tH=SH-cH; rangle=angle(tH(1,1)); %save thedata4 tH=(H-cH*eye(2))*exp(-1i*rangle); [U S]=schur(tH); CHm= S; Dm=diag([1,exp(-1i*angle(CHm(1,2)))]); CH=(Dm'*CHm*Dm); CH=real(CH); a=CH(2,2); b=CH(1,2)/2; d=sqrt(a^2+b^2); if abs(a)CHTP(1,2) Dl=[0 1 ; 1 0]; else Dl=eye(2); end CHTP=Dl*CHTP*Dl; CHTP=CHTP-diag(abs(diag(CHTP))); y=[cos(theta); sin(theta)*exp(1i*phi)]; Y=U*Dm*X'*D'*Dl'*y; pr=Y'*H*Y; [ pr z]; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function cz=closetoellipse(a,b,u,v) % Determines closest point on ellipse with semimajor and semiminor axis %lengths of a and b centered at the origin to the point (u,v) %See 'Distance from a Point to an Ellipse in 2D %David Eberly http://www.geometrictools.com %Modify (u,v), so it is in the first quadrant quad=0; if v<0 quad=bitor(quad,2); v=-v; end if u<0 quad=bitor(quad,1); u=-u; end %Largest root of the following determines %the closest point tr= roots([(-1) (- 2*a^2 - 2*b^2) (a^2*u^2 - 4*a^2*b^2 - a^4 - b^4 + b^2*v^2) (2*a^2*b^2*u^2 - 2*a^2*b^4 - 2*a^4*b^2 + 2*a^2*b^2*v^2) (a^4*b^2*v^2 - a^4*b^4 + a^2*b^4*u^2)]); t=tr(real(tr)>=-b^2*(1+1e-8)); [val ind]=sort(real(t),'descend'); %This wouldn't work in general %however do to the nature of the inversefov algorithm %the point will always have abs(u)<=a if abs(v)