@@ -842,6 +842,7 @@ The eigenvectors and eigenvalues of a map $A$ determine how a vector $v$ is tran
842
842
843
843
This is discussed further later.
844
844
845
+ ## Exercises
845
846
846
847
``` {exercise}
847
848
:label: eig1_ex1
@@ -865,6 +866,10 @@ Visualize your results by plotting the eigenvalue as a function of the number of
865
866
:class: dropdown
866
867
```
867
868
869
+ Here is one solution.
870
+
871
+ We start by looking into the distance between the eigenvector approximation and the true eigenvector.
872
+
868
873
``` {code-cell} ipython3
869
874
# Define a matrix A
870
875
A = np.array([[1, 0, 3],
@@ -878,6 +883,7 @@ num_iters = 20
878
883
b = np.random.rand(A.shape[1])
879
884
880
885
# Initialize a list to store the eigenvector approximations
886
+ norm_ls = []
881
887
res = []
882
888
883
889
# Power iteration loop
@@ -887,53 +893,29 @@ for i in range(num_iters):
887
893
# Normalize b
888
894
b = b / np.linalg.norm(b)
889
895
# 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)
892
899
893
900
# Plot the eigenvector approximations for each iteration
894
901
plt.figure(figsize=(10, 6))
895
902
plt.xlabel('Iterations')
896
903
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 )
899
906
```
900
907
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
919
909
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
930
912
eigenvector = np.linalg.eig(A)[1][:, 0]
913
+
931
914
# Set up the figure and axis for 3D plot
932
915
fig = plt.figure()
933
916
ax = fig.add_subplot(111, projection='3d')
934
917
935
- # Plot the actual eigenvectors
936
-
918
+ # Plot the eigenvectors
937
919
ax.scatter(eigenvector[0], eigenvector[1], eigenvector[2], color='r', s = 80)
938
920
939
921
# Plot the approximated eigenvectors (b) at each iteration
@@ -943,7 +925,7 @@ for i, vec in enumerate(res):
943
925
ax.set_xlabel('X')
944
926
ax.set_ylabel('Y')
945
927
ax.set_zlabel('Z')
946
- ax.set_title('Power iteration eigenvector approximations ')
928
+ ax.set_title('Power Iteration and Eigenvector Approximations ')
947
929
points = [plt.Line2D([0], [0], linestyle='none', c=i, marker='o') for i in ['r', 'b']]
948
930
ax.legend(points, ['Actual eigenvectors', 'Approximated eigenvectors (b)'], numpoints=1)
949
931
ax.set_box_aspect(aspect=None, zoom=0.8)
@@ -1006,8 +988,10 @@ c.arrows.set_alpha(0.5)
1006
988
1007
989
# Plot the eigenvectors as long blue and green arrows
1008
990
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)
1011
995
1012
996
colors = ['b', 'g']
1013
997
lines = [Line2D([0], [0], color=c, linewidth=3) for c in colors]
@@ -1094,7 +1078,8 @@ for i, example in enumerate(examples):
1094
1078
c.arrows.set_alpha(0.5)
1095
1079
1096
1080
# 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}
1098
1083
origin = np.zeros((2, len(eigenvectors)))
1099
1084
ax[i].quiver(*origin, eigenvectors_real[0], eigenvectors_real[1], **parameters)
1100
1085
ax[i].quiver(*origin, - eigenvectors_real[0], - eigenvectors_real[1], **parameters)
@@ -1107,6 +1092,8 @@ for i, example in enumerate(examples):
1107
1092
plt.show()
1108
1093
```
1109
1094
1095
+ The vector fields explains why we observed the trajectories of the vector $v$ multiplied by $A$ iteratively before.
1096
+
1110
1097
The pattern demonstrated here is because we have complex eigenvalues and eigenvectors.
1111
1098
1112
1099
It is important to acknowledge that there is a complex plane.
@@ -1129,18 +1116,11 @@ class Arrow3D(FancyArrowPatch):
1129
1116
self.set_positions((0.1*xs[0],0.1*ys[0]),(0.1*xs[1],0.1*ys[1]))
1130
1117
1131
1118
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
1138
1119
1139
- # Find eigenvalues and eigenvectors
1140
1120
eigenvalues, eigenvectors = np.linalg.eig(A)
1141
1121
1142
1122
# 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 ))
1144
1124
1145
1125
# Calculate vector field (real and imaginary parts)
1146
1126
u_real = A[0][0] * x + A[0][1] * y
@@ -1154,7 +1134,7 @@ ax = fig.add_subplot(111, projection='3d')
1154
1134
vlength = np.linalg.norm(eigenvectors)
1155
1135
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)
1156
1136
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)
1158
1138
1159
1139
# Plot 3D eigenvectors
1160
1140
for c, i in zip(['b', 'g'], [0, 1]):
0 commit comments