#!/usr/bin/env python # coding: utf-8 #
# 線形代数(Linear algebra) #
#
# cc by Shigeto R. Nishitani, 2017-10-31 #
# * file: /Users/bob/python/doing_math_with_python/linear_algebra.ipynb #

Table of Contents

#
# # sympy # # * [sympy tutorial](http://docs.sympy.org/latest/tutorial/index.html) # * [module references](http://docs.sympy.org/latest/modules/matrices/matrices.html) LUdecompositionの記述あり. # # 行列,ベクトルの生成 # ## 直接的に # In[1]: from sympy import * #init_session() #init_printing(use_unicode=True) init_printing() list_a = [1,2] list_b = [3,4] A=Matrix([list_a, list_b]) A # In[2]: x,y = symbols('x,y') v1=Matrix([x,y]) v1 # ## ゼロ行列,単位行列 # In[3]: zeros(2,3) # In[4]: ones(2,3) # In[5]: eye(3) # In[6]: diag(1,2,3) # ## 行列要素のとりだし,追加 # In[7]: A=Matrix([[1,2,3],[4,5,6],[7,8,9]]) # i行j列の要素の取り出し A[1,1] # In[8]: A[:2,1:4] # In[9]: col_0 = A[:,0] col_0 # In[10]: row_1 = A[1,:] row_1 # numpyではcolumn_stackを使って拡大係数行列を作った. # sympyではrow_insert, col_insertを使う. # In[11]: b = Matrix([1,2,3]) A.row_insert(3,b.T) # In[12]: A.col_insert(3,b) # # 行列・ベクトル間の単純な演算 # ## 次元の確認 # In[13]: A.shape # In[14]: print(v1.shape) print(v1.T.shape) # ## 転置(transpose) # In[15]: A.T # In[16]: v1.T # ## ドット積(内積) # numpyと違ってdot関数を使うと怒られる. # # "\*" を使います. # In[17]: A = Matrix([[1,2],[3,4]]) A*v1 # In[18]: v1.T*v1 #v1*v1ではerror # In[19]: v1.T*A # In[20]: v1.T*v1 # In[21]: v1*v1.T # ## 外積,outer, cross # # outer(v1,v2)がSympy1.1.1では見つからない. # crossは使える. # In[22]: v1 = Matrix([1,1,3]) v2 = Matrix([1,2,-1]) # In[23]: v1.outer(v2) # In[24]: v1.cross(v2) # ## スカラー三重積 # In[25]: v3 = Matrix([-1,2,1]) v3.dot(v1.cross(v2)) # # 行列操作 # ## 掃き出し, LU分解 # In[26]: A=Matrix([[1,2,3],[4,5,6],[5,7,9]]) print(A.nullspace()) Aex = A.col_insert(3,b) pprint(Aex) Aex.rref() # rrefはreduced row echelon formを取り出してくれる.これはGaussの消去法で下んとこまで行って,さらに上んとこへ戻ってきたやつ.拡張行列もそのままやってくれるはず.もうすこし,試す必要があるが,一応MapleのLUDecompositionに近い結果を与えてくれる. # In[27]: A=Matrix([[1,2,3],[4,5,6],[7,9,8]]) L, U, P = A.LUdecomposition() L, U, P # ## 階数, rank # In[28]: print(A) print(A.rank()) # ## 行列式, determinant # In[29]: c = Matrix([[1,1],[1,2]]) print(c.det()) a = Matrix([[1,2],[3,4]]) a.det() # ### 課題 # 次の行列式の計算を確認せよ. # $$ # \left| # \begin {array}{cccc} # 1+a & 1 & 1 & 1\\ # 1 & 1+b & 1 & 1\\ # 1 & 1 & 1+c & 1\\ # 1 & 1 & 1 & 1+d # \end {array} \right| # = abcd \left(1+\sum_{i=a}^d \frac{1}{i}\right) # $$ # # In[30]: from sympy import * a,b,c,d,x,y,z = symbols('a b c d x y z') A = Matrix([[1+a,1,1,1],[1,1+b,1,1],[1,1,1+c,1],[1,1,1,1+d]] ) pprint(A) simplify(A.det()) # ## 逆行列 # In[31]: A = Matrix([[1,2],[3,4]]) A.inv() # ### 課題 # 次の連立方程式を解け. # $$ # \left\{ # \begin {array}{cl} # x+y+z&=0\\ # ax+by+cz&=0\\ # bcx+cay+abz&=(a-b)(b-c)(c-a) # \end {array} \right. # $$ # In[32]: from pprint import pprint from sympy import * a,b,c,x,y,z = symbols('a b c x y z') A = Matrix([[1,1,1],[a,b,c],[b*c,c*a,a*b]]) bb = Matrix([0,0,(a-b)*(b-c)*(c-a)]) print(A) print(bb) Ainv = A.inv() res = Ainv * bb pprint(simplify(res[0])) pprint(simplify(res[1])) pprint(simplify(res[2])) # # 固有値,固有ベクトル # # sympyでは固有値・固有ベクトルは,eigenvects()で求められます. # 戻り値は, # > [(固有値, 重複度, [固有ベクトル]), ...] # # です. # In[33]: A = Matrix([[1,2],[2,1]]) A.eigenvects() # ## ベクトルの規格化 # # eigenvectsの固有ベクトルは規格化されていません.norm()を使うとかんたんに規格化してくれます. # In[34]: v1=Matrix(A.eigenvects()[0][2]) v2=Matrix(A.eigenvects()[1][2]) simplify(v1.T*v1) # In[35]: v_norm = v1.norm() v_norm # In[36]: v1n = v1/v_norm v1n # ## 対角化 # # ちょいとわかりやすい行列を作成してみてみます. # In[37]: D = diag(1,2) P = Matrix([[1,0],[1,1]]).T A = P*D*P.inv() A, P, D # In[38]: P,D = A.diagonalize() P.inv()*A*P # In[39]: eigs = A.eigenvects() v1 = eigs[0][-1][0] v2 = eigs[1][-1][0] Matrix([v1,v2]).reshape(2,2).T # 対角化行列$P$をeigenvectsから作ろうとして苦労した.まず,固有ベクトルの取り出しが自動的にできない.重複しているときには,固有ベクトルは二つ出てくる.さらに,タプルからの取り出しがこれでいいいのか...さらに,ベクトルから行列を作るときに横置きのができない.うううんん.他のやり方をしたでやってみる.上では仕方がないので,一旦4x1のMatrixにしてそのあとreshape,さらにTransposeで... # In[40]: v1.col_insert(1,v2) # numpyにはravel()というフラット化の関数があるがsympyにはない. # # 結論:3つほど上でやっているdiagonalizeで取り出しましょう.重複があっても取り出してくれるんで. # ### 課題 # 行列 # $$ # A\, := \, \left[ # \begin {array}{ccc} # 2&0&1\\ # 0&3&0\\ # 1&0&2 # \end {array} \right] # $$ # # を対角化する変換行列$P$を求め,対角化せよ. # In[41]: A = Matrix([[2,0,1],[0,3,0],[1,0,2]]) evs = A.eigenvects() evs # # In[42]: P,D = A.diagonalize() P,D # In[43]: P.inv()*A*P # In[ ]: # In[ ]: