Skip to content

Commit 0d33575

Browse files
committed
update eigens
1 parent 9544c9f commit 0d33575

File tree

2 files changed

+29
-69
lines changed

2 files changed

+29
-69
lines changed

lectures/eigen_I.md

Lines changed: 27 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,7 @@ The eigenvectors and eigenvalues of a map $A$ determine how a vector $v$ is tran
842842

843843
This is discussed further later.
844844

845+
## Exercises
845846

846847
```{exercise}
847848
:label: eig1_ex1
@@ -865,6 +866,10 @@ Visualize your results by plotting the eigenvalue as a function of the number of
865866
:class: dropdown
866867
```
867868

869+
Here is one solution.
870+
871+
We start by looking into the distance between the eigenvector approximation and the true eigenvector.
872+
868873
```{code-cell} ipython3
869874
# Define a matrix A
870875
A = np.array([[1, 0, 3],
@@ -878,6 +883,7 @@ num_iters = 20
878883
b = np.random.rand(A.shape[1])
879884
880885
# Initialize a list to store the eigenvector approximations
886+
norm_ls = []
881887
res = []
882888
883889
# Power iteration loop
@@ -887,53 +893,29 @@ for i in range(num_iters):
887893
# Normalize b
888894
b = b / np.linalg.norm(b)
889895
# Append b to the list of eigenvector approximations
890-
dis = np.linalg.norm(np.array(b) - np.linalg.eig(A)[1][:, 0])
891-
res.append(dis)
896+
res.append(b)
897+
norm = np.linalg.norm(np.array(b) - np.linalg.eig(A)[1][:, 0])
898+
norm_ls.append(norm)
892899
893900
# Plot the eigenvector approximations for each iteration
894901
plt.figure(figsize=(10, 6))
895902
plt.xlabel('Iterations')
896903
plt.ylabel('L2 Norm')
897-
plt.title('Power Iteration and Eigenvector Approximations')
898-
_ = plt.plot(res)
904+
plt.title('Distance between the Approximation and the True Eigenvector')
905+
_ = plt.plot(norm_ls)
899906
```
900907

901-
```{code-cell} ipython3
902-
import numpy as np
903-
import matplotlib.pyplot as plt
904-
from mpl_toolkits.mplot3d import Axes3D
905-
906-
# Define a matrix A
907-
A = np.array([[1, 0, 3],
908-
[0, 2, 0],
909-
[3, 0, 1]])
910-
911-
# Define a number of iterations
912-
num_iters = 20
913-
914-
# Define a random starting vector b
915-
b = np.array([0.5, 1, 0.5])
916-
917-
# Initialize a list to store the eigenvector approximations
918-
res = [b]
908+
Then we can look at the trajectory of the eigenvector approximation
919909

920-
# Power iteration loop
921-
for i in range(num_iters):
922-
# Multiply b by A
923-
b = A @ b
924-
# Normalize b
925-
b = b / np.linalg.norm(b)
926-
# Append b to the list of eigenvector approximations
927-
res.append(b)
928-
929-
# Get the actual eigenvectors of matrix A
910+
```{code-cell} ipython3
911+
# Get the eigenvectors of matrix A
930912
eigenvector = np.linalg.eig(A)[1][:, 0]
913+
931914
# Set up the figure and axis for 3D plot
932915
fig = plt.figure()
933916
ax = fig.add_subplot(111, projection='3d')
934917
935-
# Plot the actual eigenvectors
936-
918+
# Plot the eigenvectors
937919
ax.scatter(eigenvector[0], eigenvector[1], eigenvector[2], color='r', s = 80)
938920
939921
# Plot the approximated eigenvectors (b) at each iteration
@@ -943,7 +925,7 @@ for i, vec in enumerate(res):
943925
ax.set_xlabel('X')
944926
ax.set_ylabel('Y')
945927
ax.set_zlabel('Z')
946-
ax.set_title('Power iteration eigenvector approximations')
928+
ax.set_title('Power Iteration and Eigenvector Approximations')
947929
points = [plt.Line2D([0], [0], linestyle='none', c=i, marker='o') for i in ['r', 'b']]
948930
ax.legend(points, ['Actual eigenvectors', 'Approximated eigenvectors (b)'], numpoints=1)
949931
ax.set_box_aspect(aspect=None, zoom=0.8)
@@ -1006,8 +988,10 @@ c.arrows.set_alpha(0.5)
1006988
1007989
# Plot the eigenvectors as long blue and green arrows
1008990
origin = np.zeros((2, len(eigenvectors)))
1009-
plt.quiver(*origin, eigenvectors[0], eigenvectors[1], color=['b', 'g'], angles='xy', scale_units='xy', scale=0.1, width=0.01)
1010-
plt.quiver(*origin, - eigenvectors[0], - eigenvectors[1], color=['b', 'g'], angles='xy', scale_units='xy', scale=0.1, width=0.01)
991+
parameters = {'color':['b', 'g'], 'angles':'xy',
992+
'scale_units':'xy', 'scale':0.1, 'width':0.01}
993+
plt.quiver(*origin, eigenvectors[0], eigenvectors[1], **parameters)
994+
plt.quiver(*origin, - eigenvectors[0], - eigenvectors[1], **parameters)
1011995
1012996
colors = ['b', 'g']
1013997
lines = [Line2D([0], [0], color=c, linewidth=3) for c in colors]
@@ -1094,7 +1078,8 @@ for i, example in enumerate(examples):
10941078
c.arrows.set_alpha(0.5)
10951079
10961080
# Plot the eigenvectors as long blue and green arrows
1097-
parameters = {'color':['b', 'g'], 'angles':'xy', 'scale_units':'xy', 'scale':1, 'width':0.01, 'alpha':0.5}
1081+
parameters = {'color':['b', 'g'], 'angles':'xy',
1082+
'scale_units':'xy', 'scale':1, 'width':0.01, 'alpha':0.5}
10981083
origin = np.zeros((2, len(eigenvectors)))
10991084
ax[i].quiver(*origin, eigenvectors_real[0], eigenvectors_real[1], **parameters)
11001085
ax[i].quiver(*origin, - eigenvectors_real[0], - eigenvectors_real[1], **parameters)
@@ -1107,6 +1092,8 @@ for i, example in enumerate(examples):
11071092
plt.show()
11081093
```
11091094

1095+
The vector fields explains why we observed the trajectories of the vector $v$ multiplied by $A$ iteratively before.
1096+
11101097
The pattern demonstrated here is because we have complex eigenvalues and eigenvectors.
11111098

11121099
It is important to acknowledge that there is a complex plane.
@@ -1129,18 +1116,11 @@ class Arrow3D(FancyArrowPatch):
11291116
self.set_positions((0.1*xs[0],0.1*ys[0]),(0.1*xs[1],0.1*ys[1]))
11301117
11311118
return np.min(zs)
1132-
1133-
1134-
# Define matrix A with complex eigenvalues
1135-
A = np.array([[sqrt(3) + 1, -2],
1136-
[1, sqrt(3) - 1]])
1137-
A = (1/(2*sqrt(2))) * A
11381119
1139-
# Find eigenvalues and eigenvectors
11401120
eigenvalues, eigenvectors = np.linalg.eig(A)
11411121
11421122
# Create meshgrid for vector field
1143-
x, y = np.meshgrid(np.linspace(-2, 2, 10), np.linspace(-2, 2, 10))
1123+
x, y = np.meshgrid(np.linspace(-2, 2, 15), np.linspace(-2, 2, 15))
11441124
11451125
# Calculate vector field (real and imaginary parts)
11461126
u_real = A[0][0] * x + A[0][1] * y
@@ -1154,7 +1134,7 @@ ax = fig.add_subplot(111, projection='3d')
11541134
vlength = np.linalg.norm(eigenvectors)
11551135
ax.quiver(x, y, u_imag, u_real-x, v_real-y, v_imag-u_imag, colors = 'b', alpha=0.3, length = .2, arrow_length_ratio = 0.01)
11561136
1157-
arrow_prop_dict = dict(mutation_scale=2, arrowstyle='-|>', shrinkA=0, shrinkB=0)
1137+
arrow_prop_dict = dict(mutation_scale=5, arrowstyle='-|>', shrinkA=0, shrinkB=0)
11581138
11591139
# Plot 3D eigenvectors
11601140
for c, i in zip(['b', 'g'], [0, 1]):

lectures/eigen_II.md

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -153,40 +153,20 @@ If a matrix $A \geq 0$ then,
153153
Moreover if $A$ is also irreducible then,
154154
155155
4. the eigenvector $v$ associated with the eigenvalue $r(A)$ is strictly positive.
156-
5. there exists no other positive eigenvector $v$ (except scalar multiples of v) associated with $r(A)$.
156+
5. there exists no other positive eigenvector $v$ (except scalar multiples of $v$) associated with $r(A)$.
157157
158158
If $A$ is primitive then,
159159
160-
6. the inequality $|\lambda| \leq r(A)$ is strict for all eigenvalues 𝜆 of 𝐴 distinct from 𝑟(𝐴), and
160+
6. the inequality $|\lambda| \leq r(A)$ is strict for all eigenvalues $\lambda$ of $A$ distinct from $r(A)$, and
161161
7. with $e$ and $\varepsilon$ normalized so that the inner product of $\varepsilon$ and $e = 1$, we have
162162
$ r(A)^{-m} A^m$ converges to $\varepsilon^{\top}$ when $m \rightarrow \infty$
163163
```
164164

165165
(This is a relatively simple version of the theorem --- for more details see
166166
[here](https://en.wikipedia.org/wiki/Perron%E2%80%93Frobenius_theorem)).
167167

168-
Let's build our intuition for the theorem using a simple example we have seen [before](mc_eg1).
169-
170-
```{math}
171-
P
172-
= \left(
173-
\begin{array}{cc}
174-
1 - \alpha & \alpha \\
175-
\beta & 1 - \beta
176-
\end{array}
177-
\right)
178-
```
179-
180-
In fact, we have already seen Perron-Frobenius theorem in action before in the exercise (TODO: link to Markov chain exercise)
181-
182-
In the exercise, we stated that the convegence rate is determined by the spectral gap, the difference between the largest and the second largest eigenvalue.
183-
184-
This can be proved using Perron-Frobenius theorem.
185-
186-
187168
We will see applications of the theorem below.
188169

189-
190170
(la_neumann)=
191171
## The Neumann Series Lemma
192172

0 commit comments

Comments
 (0)