... ...
Consider the nonlinear matrix problem
\[ \left[\left(\begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix}\right) + \vert \vert x \vert \vert \left(\begin{matrix} 0 & 1 \\ -1 & 0 \end{matrix}\right) \right] \mathbf{x} = \left(\begin{matrix} 0 \\ \frac{1}{2} \end{matrix}\right) \] Construct a sequence of approximate solutions \(x_n \) by solving the linear problems
\[ \left[\left(\begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix}\right) + \vert \vert x_{n-1} \vert \vert \left(\begin{matrix} 0 & 1 \\ -1 & 0 \end{matrix}\right) \right] \mathbf{x} = \left(\begin{matrix} 0 \\ \frac{1}{2} \end{matrix}\right) \ \ , \ \ \mathbf{x}_0 = \left(\begin{matrix} 0 \\ 0 \end{matrix}\right) \]What happens if the rhs is \(\left(\begin{matrix} 0 \\ 1 \end{matrix}\right)\) instead of \(\left(\begin{matrix} 0 \\ \frac{1}{2} \end{matrix}\right)\) ?
If we apply the matrix \(\mathbf{A} \) to an arbitrary vector \(\mathbf{y}\), what happens?
First we can expand the vector in eigenbasis \[ \mathbf{y} = \sum_{n} \alpha_n \mathbf{x}_n \] and if applying to the matrix \(\mathbf{A} \) \[ \mathbf{A} \mathbf{y} = \sum_{n} \alpha_n \mathbf{A} \mathbf{x}_n = \sum_{n} \alpha_n \lambda_n \mathbf{x}_n \] So applying a matrix to an arbitrary vector amplifies the eigenvectors with large eigenvalues that contribute to the vector.
The algorithm becomes:
If we wish to change the eigenvalues but not the eigenvectors of a matrix (so-called spectral transformations), we can apply an matrix inversion \[\mathbf{A} \mathbf{x} = \lambda \mathbf{x} \ \ \rightarrow \ \ \mathbf{A}^{-1} \mathbf{x} = \lambda^{-1} \mathbf{x} \] So we apply the fix point iteration to the inverse matrix \(\tilde{\mathbf{A}} = \mathbf{A}^{-1} \).
So that means, that the largest eigenvalue \(\tilde{\lambda} \) of \(\mathbf{\tilde{A}} \) is always the smallest eigenvalue
Another spectral transformation is adding a constant \(\mu \) to the diagonal: \[\mathbf{A} \mathbf{x} = \lambda \mathbf{x} \ \ \rightarrow \ \ \left(\mathbf{A} + \mu \mathbf{I} \right) \mathbf{x} = \mathbf{A} \mathbf{x} + \mu \mathbf{x} = \lambda \mathbf{x} + \mu \mathbf{x} = \left(\lambda + \mu \right) \mathbf{x} \] We can combine the spectral transformation by adding the constant \(\mu \) to the diagonal and then invert that matrix. \[ \tilde{\mathbf{A}} = \left(\mathbf{A} - \mu \mathbf{I} \right)^{-1} \] The largest eigenvalue \(\tilde{\lambda} \) of \(\mathbf{\tilde{A}} \) is the eigenvalue \(\lambda = \mu + \tilde{\lambda}^{-1} \) of \(\mathbf{A} \) that is closest to \(\mu \)
This implementation involves three iterative methods for finding eigenvalues and eigenvectors of a matrix \(\mathbf{A}\)
The different considerations for all the algorithms are:
The specific considerations for the Inverse Power Iteration and Shift-and-Invert are
What I did:
So using this we can rewrite the Rayleigh quotient:
\[ \lambda = \frac{\mathbf{y}^{\intercal} \mathbf{A} \mathbf{y}}{\mathbf{y}^{\intercal} \mathbf{y}} \]Implementing the three iterations methods (variations os Fix Point Iterations):
The results from the command line are shown in Figure 2 and corresponds with the given values of \(\lambda \)
The convergence plot (with 10 iterations) showing the three different iteration methods are shown in Figure 3. The results from the command line are shown in Figure 4
import numpy as np import matplotlib.pyplot as plt # Parameters deflation = 0.1 # Matrices and vectors A = np.array([[1, 2], [3, 4]]) B = np.array([[0, 1], [-1, 0]]) x = np.array([1, -1]) b = np.array([0, 0.5]) # b = np.array([0, 1]) history = [] # Iterative process for ii in range(10): x = np.linalg.inv(A + np.linalg.norm(x) * B).dot(b) # x = (1 - deflation) * x + deflation * np.linalg.inv(A + np.linalg.norm(x) * B).dot(b) history.append(x) # Convert history to a numpy array for plotting history = np.array(history).T # Plotting the history plt.plot(history[0],'ko-' , label='x1') plt.plot(history[1],'bo-', label='x2') plt.xlabel('Iteration') plt.ylabel('Value') plt.legend() plt.show() # Uncomment the following lines to plot the semilog graph of the differences # diff_history = np.diff(history) # plt.semilogy(np.abs(diff_history[0]), label='diff x1') # plt.semilogy(np.abs(diff_history[1]), label='diff x2') # plt.xlabel('Iteration') # plt.ylabel('Absolute Difference') # plt.legend() # plt.show() # Print the final value of x print(history[:, -1])
clear all; close all; deflation = 0.1; A = [1 2; 3 4]; B = [0 1; -1 0]; x = [1; -1]; b = [0; 0.5]; %b = [0; 1]; history = []; for ii = 1:100 x = inv(A + norm(x) * B) * b; %x = (1 - deflation) * x + deflation * inv(A + norm(x) * B) * b; history = [history, x]; end plot(history') %semilogy(abs(diff(history'))) history(:, end)
#include < iostream > #include < Eigen/Dense > #include < vector > #include "matplotlibcpp.h"