
행렬 덧셈이 정의되려면 두 행렬의 크기가 같아야 한다.
A = matrix([[1, 2, -4], [-2, 1, 3]])
B = matrix([[0, 1, 4], [-1, 3, 1]])
C = matrix([[1,1], [2, 2]])
print( "A + B = " )
print( A + B )
print()
print( "2*A =" )
print( 2*A )
print()
print( "(-1)*C =" )
print( (-1)*C )
A + B =
[ 1 3 0]
[-3 4 4]
2*A =
[ 2 4 -8]
[-4 2 6]
(-1)*C =
[-1 -1]
[-2 -2]
행렬곱은 벡터 변환을 올바르게 합성하기 위해 만들어진 연산
그렇기 때문에 행과 열을 곱한다.


A = matrix([[1, 2, -1], [3, 1, 0]])
B = matrix([[-2, 1], [0, -3], [2, 1]])
print(A*B)
[-4 -6]
[-6 0]

성분이 모두 0인 행렬
matrix(행 개수, 열 개수, 값)
matrix(nrows, ncols, data)
세번째 인자를 0으로 지정하면 영행렬이 된다.
diagonal matrix
단위행렬은 1과 같은 역할을 하는 행렬로 주대각성분이 모두 1이고 나머지 성분은 모두 0인 n차의 정사각행렬이다.


scalar matrix

A가 n차의 정사각행렬일 때 A의 거듭제곱은:

행과 열을 바꾸는 것

A = matrix([[1, -2, 3], [4, 5, 0]])
B = matrix([[1, 2, -4], [3, -1, 2], [0, 5, 3]])
C = matrix([[5, 4], [-3, 2], [2, 1]])
D = matrix([[3, 0, 1]])
print("A^T =")
print(A.transpose()) # 행렬의 전치행렬
print("B^T =")
print(B.transpose())
Share
A^T =
[ 1 4]
[-2 5]
[ 3 0]
B^T =
[ 1 3 0]
[ 2 -1 5]
[-4 2 3]
A = random_matrix(ZZ, 7, 12) # 임의의 7x12 정수(ZZ) 행렬 A를 생성!
print( "A =" )
print( A )
print()
print("A^T=" )
print( A.transpose() ) # 생성한 행렬 A의 전치행렬 A.transpose() 구하기
Share
A =
[ -1 -2 1 1 -33 -2 -1 3 -1 0 0 1]
[ -4 1 -1 2 2 -2 -1 1 1 -1 8 -1]
[ 0 1 -1 -1 -2 -1 -1 -1 -2 -3 -1 -7]
[ -1 -1 2 0 5 4 1 1 1 1 -1 -6]
[ -2 1 -3 1 1 -5 -24 -1 1 -1 -1 3]
[-15 -15 -3 -5 -1 0 -1 -1 -1 0 -3 1]
[ 2 -1 0 -3 -1 0 0 0 -2 1 0 -45]
A^T=
[ -1 -4 0 -1 -2 -15 2]
[ -2 1 1 -1 1 -15 -1]
[ 1 -1 -1 2 -3 -3 0]
[ 1 2 -1 0 1 -5 -3]
[-33 2 -2 5 1 -1 -1]
[ -2 -2 -1 4 -5 0 0]
[ -1 -1 -1 1 -24 -1 0]
[ 3 1 -1 1 -1 -1 0]
[ -1 1 -2 1 1 -1 -2]
[ 0 -1 -3 1 -1 0 1]
[ 0 8 -1 -1 -1 -3 0]
[ 1 -1 -7 -6 3 1 -45]
import numpy as np
A = np.random.randint(5, size=(5, 7)) # 임의의 0~4 사이의 수만으로 이루어진 5x7 자연수 행렬
print( "A=")
print(A)
print( "A^T=")
print(A.transpose())
Share
A=
[[4 3 0 0 3 2 2]
[0 2 3 1 2 0 1]
[1 1 2 0 1 3 2]
[4 4 4 0 0 3 0]
[2 2 4 3 1 1 2]]
A^T=
[[4 0 1 4 2]
[3 2 1 4 2]
[0 3 2 4 4]
[0 1 0 0 3]
[3 2 1 0 1]
[2 0 3 3 1]
[2 1 2 0 2]]

n차의 정사각행렬 A에 대하여 다음을 만족하는 행렬 B가 존재하면 A는 가역(invertible, nonsingular) 라고 한다.

이 때 B를 A의 역행렬(inverse matrix)라고 하며, 이러한 B가 존재하지 않으면 A는 비가역(noninvertible, singular) 라고 한다.
A = matrix([[1, 4, 3], [2, 5, 6], [0, 0, 0]])
A.is_invertible() #행렬이 가역인지 확인
False

A = matrix(2, 2, [3, 5, 1, 2])
print("A=")
print(A)
print()
print("A.inverse()=")
A.inverse()
A=
[3 5]
[1 2]
A.inverse()=
[ 2 -5]
[-1 3]


위의 경우를 차례로...
# 주의!! Sage의 index는 0부터 시작한다.
# elementary_matrix(n, row1=i, row2=j): i행과 j행을 교환
E1 = elementary_matrix(4, row1=1, row2=2) # 기본행렬 r2 ↔ r3
# elementary_matrix(n, row1=i, scale=m): i행에 m을 곱한다.
E2 = elementary_matrix(4, row1=2, scale=-3) # 기본행렬 (-3)*r3
# elementary_matrix(n, row1=i, row2=j, scale=m): j행에 m을 곱하여 i행에 더함
E3 = elementary_matrix(4, row1=0, row2=3, scale=7) # 기본행렬 7*r4 + r1
print ( "E1 =" )
print ( E1 )
print ()
print ( "E2 =" )
print ( E2 )
print ()
print ( "E3 =" )
print ( E3 )
E1 =
[1 0 0 0]
[0 0 1 0]
[0 1 0 0]
[0 0 0 1]
E2 =
[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 -3 0]
[ 0 0 0 1]
E3 =
[1 0 0 7]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]

역행렬 구하기의 예)






A = matrix(3, 3, [1, 2, 3, 2, 5, 3, 1, 0, 8])
b = vector([1, 3, -1])
print( "x=", A.inverse()*b) # 역행렬을 이용한 연립방정식의 해 구하기
print()
print( "x=", A.solve_right(b) ) # .solve_right()을 이용하여 구할 수도 있다.
Share
x= (-1, 1, 0)
x= (-1, 1, 0)
H = diagonal_matrix([-3, -2, 1]) # 대각선행렬
K = identity_matrix(3) #단위행렬
J = matrix(2, 2, 0) # 영행렬
print( "H =")
print( H )
print()
print( "K=")
print( K )
print()
print( "J=")
print( J )
print()
Share
H =
[-3 0 0]
[ 0 -2 0]
[ 0 0 1]
K=
[1 0 0]
[0 1 0]
[0 0 1]
J=
[0 0]
[0 0]

A = matrix([[1,2,3], [2,4,5], [3,5,6]])
B = matrix([[0,1,-2], [-1,0,3], [2,-3,0]])
print( bool(A == A.transpose()) ) # A가 대칭인지 확인
print( bool(B == -B.transpose()) ) # B가 반대칭인지 확인
True
True
LU 분해(factorization)는 어떤 행렬 A를 두 행렬의 곱으로 나누는 것
정사각행렬 A의 REF는 상삼각행렬 U라 할 때, U는 A에 기본행렬들을 곱함으로써 (가우스 소거법, 기본행렬들을 필요에 따라 곱하여 소거함으로써) 얻어진다.

Ei 들은 치환행렬 또는 하삼각행렬이다. 하삼각행렬의 역행렬도 하삼각행렬이다. 따라서 치환행렬이 필요한 경우를 별도로 미리 처리하면, 일반성을 잃지 않고 A를 하삼각행렬 L과 상삼각행렬 U의 곱 A=LU로 쓸 수 있다.
-> Ei는 기본행렬들로 가우스 소거에서 사용하는 기본행렬은 두 종류이다. - 치환행렬, R1 <-> R2, 그리고 하삼각행렬 R2 -> R2 - 3R1. 하삼각행렬의 역행렬이 하삼각행렬인 것은 하삼각행렬의 특징이고, 치환행렬(R1 <-> R2)이 필요한 경우에는 미리 처리한 것으로 치면; 그렇다 할지라도 LU분해의 성질을 해하지 않으므로, A=LU라고 할 수 있다.

A=LU
L: 하삼각행렬 (Lower triangular matrix)
U: 상삼각행렬 (Upper triangular matrix) - U는 가우스 소거법의 결과로 만들어지는 행렬
가우스 소거에 사용되는 기본행렬은 대부분 하삼각행렬이고, 그 역행렬도 하삼각행렬이므로 행 교환만 따로 처리하면 어떤 행렬 A도 A=LU 로 표현할 수 있다.





자연수의 집합 S = {1, 2, ..., n}의 치환(permutation, 순열)이란 S에서 S로의 일대일 대응 함수이다. (모든 원소를 한 번씩만 다른 위치로 재배치하는 것, 순서를 바꾸는 함수)
지환에서 반전(inversion)이란 큰 자연수가 작은 자연수보다 더 왼쪽에 먼저 나타나는 경우를 말함. 예) (1, 4, 2, 3)
치환이 가진 반전의 총 개수가 짝수-> 짝치환(even permutation)
홀수면 -> 홀치환(odd permutation)

print( Permutation([5, 1, 2, 4, 3]).inversions() ) #반전이 일어난 부분 찾기
print( Permutation([5, 1, 2, 4, 3]).number_of_inversions() ) #반전의 개수 구하기
print( Permutation([5, 1, 2, 4, 3]).is_even() ) # 짝치환인지 확인
[(1, 2), (1, 3), (1, 4), (1, 5), (4, 5)]
5
False

예) 
행렬식 det(A) = 1⋅4 − 2⋅3 = −2
det(A)는 행렬 A가 "다른 벡터나 공간에 어떤 변형을 가하는지"를 측정하는 값이다.
행렬 A가 다른 벡터에 곱해졌을 때,
det(A)는 이 공간 변화율
(1) 행이 같으면 0
det(A) = 0
두 행이 같으면 공간이 찢어지지 않기 때문에
2차원 -> 선
3차원 -> 평면
0이 아니면? 선형독립
(2) 행을 바꾸면 부호가 바뀜
(3) 각 행에 대해 선형(linear)
det(A)는 행렬 내부 값들로 계산됨


결국 det(A)는 열벡터들이 만드는 공간의 부피이다.
혹은 선형변환의 부피 변화율 이다.
-> A의 열벡터들이 만드는 평행다각형(또는 평행육면체)의 부피
B = matrix([[1, 2, 3], [-4, 5, 6], [7, -8, 9]])
print( B.det() ) # 행렬식 구하기
240

A = random_matrix(QQ, 3, 3) # QQ - 유리수집합
B = random_matrix(QQ, 3, 3)
AB = A*B
print( "|AB| = |A||B| ?", AB.det() == A.det()*B.det() )
print( "|A| =", A.det())
if A.det() != 0:
print("Is A invertible ?", A.is_invertible() )
print("|A^-1| = |A|^-1 ?", 1/A.det() == A.inverse().det() )
else:
print( "Is A invertible ?", A.is_invertible() )
|AB| = |A||B| ? True
|A| = 12
Is A invertible ? True
|A^-1| = |A|^-1 ? True
랜덤 행렬이라 det(A)의 값은 계속 변함