1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
function cholmod_updown_demo
%CHOLMOD_UPDOWN_DEMO a demo for CHOLMOD's update/downdate and row add/delete
%
% Provides a short demo of CHOLMOD's update/downdate and row add/delete
% functions.
%
% Example:
% cholmod_updown_demo
%
% See also CHOLMOD_DEMO
% Copyright 2015, Timothy A. Davis, http://www.suitesparse.com
fprintf ('\n\n------------------------------------------------------------\n') ;
fprintf ('demo of CHOLMOD update/downdate and row add/delete functions\n') ;
fprintf ('------------------------------------------------------------\n\n') ;
% A is the matrix used in the MATLAB 'bench' demo
A = delsq (numgrid ('L', 300)) ;
n = size (A,1) ;
% make b small so we can use absolute error norms, norm (A*x-b)
b = rand (n,1) / n ;
% L*D*L' = A(p,p). The 2nd argument is zero if A is positive definite.
[LD,ignore,p] = ldlchol (A) ;
% solve Ax=b using the L*D*L' factorization of A(p,p)
c = b (p) ;
x = ldlsolve (LD, c) ;
x (p) = x ;
err = norm (A*x-b) ;
fprintf ('norm (A*x-b) using ldlsolve: %g\n', err) ;
if (err > 1e-12)
error ('!')
end
% solve again, just using backslash
tic
x = A\b ;
t1 = toc ;
err = norm (A*x-b) ;
fprintf ('norm (A*x-b) using backslash: %g\n', err) ;
fprintf ('time for x=A\\b: %g\n', t1) ;
if (err > 1e-12)
error ('!')
end
% check the norm of LDL'-S
[L,D] = ldlsplit (LD) ;
S = A (p,p) ;
err = norm (L*D*L' - S, 1) ;
fprintf ('nnz (L) for original matrix: %d\n', nnz (L)) ;
% rank-1 update of the L*D*L' factorization
% A becomes A2=A+W*W', and S becomes S2=S+C*C'. Some fillin occurs.
fprintf ('\n\n------------------------------------------------------------\n') ;
fprintf ('Update A to A+W*W'', and the permuted S=A(p,p) becomes S+C*C'':\n') ;
W = sparse ([1 2 3 152], [1 1 1 1], [5 -1 -1 -1], n, 1)
C = W (p,:)
tic
LD2 = ldlupdate (LD, C, '+') ;
t2 = toc ;
S2 = S + C*C' ;
A2 = A + W*W' ;
[L,D] = ldlsplit (LD2) ;
err = norm (L*D*L' - S2, 1) ;
fprintf ('norm (LDL-S2) after update: %g\n', err) ;
fprintf ('nnz (L) after rank-1 update: %d\n', nnz (L)) ;
if (err > 1e-12)
error ('!')
end
% solve A2*x=b using the updated LDL factorization
tic
c = b (p) ;
x = ldlsolve (LD2, c) ;
x (p) = x ;
t3 = toc ;
err = norm (A2*x-b) ;
fprintf ('norm (A*x-b) using ldlsolve: %g\n', err) ;
if (err > 1e-12)
error ('!')
end
fprintf ('time to solve x=A\\b using update: %g\n', t2 + t3) ;
% solve again, just using backslash
tic
x = A2\b ;
t1 = toc ;
err = norm (A2*x-b) ;
fprintf ('norm (A*x-b) using backslash: %g\n', err) ;
if (err > 1e-12)
error ('!')
end
fprintf ('time for x=A\\b: %g\n', t1) ;
fprintf ('speedup of update vs backslash: %g\n', t1 / (t2 + t3)) ;
% invert the permutation
invp = zeros (1,n) ;
invp (p) = 1:n ;
% delete row 3 of A to get A3. This corresponds to row invp(3) in S and LDL
fprintf ('\n\n------------------------------------------------------------\n') ;
fprintf ('Delete row 3\n') ;
k = 3 ;
pk = invp (k) ;
I = speye (n) ;
A3 = A ;
A3 (:,k) = I (:,k) ;
A3 (k,:) = I (k,:) ;
tic
LD3 = ldlrowmod (LD, pk) ;
t2 = toc ;
S3 = S ;
S3 (:,pk) = I (:,pk) ;
S3 (pk,:) = I (pk,:) ;
[L,D] = ldlsplit (LD3) ;
err = norm (L*D*L' - S3, 1) ;
fprintf ('norm (LDL-S3) after row del: %g\n', err) ;
if (err > 1e-12)
error ('!')
end
% solve A3*x=b using the modified LDL factorization
tic
c = b (p) ;
x = ldlsolve (LD3, c) ; % x = S3\c
x (p) = x ; % now x = A3\b
t3 = toc ;
err = norm (A3*x-b) ;
fprintf ('norm (A3*x-b) after row del: %g\n', err) ;
fprintf ('nnz (L) after row del: %d\n', nnz (L)) ;
if (err > 1e-12)
error ('!')
end
% solve again using backslash
tic
x = A3\b ;
t1 = toc ;
err = norm (A3*x-b) ;
fprintf ('norm (A3*x-b) with backslash: %g\n', err) ;
fprintf ('time for x=A\\b with backslash %g\n', t1) ;
fprintf ('time for x=A\\b using rowdel: %g\n', t2 + t3) ;
fprintf ('speedup of rowdel vs backslash: %g\n', t1 / (t2 + t3)) ;
% add row 3 back to A3 to get A4. This corresponds to row invp(3) in S and LDL
fprintf ('\n\n------------------------------------------------------------\n') ;
fprintf ('Add row 3 back\n') ;
W = sparse ([1 3 7 9], [1 1 1 1], [-1 8 -1 -1], n, 1) ;
A4 = A3 ;
A4 (:,k) = W ;
A4 (k,:) = W' ;
C = W (p) ; % permuted version of row/column 3
S4 = S3 ;
S4 (:,pk) = C ;
S4 (pk,:) = C' ;
tic
LD4 = ldlrowmod (LD3, pk, C) ;
t2 = toc ;
fprintf ('nnz (L) after row add: %d\n', nnz (L)) ;
[L,D] = ldlsplit (LD4) ;
err = norm (L*D*L' - S4, 1) ;
fprintf ('norm (LDL-S4) after row add: %g\n', err) ;
if (err > 1e-12)
error ('!')
end
% solve A4*x=b using the modified LDL factorization
tic
c = b (p) ;
x = ldlsolve (LD4, c) ; % x = S4\c
x (p) = x ; % now x = A4\b
t3 = toc ;
err = norm (A4*x-b) ;
fprintf ('norm (A4*x-b) after row add: %g\n', err) ;
if (err > 1e-12)
error ('!')
end
% solve A4*x=b using backslash
tic
x = A4\b ;
t1 = toc ;
err = norm (A4*x-b) ;
fprintf ('norm (A4*x-b) with backslash: %g\n', err) ;
if (err > 1e-12)
error ('!')
end
fprintf ('time for x=A\\b with backslash %g\n', t1) ;
fprintf ('time for x=A\\b using rowadd: %g\n', t2 + t3) ;
fprintf ('speedup of rowadd vs backslash: %g\n', t1 / (t2 + t3)) ;
|