I have made some MATLAB code for Cholupdate algorithm. The problem is that some times it works, some times not.

function [L] = cholupdate2(L, x, OP)
  cholupdate(L, x, OP) % OP can be "+" = rank_one_update or "-" = rank_one_downdate
  F = 1;
  if(strcmp(OP, '-') == 1)
    F = -1; % Rank_one_downdate
  end
  n = length(x);
  for k = 1:n
      a = L(k,k);
      b = x(k);
      r = sqrt(a*a + F * b*b);
      c = r / a;
      s = b / a;
      L(k, k) = -r;
      if k < n
          for i = k+1:n
            L(k, i) = -(L(k,i) + F * s * x(i)) / c;
            x(i) = -c * x(i) - s * L(k, i);
          end
      end
  end
end

If I try an example

A = [-3.2462,  2.1783,      2.4925,           0;
           0, -3.3096,     -1.4982,           0;
           0,       0,     -5.8431,     -1.0139;
           0,       0,           0,     -4.8889];

x =  [-3.0105,
       2.2319,
       2.5538,
           0];

cholupdate2(A, x, '+')  %// or '-' (see the MATLAB code in cholupdate function above)

Then I get the output.

ans =

  -4.4273   3.1148   3.5641        0
        0  -3.3132  -1.5049        0
        0        0  -5.8441  -1.0137
        0        0        0  -4.8889

ans =

  -4.4273   3.1148   3.5641        0
        0  -3.3132  -1.5049        0
        0        0  -5.8441  -1.0137
        0        0        0  -4.8889

The first matrix is from MATLAB/GNU Octave, the second matrix is from my cholupdate2 function.

But if I change -3.3096 to 3.3096 inside the A matrix.

Now I'm getting the output. As you can see, they are not 100% exactly the same.

ans =

  -4.4273   3.1148   3.5641        0
        0   3.3132  -1.4882        0
        0        0  -5.8483  -1.0130
        0        0        0  -4.8891

ans =

  -4.4273   3.1148   3.5641        0
        0  -3.3132   1.4882        0
        0        0  -5.8483  -1.0130
        0        0        0  -4.8891

I took the source code from Wikipedia and modify so it will return not-transpose back, which is do inside the Wikipedia code. I also added the rank-one downdate functionality.

So my question for you is:

If I got a matrix A and I want to update it with cholesky update. I need to add

$$\tilde A = A + x*x^T$$

Is that correct? What can $x$ be then?


Solution 1:

Consider the SPD matrix $\mathbf{A} = \mathbf{U}^T \mathbf{U}$. We are interested in the Cholesky decomposition of its rank-one update: $\mathbf{A}_1= \mathbf{A}+\mathbf{x}\mathbf{x}^T = \mathbf{U}_1^T \mathbf{U}_1$.

The cholupdate function computes $\mathbf{U}_1$ from the knowledge of $\mathbf{U}$ and $\mathbf{x}$

The idea is to consider the extended $(n+1)\times n$ matrix $\mathbf{B}= \begin{bmatrix} \mathbf{x}^T \\ \mathbf{U} \end{bmatrix} $ and find the (orthogonal) Givens rotations such that $ \mathbf{C} = \mathbf{G}_n \mathbf{G}_1 \mathbf{B}= \begin{bmatrix} \mathbf{0}^T \\ \mathbf{U}_1 \end{bmatrix} $ where $\mathbf{U}_1$ is upper triangular.

Because the Givens rotations are orthogonal, we see that $ \mathbf{C}^T\mathbf{C}= \mathbf{B}^T\mathbf{B}= \mathbf{U}^T\mathbf{U}+\mathbf{x}\mathbf{x}^T = \mathbf{U}_1^T\mathbf{U}_1$

Solution 2:

Your decomposition is as valid as the one from Matlab/GNU Octave because there is some degree of freedom in the row sign of $\mathbf{U}$. On your example, the Given matrix transforms

B=
   -3.0105    2.2319    2.5538         0
   -3.2462    2.1783    2.4925         0
         0   -3.3096   -1.4982         0
         0         0   -5.8431   -1.0139
         0         0         0   -4.8889

into

G1*B=
         0    0.1553    0.1776         0
   -4.4273    3.1148    3.5641         0
         0   -3.3096   -1.4982         0
         0         0   -5.8431   -1.0139
         0         0         0   -4.8889

then

G2*G1*B =
         0         0    0.1072         0
   -4.4273    3.1148    3.5641         0
         0   -3.3132   -1.5049         0
         0         0   -5.8431   -1.0139
         0         0         0   -4.8889

and finally

G3*G2*G1*B =

         0         0   -0.0000   -0.0186
   -4.4273    3.1148    3.5641         0
         0   -3.3132   -1.5049         0
         0         0   -5.8441   -1.0137
         0         0         0   -4.8889