EXCELSIOR

[코딩더매트릭스]Chapter02 - 필드 Field 본문

Linear Algebra/Coding the Matrix

[코딩더매트릭스]Chapter02 - 필드 Field

Excelsior-JH 2018. 2. 1. 17:34

위의 예제에서도 알 수 있듯이, 허수는 i가 아닌 j라고 쓴다. 파이썬에서의 복소수는 아래와 같은 구조로 구성되어 있다.

z == z.real + z.imag*1j

실수부(real part)는 z.real, 허수부(imaginary part)는 z.imag로 구할 수 있다.

1
2
3
4
5
6
7
8
= 1 + 3j
print('real part: {}'.format(z.real)) # 실수부
print('imaginary part: {}'.format(z.imag)) # 허수부
 
'''출력결과
real part: 1.0
imaginary part: 3.0
'''
cs


복소수에도 +, -, *, /, ** 연산자를 쓸 수 있다.

1
2
3
(1 + 3j) + (10 + 20j)  # (11+23j)
3j**2  # (-9+0j)
4*3j**2  # (-36+0j)
cs


2.3 필드의 추상화

선형대수학에서 개념, theorem, 프로시저 등이 실수뿐만 아니라 복소수와 다른 종류의 숫자에 대해서도 성립한다.

  • 개념, theorem, 프로시저를 산술 연산자 +, -, *, /에 대해 기술한다.

  • 이들 연산자는 교환법칙(), 결합법칙()와 같은 기본 법칙만을 만족한다고 가정한다.

개념, theorem, 프로시저는 이들 기본 법칙에만 의존하므로, 필드(체)의 수 체계에 적용할 수 있다.

2.4 복소수 필드 다루기

파이썬에서 복소수 는 두 개의 수 z.real(실수부) 과 z.imag(허수부)로 구성되어 있다. 이를 복소평면(complex plane) 위의 점으로 나타내면 아래의 그림과 같이 나타낼 수 있다.
복소평면
코딩더매트릭스 교재에서는 별도로 각 챕터마다 실습을 할 수 있도록 파이썬 파일들을 제공한다. 소스코드들은 http://resources.codingthematrix.com/ 에서 받을 수 있다. 아래의 예제는 plotting.py를 import 시켜 복소 평면을 구현한 예제이다.

1
2
3
4
from plotting import plot
 
= {2+2j, 3+2j, 1.75+1j, 2+1j, 2.25+1j, 2.5+1j, 2.75+1j, 3+1j, 3.25+1j}
plot(S, 8)
cs


2.4.1 복소수의 절대값

복소수 $z$의 절대값은 $\left| z \right|$로 쓰며 파이썬에서는 abs(z)로 표현한다. 
아래의 그림과 같이 복소평면의 원점에서 대응하는 점까지의 거리 를 말한다.
피타고라스 정리에 의하면, $\left| z \right|^2 = (z.real)^2 + (z.imag)^2$ 이다.복소평면

1
2
3
4
5
print(abs(3+4j))
'''출력결과
5.0
'''
cs


복소수 $z$의 켤레(공액, conjugate) 복소수는 $\bar { z } $로 쓰며, z.real - z.imag로 정의된다.
파이썬에서는 z.conugate()로 켤레복소수를 얻을 수 있다.


1
(3+4j).conjugate()
cs



$\left| z \right|^2$를 $z$와 $\bar { z }$를 이용하여 나타내면 아래와 같다.$$\left| z \right|^2 = z\cdot \bar { z }$$



2.4.2 복소수 덧셈하기

아래의 복소수 집합 $S$에, 각 복소수 $z$에 $1+2i$를 더해보자. 즉, 다음 함수를 $S$의 각 원소에 적용하여 $S_trans$라는 새로운 집합을 만든다.$$f(z)=1+2i+z$$


1
2
3
4
= {2+2j, 3+2j, 1.75+1j, 2+1j, 2.25+1j, 2.5+1j, 2.75+1j, 3+1j, 3.25+1j}
S_trans = {z+(1+2j) for z in S}
 
plot(S_trans, 8)
cs


위의 함수 $f(z)$는 실수좌표($x$축)를 $1$만큼, 허수좌표($y$축)을 $2$만큼 증가시킨다. 즉, 아래의 그림과 같이 그래프에서 오른쪽으로 1칸, 위쪽으로 2칸 이동한 것과 같다.평행이동


복소수의 평행이동을 다음과 같이 나타낼 수 있다. $z_0$은 복소수를 나타낸다.$$f(z)=z_0+z$$


평행이동


평행이동 합성하기, 화살표 더하기

$f_1(z)=z_1+z$와 $f_2(z)=z_2+z$를 합성하면,$$\begin{eqnarray} ({ f }_{ 2 }\circ { f }_{ 1 })(z) & = & { f }_{ 2 }\left( { f }_{ 1 }\left( z \right)  \right)  \\  & = & { f }_{ 2 }\left( { z }_{ 1 }+{ z } \right)  \\  & = & { z }_{ 2 }+{ z }_{ 1 }+z \end{eqnarray}$$평행이동


2.4.3 양의 실수로 복소수 곱하기

아래의 복소수 집합 $S$의 각 복소수 $z$에 $\frac{1}{2}$를 곱해보자.

$$g(z)=\frac{1}{2}z$$


1
2
3
= {2+2j, 3+2j, 1.75+1j, 2+1j, 2.25+1j, 2.5+1j, 2.75+1j, 3+1j, 3.25+1j}
S_scale = {z*(1/2for z in S}
plot(S_scale, 4)
cs


스케일링



이러한 연산을 스케일링(scaling)이라고 하며, 스케일링을 적용하게 되면 그래프의 크기 변경이 일어난다.



2.4.4 음수로 복소수 곱하기 : 180도 회전

다음은 복소수 집합 $S$의 각 복소수 $z$에 $-1$을 곱한 결과이다.


회전

1
2
3
= {2+2j, 3+2j, 1.75+1j, 2+1j, 2.25+1j, 2.5+1j, 2.75+1j, 3+1j, 3.25+1j}
S_rotation = {z*(-1for z in S}
plot(S_rotation, 4)
cs


2.4.5 $i$를 곱하기 : 90도 회전

회전

1
2
3
= {2+2j, 3+2j, 1.75+1j, 2+1j, 2.25+1j, 2.5+1j, 2.75+1j, 3+1j, 3.25+1j}
S_rotation = {z*(1j) for z in S}
plot(S_rotation, 4)
cs



Task 2.4.10 (p.54)

컴프리헨션을 사용하여 리스트 pts에 복소수 $x+yi$ 집합을 할당해 보자. 이때 픽셀$(x, y)$의 이미지 색상(RGB)는 0.5 보다 작다. 리스트를 pts 그래프로 그려보자



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from PIL import Image
import numpy as np
 
data = Image.open('./images/img01.png'# 이미지 파일 불러오기
# data = data.convert('L')
data = np.asarray(data, dtype='float32'/ 255 # 이미지 파일을 np.asarray를 이용해 배열로 만들기
data = data.tolist() # 리스트로 변환 하기
pts = [[x + y * 1j for x, pixel in enumerate(row) if pixel < 0.5for y, row in enumerate(reversed(data))]
pts1 = sum(pts, [])
plot(pts1, 2001)
 
 
y_gen = ((y, row) for y, row in enumerate(reversed(data)))
print(next(y_gen))
 
x_gen = ([(x, pixel) for x, pixel in enumerate(row) if pixel < 0.5for y, row in enumerate(reversed(data)))
print(next(x_gen))
# print(next(x_gen))
 
pts_gen = ([x + y * 1j for x, pixel in enumerate(row) if pixel < 0.5for y, row in enumerate(reversed(data)))
 
print(next(pts_gen))
cs


Task 2.4.11

파이썬 프로시저 f(z)를 작성해 보자. 이 프로시저는 리스트 pts의 점들을 원점에 중심을 둔 점들의 집합이 되게 평행이동 한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def trans2center(z_list):
    pts_center = []
    z_real = [z.real for z in z_list]
    z_imag = [z.imag for z in z_list]
    real_center = (max(z_real) - min(z_real)) / 2
    imag_center = (max(z_imag) - min(z_imag)) / 2
    for z in z_list:
        z_real = z.real - real_center
        z_imag = z.imag - imag_center
        pts_center.append(z_real+z_imag*1j)
        
    return pts_center
 
pts2 = trans2center(pts1)
plot(pts2, 2001)
cs



2.4.6 복소 평면의 단위원: 편각(argument) 과 각도

180도 또는 90도 회전을 복소수 곱에 의해 나타낼 수 있다. 뿐만 아니라 각도(angle)대신 라디안(radian)을 사용하여 다양한 회전을 표현할 수 있다.

단위원 위에 있는 복소수의 편각

단위원은 복소 평면의 원점에 중심을 둔 반지름이 1인 원이다.


원 위의 점 $z$는 원의 가장 오른쪽 점인 $1+0i$에서 시작하여 $z$에 도착할 때까지 원을 따라 반시계 방향으로 이동하는 거리로 표현할 수 있다. 이러한 거리를 $z$의 편각(argument)이라고 한다.


파이썬에서 편각(argument)은 cmath.phase()함수를 이용해 구할 수 있다.

1
2
3
import cmath
 
cmath.phase(-1+0j) # pi
cs



2.4.7 오일러 공식 - Euler's formula

오일러의 공식은 수학자 레온하르트 오일러의 이름이 붙은 공식으로, 복소수 지수를 정의하는 데에 출발점이 되며, 삼각함수와 지수함수에 대한 관계를 나타낸다.
임의의 실수 $\theta$에 대해, $e^{i\theta}$는 편각이 $\theta$인 단위원 위의 점 $z$를 의미한다.

$$e^{ix}=\cos { x } +i\sin{x} $$



$x$가 $\pi$일 경우 $e^{i\pi}+1 = 0$이라는 오일러 등식을 구할 수 있다.

2.4.8 복소수에 대한 극좌표 표현

오일러 공식은 단위원 위에 있는 복소수를 쉽게 표현할 수 있는 방법을 제시한다. 
임의의 복소수 $z$를 고려해보자. $L$을 원점에서 $z$까지의 복소평면 위에 있는 선분이라 하고, $z'$은 이 선분이 단위원과 교차하는 점이라고 하자.

$r$은 $z$까지의 선분의 길이라고 하면, $z'$는 $z$를 축소한것 이라고 보면, 다음과 같이 쓸 수 있다.$$z'=\frac{1}{r}z$$

$\theta$를 $z'$의 편각이라 하면, 오일러 공식에 의해 $z'=e^{\theta i}$ 가 된다. 따라서 다음과 같이 쓸 수 있다.$$z=re^{\theta i}$$

여기서, $r$과 $\theta$는 $z$의 극좌표(polar coordinates)이다.

파이썬에서 극좌표(polar coordinates)는 cmath.polar()를 이용해 구할 수 있다. return 값은 $r$(절대값$\left| z \right|$, abs) 과 $\theta$(편각, argument)이다.

1
2
3
4
5
# 1+1i 의 극좌표 구하기
cmath.polar(1+1j)
 
# 극좌표를 이용해 복소수 구하기
cmath.rect(1.41421356237309510.7853981633974483)
cs




2.4.9 첫 번째 지수 법칙

지수에 대한 곱은 그 지수들을 더하면 된다.$$e^ue^v=e^{u+v}$$

2.4.10 $\tau$ 라디안 회전

1 라디안(radian)은 원둘레 위에서 반지름의 길이와 같은 길이를 갖는 호에 대응하는 중심각의 크기이다.

$\tau$를 라디안(radian) 값이라 하고, $z$를 $\tau$만큼 회전한 것은 $z$와 절대값($\left| z \right|$)은 같고 편각(argument)은 $z$보다 $\tau$만큼 더 커야 한다. 즉, $\tau$ 만큼 회전한 $z$는 $re^{(\theta + \tau)i}$ 이다. 이 값을 $z$로 부터 구해보면 아래의 식과 같다.$$ r{ e }^{ (\theta +\tau )i }=r{ e }^{ \theta i }{ e }^{ \tau i }=z{ e }^{ \tau i }$$

따라서, $\tau$ 만큼 회전한 것을 나타내는 함수는 다음과 같이 쓸 수 있다.$$f\left( z \right) =z{ e }^{ \tau i }$$

Task 2.4.18 (p.58)

S의 원소들을 $\frac{\pi}{4}$만큼 회전한 것으로 이루어진 집합을 반환하는 컴프리헨션을 작성해 보자.

1
2
3
4
= {2+2j, 3+2j, 1.75+1j, 2+1j, 2.25+1j, 2.5+1j, 2.75+1j, 3+1j, 3.25+1j}
euler = cmath.exp(cmath.pi / 4 * 1j)
S_rad = {z * euler for z in S}
plot(S_rad, 4)
cs


Task 2.4.19 (p.58)

Task 2.4.10 에서의 리스트 pts의 복소수들을 $\frac{\pi}{4}$만큼 회전한 것을 그래프로 그려보자



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
data = Image.open('./images/img01.png'# 이미지 파일 불러오기
# data = data.convert('L')
data = np.asarray(data, dtype='float32'/ 255 # 이미지 파일을 np.asarray를 이용해 배열로 만들기
data = data.tolist() # 리스트로 변환 하기
 
# 라디안 회전을 적용하는 함수 정의
def rad_rotation(z_list):
    euler = cmath.exp(cmath.pi / 4 * 1j)
    z_rad = [z * euler for z in z_list]
    return z_rad
 
 
pts = [[x + y * 1j for x, pixel in enumerate(row) if pixel < 0.5for y, row in enumerate(reversed(data))]
pts_org = sum(pts, [])
pts_rad = rad_rotation(pts_org)
plot(pts_rad, 2001)

cs



2.4.11 연산 결합하기

Task 2.4.20 (p.59)

집합 pts를 변환하는 컴프리헨션을 작성해 보자. 이변환은 이미지가 중심에 위치하도록 평행이동하고, $\frac{\pi}{4}$ 만큼 회전하며, 그다음에 $\frac{1}{2}$만큼 스케일링한다.


1
2
3
4
5
6
7
8
9
def scaling(z_list):
    z_scaled = [z * 0.5 for z in z_list]
    return z_scaled
 
 
pts_trans = trans2center(pts_org) # 이미지를 중심으로 평행이동
pts_rad = rad_rotation(pts_trans) # 이미지를 pi/4 만큼 회전
pts_scaled = scaling(pts_rad) # 이미지를 스케일링
plot(pts_scaled, 2001)
cs



2.5 $GF(2)$ 에 대해 알아보기

갈루아 필드(Galois Field)는 유한체(Finite Field)라고도 하며 유한개의 원소를 갖는 대수 체계를 갖춘 체(Field)이다. 즉, 유한체 집합 내 원소의 연산(덧셈, 곱셈) 결과가 다시 그 집합 내에 있게된다. 
실수필드 $R$, 복소수 필드$C$ 등은 그 요소 수가 무한 개인 체(field) 지만, 갈루아 필드는 유한체이므로 요소 수가 유한개 이다. 
그 중 $GF(2)$는 $0$과 $1$ 두 개의 원소를 갖는 갈루아 필드이다. $GF(2)$에서 연산은 아래와 같이 나타 낼 수 있다.


Comments