1. The analytic SVD
Nearly everybody knows the matrix SVD $$ A=USV^T, $$ where $U,V$ are orthogonal and $S$ is diagonal with nonnegative nonincreasing elements. A less known generalization is the analytic SVD: Let $A(t)$ be a matrix whose elements are analytic functions of a parameter $t$ belonging to a real interval (for example, $t \in [-1,1]$). Then, there exists an analytic singular value decomposition [1,2] $$ A(t)=U(t)S(t)V(t)^T, $$ in which each matrix on the right-hand side is analytic for $t \in [-1,1]$. Moreover, $U(t)$ and $V(t)$ are unitary for $t \in [-1,1]$, while $S(t)$ is a diagonal matrix whose entries are real analytic functions of $t$, although not necessarily positive or ordered (these relaxations are necessary to achieve analyticity)
2. A non-smooth SVD
Let's try to use Chebfun to explore the analytic SVD. We define a $4\times 4$ matrix $A(t)$ depending affinely on $t$:
function AnalyticSVD()
tic clear, close all LW = 'linewidth'; MS = 'markersize'; FS = 'fontsize'; lw = 2; fs = 14; ms = 10; CO = 'color'; VEC = 'vectorize'; SP = 'splitting'; m = 4; n = 4; rng(10); A = randn(m,n); B = randn(m,n); AA = @(t) A*t + B*(1-t);
Next, we use Chebfun to resolve the analytic SVD as a function. We expect the initial outcome to be likely to have many singularities, for reasons to be clarified below, and for this reason we use 'splitting on'. We now create a function UVSVD that, given a matrix $A$, outputs one of the scalar elements of the SVD (see the listing at the end). Chebfun with the flag 'splitting on' will introduce break points, which we highlight in the plot. The black vertical lines indicate the x-values of the break points, with the black circles showing the location of the particular singular value that requires splitting.
for ii = 1:n f = chebfun(@(t) UVSVD(AA(t),ii),SP,'on',VEC); plot(f,LW,lw), hold on, grid on b = f.domain(2:end-1); k = length(b); for j = 1:k, x = b(j); plot(x*[1 1],[0 4],'k'), plot(x,f(x),'ko'),end end
Now let's also look at the singular vectors.
for pos = 1:n uu = chebfun(@(t)UVSVD(AA(t),1,pos,1),SP,'on',VEC); ss = chebfun(@(t)UVSVD(AA(t),pos,pos,2),SP,'on',VEC); vv = chebfun(@(t)UVSVD(AA(t),1,pos,3),SP,'on',VEC); subplot(1,3,1), hold on, grid on plot(ss,LW,lw), title('singular values') subplot(1,3,2), hold on plot(uu,LW,lw), title('U') subplot(1,3,3), hold on plot(vv,LW,lw), title('V') % store chebfuns for later use uupos{pos} = uu; sspos{pos} = ss; vvpos{pos} = vv; end
At the moment neither the singular values nor the singular vectors look like analytic functions. One reason is that the theory prescribes the singular values of an analytic SVD to be possibly negative: otherwise, points of nondifferentiability may occur.
3. Making the singular values smooth
To cure this, we look at the breakpoints of the singular values' chebfuns, and we flip the signs of every other segment if they do correspond to a discontinuity in the derivative. Moreover, precisely one of the two singular vectors corresponding to a nondifferentiable singular value must be affected by a discontinuity. Hence, we flip the sign of the corresponding chebfun accordingly.
clf for pos = 1:n uu = uupos{pos}; vv = vvpos{pos}; ss = sspos{pos}; endsss = ss.ends(2:end-1); endsuu = uu.ends(2:end-1); endsvv = vv.ends(2:end-1); ssp = diff(ss); %derivative of singular values spleft = ssp(endsss,'left'); %left-derivatives at breakpoints spright = ssp(endsss,'right'); %right-derivatives at breakpoints sdisc = find(abs(spleft-spright)>1e-8); %non-smooth break points uleft = uu(endsss(sdisc),'left'); uright = uu(endsss(sdisc),'right'); for ii = 1:length(sdisc) ss = chebfun(@(t)ss(t).*sign(endsss(sdisc(ii))-t),SP,'on',VEC); if abs(uleft-uright)>1e-8 uu = chebfun(@(t)uu(t).*sign(endsss(sdisc(ii))-t),SP,'on',VEC); else vv = chebfun(@(t)vv(t).*sign(endsss(sdisc(ii))-t),SP,'on',VEC); end end subplot(1,3,1), hold on, grid on plot(ss,LW,lw), title('singular values') subplot(1,3,2), hold on plot(uu,LW,lw), title('U') subplot(1,3,3), hold on plot(vv,LW,lw), title('V') uupos{pos} = uu; sspos{pos} = ss; vvpos{pos} = vv; end
4. Making the singular vectors smooth
After this treatment, the singular values now do look nice and smooth. This is not the case for the singular vectors yet. Why? This time, the explanation is not mathematical, but computational: MATLAB's svd makes some arbitrary choices on the signs of the singular vectors that might not fit well with the analytic SVD. Again, this is easily remedied by looking at breakpoints in the singular vectors' chebfuns, and by flipping the sign every other segment; this resembles the unwrap command for obtaining continuous arguments for complex numbers; see http://www.chebfun.org/examples/complex/Arguments.html
clf for pos = 1:n uu = uupos{pos}; vv = vvpos{pos}; ss = sspos{pos}; endsuu = uu.ends(2:end-1); uleft = uu(endsuu,'left'); uright = uu(endsuu,'right'); jumps = find(abs(uleft-uright)>1e-8); for ii = 1:length(jumps) uu = chebfun(@(t)uu(t).*sign(endsuu(jumps(ii))-t),SP,'on',VEC); vv = chebfun(@(t)vv(t).*sign(endsuu(jumps(ii))-t),SP,'on',VEC); end subplot(1,3,1) plot(ss,LW,lw), hold on, grid on, title('singular values') subplot(1,3,2) plot(uu,LW,lw), hold on, grid on, title('U') subplot(1,3,3) plot(vv,LW,lw), hold on, grid on, title('V') uupos{pos} = uu; vvpos{pos} = vv; sspos{pos} = ss; end
5. Eliminating the unnecessary breakpoints
Now these functions are supposed to be analytic across the interval $[-1,1]$. We form a global chebfun to confirm this. We show the plots for the first and last singular values; the others look similar.
clf for pos = [1 n] uu = uupos{pos}; uu = chebfun(@(t)uu(t)); ss = sspos{pos}; ss = chebfun(@(t)ss(t)); vv = vvpos{pos}; vv = chebfun(@(t)vv(t)); plotcoeffs(uu,'b.',LW,lw), hold on plotcoeffs(ss,'k.',LW,lw) plotcoeffs(vv,'r.',LW,lw) text(length(uu)+5,eps*10,['U_{',num2str(pos),'1}'],CO,'b',FS,fs) text(length(ss)+5,eps/10,['\sigma_',num2str(pos)],CO,'k',FS,fs) text(length(vv)+5,eps/1e3,['V_{',num2str(pos),'1}'],CO,'r',FS,fs) end
And we are finally happy! Nonetheless, one should not assume that computing an analytic SVD is always this simple: we have avoided the difficult case where multiple singular values are present, in which case the singular vectors need to be chosen very carefully. Nearly-multiple singular values can be equally challenging to deal with numerically. See [1] for an algorithm that addresses these issues, which still seems to be a state-of-the-art reference on computing an analytic SVD.
Unfortunately, these computations are not very fast:
time_in_seconds = toc
time_in_seconds = 1.128618140000000e+02
6. References
[1] A. Bunse-Gerstner, R. Byers, V. Mehrmann and N. Nichols, Numerical computation of an analytic singular value decomposition of a matrix valued function, Numerische Mathematik (1991), 60(1), 1--39.
[2] T. Kato, Perturbation Theory for Linear Operators, Springer, 1995.
end function y = UVSVD(A,i,j,pos) % (ij) element of U(if pos=1), S(if pos=2) , V(if pos=3) if nargin==1 i = 1; j = 1; end if nargin<4 pos = 2; end [U,S,V] = svd(A,0); if pos == 1 y = U(i,j); elseif pos == 2 y = S(i,i); else y = V(i,j); end end