Matrix-free iterations Tobin A. Driscoll Richard J. Braun 
In Chapter 4, we solved the nonlinear rootfinding problem f ( x ) = 0 \mathbf{f}(\mathbf{x})=\boldsymbol{0} f ( x ) = 0 f \mathbf{f} f x \mathbf{x} x f \mathbf{f} f f − 1 ( 0 ) \mathbf{f}^{-1}(\boldsymbol{0}) f − 1 ( 0 ) 
We can explore the same idea in the context of linear algebra by shifting our viewpoint from matrices to linear transformations . If we define f ( x ) = A x \mathbf{f}(\mathbf{x})=\mathbf{A}\mathbf{x} f ( x ) = Ax x \mathbf{x} x y \mathbf{y} y α \alpha α 
f ( x + y ) = f ( x ) + f ( y ) , f ( α x ) = α   f ( x ) . \begin{split}
\mathbf{f}(\mathbf{x} + \mathbf{y} ) &= \mathbf{f}(\mathbf{x}) + \mathbf{f}(\mathbf{y} ), \\
\mathbf{f}(\alpha \mathbf{x} ) & = \alpha\, \mathbf{f}(\mathbf{x}).
\end{split} f ( x + y ) f ( α x )  = f ( x ) + f ( y ) , = α f ( x ) .  These properties define a linear transformation. Moreover, every  linear transformation between finite-dimensional vector spaces can be represented as a matrix-vector multiplication.
A close examination reveals that in the power iteration and Krylov subspace methods, the only appearance of the matrix A \mathbf{A} A f ( x ) = A x \mathbf{f}(\mathbf{x})=\mathbf{A}\mathbf{x} f ( x ) = Ax f \mathbf{f} f 
8.7.1 Blurring images ¶ In From matrix to insight  we saw that a grayscale image can be represented as an m × n m\times n m × n X \mathbf{X} X B \mathbf{B} B m × m m\times m m × m 
B i j = { 1 2 if  i = j , 1 4 if  ∣ i − j ∣ = 1 , 0 otherwise. B_{ij} =
\begin{cases}
\tfrac{1}{2} & \text{if $i=j$},\\
\tfrac{1}{4} & \text{if $|i-j|=1$},\\
0 & \text{otherwise.}
\end{cases} B ij  = ⎩ ⎨ ⎧  2 1  4 1  0  if  i = j , if ∣ i − j ∣ = 1 , otherwise.  The product B X \mathbf{B}\mathbf{X} BX B \mathbf{B} B X \mathbf{X} X B \mathbf{B} B 
In order to blur horizontally, we can transpose the image and apply blurring in the same way. We need a blurring matrix defined as in (8.7.2) n × n n\times n n × n C \mathbf{C} C C \mathbf{C} C 
( C X T ) T = X C T = X C , \bigl(\mathbf{C} \mathbf{X}^T\bigr)^T = \mathbf{X}\mathbf{C}^T = \mathbf{X}\mathbf{C}, ( C X T ) T = X C T = XC , using the symmetry of C \mathbf{C} C 
blur  ( X ) = B k X C k \operatorname{blur}(\mathbf{X}) = \mathbf{B}^k \mathbf{X} \mathbf{C}^k blur ( X ) = B k X C k for a positive integer k k k 
Example 8.7.1  (Blurring an image)
Example 8.7.1 We use a readily available test image.
using Images, TestImages
img = testimage("mandrill")
m, n = size(img)
X = @. Float64(Gray(img))
plot(Gray.(X), title="Original image", aspect_ratio=1)We define the one-dimensional tridiagonal blurring matrices.
using SparseArrays
function blurmatrix(d)
    v1 = fill(0.25, d - 1)
    return spdiagm(0 => fill(0.5, d), 1 => v1, -1 => v1)
end
B, C = blurmatrix(m), blurmatrix(n);
Finally, we show the results of using k = 12 k=12 k = 12 
using Plots
blur = X -> B^12 * X * C^12;
Z = blur(X)
plot(Gray.(Z), title="Blurred image")Example 8.7.1 We use a readily available test image.
load mandrill
[m, n] = size(X);
clf
imshow(X, [0, 255])
title('Original image')    % ignore thisWe define the one-dimensional tridiagonal blurring matrices.
v = [1/4, 1/2, 1/4];
B = spdiags(v, -1:1, m, m);
C = spdiags(v, -1:1, n, n);
Finally, we show the results of using k = 12 k=12 k = 12 
blur = @(X) B^12 * X * C^12;
imshow(blur(X), [0, 255])
title(('Blurred image'));Example 8.7.1 We use a readily available test image.
from skimage import data as testimages
from skimage.color import rgb2gray
img = getattr(testimages, "coffee")()
X = rgb2gray(img)
imshow(X, cmap="gray");We define the one-dimensional tridiagonal blurring matrices.
import scipy.sparse as sp
def blurmatrix(d):
    data = [[0.25] * (d-1), [0.5] * d, [0.25] * (d-1)]
    return sp.diags(data, [-1, 0, 1], shape=(d, d))
m, n = X.shape
B = blurmatrix(m)
C = blurmatrix(n)
Finally, we show the results of using k = 12 k=12 k = 12 
from scipy.sparse.linalg import matrix_power
blur = lambda X: matrix_power(B, 12) @ X @ matrix_power(C, 12)
imshow(blur(X), cmap="gray")
title("Blurred image");8.7.2 Deblurring ¶ A more interesting operation is deblurring : given an image blurred by poor focus, can we reconstruct the true image? Conceptually, we want to invert the function blur  ( X ) \operatorname{blur}(\mathbf{X}) blur ( X ) 
It’s easy to see from (8.7.4) m × n m\times n m × n m n mn mn vec  ( X ) = x \operatorname{vec}(\mathbf{X})=\mathbf{x} vec ( X ) = x unvec  ( x ) = X \operatorname{unvec}(\mathbf{x})=\mathbf{X} unvec ( x ) = X X \mathbf{X} X Z = blur  ( X ) \mathbf{Z}=\operatorname{blur}(\mathbf{X}) Z = blur ( X ) A \mathbf{A} A 
A vec  ( X ) = vec  ( Z ) , \mathbf{A} \operatorname{vec}(\mathbf{X}) = \operatorname{vec}(\mathbf{Z}), A vec ( X ) = vec ( Z ) , or A x = z \mathbf{A}\mathbf{x}=\mathbf{z} Ax = z 
The matrix A \mathbf{A} A m n × m n mn\times mn mn × mn 1.4 × 1 0 14 1.4\times 10^{14} 1.4 × 1 0 14 
Instead, given any vector u \mathbf{u} u v = A u \mathbf{v}=\mathbf{A}\mathbf{u} v = Au 
U = unvec  ( u ) , V = blur  ( U ) , v = vec  ( V ) . \begin{align*}
  \mathbf{U} &= \operatorname{unvec}(\mathbf{u}), \\
  \mathbf{V} &= \operatorname{blur}(\mathbf{U}), \\
  \mathbf{v} &= \operatorname{vec}(\mathbf{V}).
\end{align*} U V v  = unvec ( u ) , = blur ( U ) , = vec ( V ) .  The following example shows how to put these ideas into practice with MINRES.
Example 8.7.2  (Deblurring an image)
Example 8.7.2 We repeat the earlier process to blur an original image X \mathbf{X} X Z \mathbf{Z} Z 
img = testimage("lighthouse")
m, n = size(img)
X = @. Float64(Gray(img))
B = spdiagm(0 => fill(0.5, m),
    1 => fill(0.25, m - 1), -1 => fill(0.25, m - 1))
C = spdiagm(0 => fill(0.5, n),
    1 => fill(0.25, n - 1), -1 => fill(0.25, n - 1))
blur = X -> B^12 * X * C^12
Z = blur(X)
plot(Gray.(Z), title="Blurred image")Now we imagine that X \mathbf{X} X Z \mathbf{Z} Z 
# vec (built-in) converts matrix to vector
unvec = z -> reshape(z, m, n);  # convert vector to matrix
Now we declare the three-step blur transformation as a LinearMap, supplying also the size of the vector form of an image.
using LinearMaps
T = LinearMap(x -> vec(blur(unvec(x))), m * n);
The blurring operators are symmetric, so we apply minres to the composite blurring transformation T.
Tip
The function clamp01 in Images restricts values to be in the interval [ 0 , 1 ] [0,1] [ 0 , 1 ] 
using IterativeSolvers
y = minres(T, vec(Z), maxiter=50, reltol=1e-5);
Y = unvec(clamp01.(y))
plot(Gray.(X), layout=2, title="Original")
plot!(Gray.(Y), subplot=2, title="Deblurred")Example 8.7.2 We repeat the earlier process to blur an original image X \mathbf{X} X Z \mathbf{Z} Z 
load mandrill
[m, n] = size(X);
v = [1/4, 1/2, 1/4];
B = spdiags(v, -1:1, m, m);
C = spdiags(v, -1:1, n, n);
blur = @(X) B^12 * X * C^12;
Z = blur(X);
clf,  imshow(Z, [0, 255])
title(("Blurred image"));Now we imagine that X \mathbf{X} X Z \mathbf{Z} Z 
vec = @(X) reshape(X,m*n,1);
unvec = @(x) reshape(x,m,n);
T = @(x) vec( blur(unvec(x)) );
The blurring operators are symmetric, so we apply minres to the composite blurring transformation T.
y = gmres(T, vec(Z), 50, 1e-5);
Y = unvec(y);
subplot(121)
imshow(X, [0, 255])
title("Original")
subplot(122)
imshow(Y, [0, 255])
title(("Deblurred"));gmres(50) converged at outer iteration 2 (inner iteration 45) to a solution with relative residual 1e-05.
 Example 8.7.2 We repeat the earlier process to blur an original image X \mathbf{X} X Z \mathbf{Z} Z 
img = getattr(testimages, "coffee")()
X = rgb2gray(img)
m, n = X.shape
import scipy.sparse as sp
def blurmatrix(d):
    data = [[0.25] * (d-1), [0.5] * d, [0.25] * (d-1)]
    return sp.diags(data, [-1, 0, 1], shape=(d, d))
B = blurmatrix(m)
C = blurmatrix(n)
from scipy.sparse.linalg import matrix_power
blur = lambda X: matrix_power(B, 12) @ X @ matrix_power(C, 12)
Z = blur(X)
imshow(Z, cmap="gray")
title("Blurred image");Now we imagine that X \mathbf{X} X Z \mathbf{Z} Z 
from scipy.sparse.linalg import LinearOperator
vec = lambda Z: Z.reshape(m * n)
unvec = lambda z: z.reshape(m, n)
xform = lambda x: vec(blur(unvec(x)))
Now we declare the three-step blur transformation as a LinearOperator, supplying also the size of the vector form of an image.
T = LinearOperator((m * n, m * n), matvec=xform)
The blurring operators are symmetric, so we apply minres to the composite blurring transformation T.
from scipy.sparse.linalg import gmres
y, flag = gmres(T, vec(Z), rtol=1e-5, maxiter=50)
Y = unvec(maximum(0, minimum(1, y)))
subplot(1, 2, 1),  imshow(X, cmap="gray")
axis("off"),  title("Original")
subplot(1, 2, 2),  imshow(Y, cmap="gray")
axis("off"),  title("Deblurred");8.7.3 Exercises ¶ ✍ In each case, state with reasons whether the given transformation on n n n 
(a)    f ( x ) = [ x 2 x 3 ⋮ x n x 1 ] \,\mathbf{f}(\mathbf{x}) = \begin{bmatrix} x_2\\x_3 \\\vdots\\ x_n \\ x_1 \end{bmatrix}\qquad f ( x ) = ⎣ ⎡  x 2  x 3  ⋮ x n  x 1   ⎦ ⎤  (b)    f ( x ) = [ x 1 x 1 + x 2 x 1 + x 2 + x 3 ⋮ x 1 + ⋯ + x n ] \,\mathbf{f}(\mathbf{x}) = \begin{bmatrix} x_1\\x_1+x_2\\x_1+x_2+x_3\\\vdots\\x_1+\cdots+x_n \end{bmatrix} \qquad f ( x ) = ⎣ ⎡  x 1  x 1  + x 2  x 1  + x 2  + x 3  ⋮ x 1  + ⋯ + x n   ⎦ ⎤  (c)    f ( x ) = [ x 1 + 1 x 2 + 2 x 3 + 3 ⋮ x n + n ] \,\mathbf{f}(\mathbf{x}) = \begin{bmatrix} x_1 + 1 \\x_2 + 2 \\ x_3 + 3 \\\vdots \\ x_n+n \end{bmatrix} \qquad f ( x ) = ⎣ ⎡  x 1  + 1 x 2  + 2 x 3  + 3 ⋮ x n  + n  ⎦ ⎤  (d)    f ( x ) = ∥ x ∥ ∞   e 1 \,\mathbf{f}(\mathbf{x}) = \|\mathbf{x}\|_\infty\, \mathbf{e}_1 f ( x ) = ∥ x ∥ ∞  e 1  
The condition number of the matrix of the blur transformation is related to the condition numbers of the single-dimension matrices B k \mathbf{B}^k B k C k \mathbf{C}^k C k (8.7.4) 
(a)  ⌨  Let m = 50 m=50 m = 50 B \mathbf{B} B SPD . Find κ ( B ) \kappa(\mathbf{B}) κ ( B ) cond requires a regular dense matrix, not a sparse matrix.)
(b)  ✍ Explain why part (a) implies κ ( B k ) = κ ( B ) k \kappa( \mathbf{B}^k ) = \kappa(\mathbf{B})^k κ ( B k ) = κ ( B ) k 
(c)  ✍ Explain two important effects of the limit k → ∞ k\to \infty k → ∞ 
The cumulative summation function cumsum is defined as
f ( x ) = [ x 1 x 1 + x 2 ⋮ x 1 + x 2 + ⋯ + x n ] . \mathbf{f}(\mathbf{x}) = \begin{bmatrix} x_1 \\ x_1+x_2 \\ \vdots \\ x_1 + x_2 + \cdots + x_n \end{bmatrix}. f ( x ) = ⎣ ⎡  x 1  x 1  + x 2  ⋮ x 1  + x 2  + ⋯ + x n   ⎦ ⎤  . (a)  ✍ Show that f \mathbf{f} f 
(b)  ⌨ Define vector b \mathbf{b} b b i = ( i / 100 ) 2 b_i = (i/100)^2 b i  = ( i /100 ) 2 i = 1 , … , 100 i=1,\ldots,100 i = 1 , … , 100 gmres to find x = f − 1 ( b ) \mathbf{x}=\mathbf{f}^{-1}(\mathbf{b}) x = f − 1 ( b ) 
(c)  ⌨ Plot x \mathbf{x} x