(3.1,3.2はプログラム例なし) ■3.3 反復法による固有値 表3-1 べき乗法のプログラム import math def array(N1, N2=0):#配列 if N2!=0: return [[0 for i in range(N2)] for i in range(N1)] return [0 for i in range(N1)] def transM(A):#転置行列 N1=len(A); N2=len(A[0]);C=array(N2,N1) for i in range(N1): for j in range(N2):C[j][i]=A[i][j] return C def mltScalarV(S, B): N=len(B); C=array(N) for i in range(N): C[i]=S*B[i] return C def mltM(A,B):#行列乗算 NA1=len(A); NA2=len(A[0]);NB1=len(B); NB2=len(B[0]);NN=NA2 C=array(NA1,NB2) if NN>NB1: NN=NB1 for i in range(NA1): for j in range(NB2): C[i][j]=0 for k in range(NN): C[i][j]+= A[i][k]*B[k][j] return C def PowerIter(A, EPS):#べき乗法による固有値 N=len(A); X=array(N);XTemp=array(2,N) IterMax = 100; K1 = 1; K2 = 0; XTemp[K2][0] = 1 for Iter in range(IterMax): KK = K2; K2 = K1; K1 = KK ## K1:前回計算,K2;今回 for i in range(N): # 行列式の乗算 T = 0 for j in range(N): T += A[i][j] * XTemp[K1][j] XTemp[K2][i] = T T = 0 #ノルム1=1による方法 for i in range(N): T += XTemp[K2][i]*XTemp[K2][i] lamb = math.sqrt(T) if abs(lamb) < EPS : return [] #固有値が0のとき収束しない for i in range(N): XTemp[K2][i] /= lamb T1 = 0; T2 = 0 for i in range(N): DX = XTemp[K2][i]- XTemp[K1][i] T1 +=DX * DX; T2 += XTemp[K2][i] * XTemp[K2][i] if abs(T2) < EPS: return [] #固有ベクトルが0のとき収束しない E = T1 / T2 if E=0 :T = 1.0/(T+math.sqrt(T*T+1.0)) else: T = 1.0/(T-math.sqrt(T*T+1.0)) C = 1.0/math.sqrt(T*T+1); S = T*C; T *= A[j][k] D[j] = D[j]-T; D[k] = D[k]+T; A[j][k] = 0 for i in range(j): X = A[i][j]; Y = A[i][k] A[i][j] = X*C - Y*S; A[i][k] = X*S + Y*C for i in range(j + 1, k): X = A[j][i]; Y = A[i][k] A[j][i] = X*C - Y*S; A[i][k] = X*S + Y*C for i in range(k + 1, N): X = A[j][i]; Y = A[k][i] A[j][i] = X*C - Y*S; A[k][i] = X*S + Y*C for i in range(N): X = W[j][i]; Y = W[k][i] W[j][i] = X*C - Y*S; W[k][i] = X*S + Y*C if OK: break if OK: for i in range(N-1): k=i for j in range(i + 1, N): if D[j] > D[k] : k = j T = D[i]; D[i] = D[k]; D[k] = T T = W[i]; W[i] = W[k]; W[k] = T for i in range(N): for j in range(N): A[i][j]=W[j][i] return [D,A] else: print("収束しません"); return[] def mltEigenV(D,W):#固有値配列×固有ベクトル行列 N=len(D); C=array(N,N) for i in range(N): for j in range(N): C[j][i]=D[i]*W[j][i] return C A=[[4, 2, 1, 3], [2, 3, 1, 2], [1, 1, 2, 1], [3, 2, 1, 1]] DW=eigenJacobi(A); D=DW[0]; W=DW[1] printV(" λ =",D); printM(" W =",W) printM(" A*W =", mltM(A,W)); printM("λ*W =",mltEigenV(D,W)) 表3-6 三重対角化による固有値の計算 copyArrayについては表3-3, mltEigenV,printM,printVについては表3-5 を参照してください。)--- def tridiagonalize(MAT,EPS): A=copyArray(MAT) N=len(A);V=array(N); W=array(N+1);D=array(N);E=array(N) for k in range(N-2): D[k] = A[k][k] for i in range(k+1,N): W[i] = A[i][k] S = 0 for i in range(k+1,N):S += W[i]*W[i] if abs(S) > EPS: if W[k+1]>=0: S = math.sqrt(S) else: S = -math.sqrt(S) E[k+1] = -S; W[k+1] += S S = 1 / math.sqrt(W[k+1]*S) for i in range(k+1, N): W[i] *= S for i in range(k+1, N): S = 0 for j in range(k+1, i+1):S += A[i][j]*W[j] for j in range(i+1, N): S += A[j][i] * W[j] V[i] = S S = 0 for i in range(k+1,N): S +=W[i]*V[i] S /= 2 for i in range(k+1,N): V[i] -= S * W[i] for i in range(k+1,N): for j in range(k+1,i+1): A[i][j] = A[i][j] - W[i]*V[j]-W[j]*V[i] # 固有ベクトルを求めるときWの内容をAに移す for i in range(k+1,N): A[i][k] = W[i] else: E[k+1] = 0 D[N-2]= A[N-2][N-2]; D[N-1] = A[N-1][N-1]#制限値に注意 E[0] = 0; E[N-1] = A[N-1][N-2] #以下,固有ベクトル計算用 for k in range(N-1, -1,-1): if k < N - 1: for i in range(k+1,N): W[i] = A[i][k] for i in range(k+1,N): S = 0 for j in range(k+1,N): S += A[i][j]*W[j] V[i] = S for i in range(k+1, N): for j in range(k+1,N): A[i][j] -= V[i]*W[j] for i in range(N): A[i][k] = 0 A[k][k]= 1 return [D,E,A] def Zero(D,E,i): T=0 if i>0:T=abs(D[i])+abs(D[i-1]) return (T+abs(E[i]))==T def eigenHouseholder(MAT,EPS): MaxIter = 20; N=len(MAT) DEA=tridiagonalize(MAT,EPS); D=DEA[0]; E=DEA[1]; A=DEA[2] E[0] = 1.0; H = N-1 while Zero(D, E, H):H-=1 while H > 0: E[0] = 0.0; L = H - 1 while not Zero(D, E, L): L -=1 for Iter in range(MaxIter): W = (D[H-1]-D[H])/2; S = math.sqrt(W*W+E[H]*E[H]) if W < 0 : S = -S X = D[L]-D[H]+E[H]*E[H]/(W+S); Y = E[L+1]; Z = 0 for k in range(L,H): if abs(X) >= abs(Y): T = -Y/X; C = 1/math.sqrt(T*T+1); S = T*C else: T = -X/Y; S = 1/math.sqrt(T*T+1) if T < 0 : S = -S C = T*S W = D[k]-D[k+1]; T = (W*S+2*C*E[k+1])*S D[k]-=T; D[k+1]+= T E[k] = C*E[k]-S*Z; E[k+1] = E[k+1]*(C*C-S*S)+W*S*C for i in range(N): X = A[k][i]; Y = A[k+1][i] A[k][i] = C*X - S*Y; A[k+1][i] = S*X + C*Y if k < N - 2 : X = E[k+1]; Y = -S*E[k+2];Z = Y;E[k+2] = C*E[k+2] if Zero(D, E, H):break E[0] = 1.0; H -=1 while Zero(D, E, H): H -= 1 for k in range(N-1):#以下,固有ベクトル j = k for i in range(k+1,N): if D[i] > D[j] :L = i T = D[k]; D[k] = D[j]; D[j] = T T = A[k]; A[k] = A[j]; A[j] = T return [D,transM(A)] A=[[4,2,1,3],[2,3,1,2],[1,1,2,1],[3,2,1,1]] Z=eigenHouseholder(A,0.0000000001) D=Z[0]; W=Z[1] printV(" λ =",D) printM(" W =",W) printM(" A*W =",mltM(A,W)) printM("λ*W =",mltEigenV(D,W))