레이블이 sympy인 게시물을 표시합니다. 모든 게시물 표시
레이블이 sympy인 게시물을 표시합니다. 모든 게시물 표시

2015년 6월 22일 월요일

winPython 에서 ipython 의 sympy 설정

 파이썬에서 심볼릭 (symbolic) 수학을 지원하는 sympy 라는 모듈이 있다. winPython을 사용한다면 기본적으로 설치되어 있으므로 사용하고 싶다면

>>> import sympy as sp
라고 하면 된다. 흥미로운 것은 수학 계산식을 LaTex 스타일로 깔끔하게 표시할 수 있다. 이를 위해서는 다음과 같은 이 모듈 내의 함수를 호출하면 된다.
>>> sp.init_printing() # 수식을 LaTex 스타일로 표시한다.

만약 배경색을 검은 색으로 사용하고 있다면 다음과 같이 글자색을 흰색으로 지정해 줄 수 있다.

>>> sp.init_printing(forecolor='White')
이 함수를 맨 처음 실행시킬 때는 별도의 패키지를 인스톨하라는 대화창이 뜨며 한 번만 인스톨해주면 된다. 이렇게 하면 이후에 수학식이 LaTex 스타일로 굉장히 깔끔하게 표시된다. 예를 들면 아래와 같다.

유니코드를 사용하여 수식을 표시하는 함수로 pprint()가 있다. 만약 아스키코드로만 표시하고 싶다면 use_unicode = False 옵션을 주면 된다.

>>> expr = sp.sqrt(x/(x**2+1))+sp.pi
>>> sp.pprint(expr) # 유니코드를 이용하여 수식 표시
         ________    
       ╱   x        
     ╱  ──────  + π
   ╱    2         
╲╱    x  + 1     
>>> sp.pprint(expr,use_unicode=False) #아스키코드로 수식 표시
    ________     
   /   x         
  /  ------  + pi
 /    2          
\/    x  + 1      

 그런데 sympy 에는 init_session() 이라는 함수가 있는데 이 함수의 옵션으로 ipython=True 를 주면 sympy 모듈이 전역 공간으로 임포트되며 LaTeX 모드가 활성화된다.
init_session()함수를 호출하면 내부에서 from sympy import * 가 수행되므로 이 모듈의 모든 함수/변수가 전역 공간에 올라온다. 따라서 이후에는 ipython 콘솔을 sympy 위주의 쉘로 활용할 수 있다.
다른 방법으로 위와 같이 명령어로 입력하지 않고 설정창에서 지정해 줄 수 있다.

만약 sympy 위주로 쉘을 사용하고 싶다면 이 옵션을 지정해 주는 것도 좋을 것이다.
하지만 sympy 도 다른 모듈들(numpy 등)과 구분하여 사용하고 싶다면 맨 처음에 소개한 명령어를 사용하는 것이 좋다.
>>> import sympy as sp
>>> sp.init_printing() # LaTex 스타일로 수식 표시
 ipython의 매직 명령어인 %matplotlib inline 이라고 하면 ipython 창에 그래프를 그려준다.

>>> %matplotlib [gui]

여기서 [gui] 옵션으로 inline, gtk4, qt4 등을 줄 수 있으며 inline 을 주면 ipython 창 내부에 그래프를 도시해 준다. 이후에 예를 들어 sympy.plot() 함수 등을 사용하면 ipython 내부 창에 그래프를 띄워준다.
 만약 초기에 이러한 설정으로 시작하고 싶다면 옵션으로 지정하여 ipython 창이 생성될 때 자동으로 설정되도록 할 수 있다. 아래 그림과 같이 Support for graphics (Matplotlib) 항목 내의 Active support 를 체크하면 ipython 이 시작될 때 그래프 기능을 활성화시킨다.
단 이 옵션은 자동으로 numpy 와 matplotlib.pyplot 모듈을 np, plt 이름으로 임포트시킨다. 이것은 dir() 명령으로 확인할 수 있다.

 두 번째 항목인 automatically load pylab 은 비활성화시키기를 권장한다. pylab 은 내부에서 numpy와 matplotlib.pyplot 등의 모듈들을 전역공간으로 임포트하여 함수들을 관리하는데 혼동을 주기 때문이다.


2015년 5월 8일 금요일

심파이(sympy)를 이용한 미분방정식 풀이

 만약 x, y가 심볼로 등록이 되어 있다면 함수 y(x)의 x에 대한 미분은 sympy에서 다음과 같이 표현할 수 있다.

  • y(x) : 독립 변수 x에 대한 함수 y
  • y(x).diff() 혹은 y(x).diff(x,1) : 1차 미분
  • y(x).diff(x,2) : 2차 미분
  • y(x).diff(x,3) : 3차 미분

이것을 이용하면 상미분식을 표현할 수 있다. 예를 들면 다음과 같다.

[표 1] 미분식의 심파이 표현식 예
수식
심파이 표현식
y(x).diff() - cos(x)
y(x).diff(x,2) + 9*y(x) - exp(-2*x)
y(x).diff()-1-y(x)**2

함수를 표현할 때 y(x)와 같이 독립변수도 반드시 표기해야 함을 유의하자.

 dsolve()함수는 미분방정식을 풀어주는 sympy의 기본 함수이다. 첫 번째 인자로 미분식을, 두 번째 인자로 구할 함수를 적어주면 된다. 예를 들어서 다음과 같은 1차 상미방을 푼다고 가정하자.


이 미분방정식의 우변을 0으로 만들면 다음과 같다.


이제 dsolve 함수의 첫 번째 인자로 위 식의 좌변을 넣어주고 두 번째 인자로 y(x)를 인가하면 된다.


여기서 C1은 상수이다.  다른 미분 방정식을 풀어보자.


이 방정식도 우변을 먼저 0으로 만들어야 한다.


이제 이 식의 좌변을 dsolve()함수의 첫 번째 인자로 넣어준다.


2차 미분방정식도 입력할 수 있다. 예를 들어


을 풀려면 다음과 같이 하면 된다.


만약 함수의 미분표현식을 매번 입력하기 번거롭다면 다음과 같이 새로 정의하여 사용하면 된다.


이렇게 정의해 놓으면 이후부터는 y(x).diff() 대신 dy를, y(x).diff(x,2) 와 같이 긴 표현식 대신 ddy를 사용하면된다.


여기서 C1과 C2는 상수이다. 이것이 dsolve()함수를 이용한 미분방정식을 푸는 가장 기본적인 방법이다.

심파이(sympy) 실행 환경

 심파이를 가장 간단하게 실행해 볼 수 있는 방법은 live.sympy.org 에 접속하는 것이다. 이 페이지에 접속하면 심파이의 최신 버전이 임포트된 파이썬 쉘을 사용할 수 있다.

[그림 1] live.sympy.org의 접속 화면

맨 처음 접속했을 때 상단에 보면 다음과 같이 미리 실행되는 명령들이 있다.

These commands were executed:
>>> from __future__ import division
>>> from sympy import *  
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)

 미리 실행되는 이  명령들에 의해서 심파이 모듈이 글로벌 환경에 임포트되어 있고 또한  변수 x, y, z, t 는 심파이의 대수 기호로 사용할 수 있다. 그리고 k, m, n은 정수 대수 기호 그리고 f, g, h 는 함수 기호로 바로 사용할 수 있다.

 만약 윈도를 사용하고 있고 로컬PC에서 심파이를 실행하고 싶다면 winpython을 사용하면 된다. 이 패키지는 파이썬과 필요한 모듈들이 대부분 포함되어 있으며 설치방식이 아니라 단순히 압축을 푼 후 실행하는 방식 (포터블)이라 사용하기 용이하다. 파이썬 2.x버전, 3.x 버전 각각 별도로 그리고 윈도 32bit, 64bit 버전별로 배포본이 마련되어 있다. 자기 환경에 맞는 것을 선택하여 다운로드하면 된다.

필자는 winpython 3.4.3.2 버전을 다운로드 받아서 실행하였다. 그러면 그 실행 파일의 하위 폴더에 다음과 같은 파일들이 생성되어 있다. 그 후 Spyder.exe를 실행하면 된다.

[그림 2] winpython의 설치 폴더

Spyder 가 실행된 후 Tools>Preferences 메뉴에서 다음 그림과 같은 항목을 체크한 후 ipython쉘을 실행시키면 바로 sympy를 사용할 수 있다.
[그림 3] winpython에서 sympy를 기본으로 실행시키기

이제는 로컬PC에서 ipython과 sympy를 사용할 수 있다.
[그림 4] winpython에서 ipython console을 실행시킨 화면

2015년 4월 30일 목요일

sympy 선형대수 4 : 선형 대수 연산

 심파이에서 행렬객체에 수행할 수 있는 선형대수 관련 연산을 다음 표에 정리하엿다.

[표 1] 선형대수 연산
연산
기능
A.T
A.H
A.D
전치행렬(transposition)
복소전치행렬(hermite conjugation)
Dirac transposition
A.rank()
행렬의 랭크(rank)
A.det()
행렬식 (determinant)
A.inv()
역행렬 (inverse matrix)
A.LUsolve(b)
행렬방정식 Ax=b 를 푼다.
A.norm()
norm을 구한다.
A.eigenvals(**flags)
A.eigenvecs(**flag)
행렬의 고유값을 구한다.
행렬의 고유값과 고유벡터를 구한다.
A.evalf()
행렬 각 요소의 실수 근사값을 구한다.
A.applyfunc(f)
행렬 각 요소에 함수 f를 적용한다.

숫자로만 이루어진 행렬뿐만 아니라 대수 기호가 포함된 행렬에 대한 연산도 수행 가능하다.

>>> x=symbols('x') # x 를 기호로 설정
>>> C=Matrix([[x,2],[1,x]])
>>> D=ones(2)*x

>>> C
[x  2]
[1  x]

>>> D
[x  x]
[x  x]

>>> C.det()
2    
x  - 2

>>> C*D
[  2             2   ]
[x  + 2*x  x  + 2*x  ]
[   2           2    ]
[ x  + x    x  + x   ]

만약 대수 기호 대신에 숫자를 입력하고 싶다면 subs() 메쏘드를 이용한다.

>>> C.subs(x,11)
[11  2 ]
[1   11]

>>> y=symbols('y')

>>> D.subs(x,y**2+1)
[ 2       2    ]
[y  + 1  y  + 1]
[ 2       2    ]
[y  + 1  y  + 1]

>>> D.subs(x,sqrt(y))
[  ___    ___     ]
[\/ y     \/ y    ]
[  ___    ___     ]
[\/ y     \/ y    ]


sympy 선형대수 3 : 행렬의 기본 연산

 행렬 간 산술 연산은 +, -, *, ** 연산자로 수행할 수 있다. *은 행렬 간 곱셈을, **은 거듭제곱을 수행한다.

[표 1] 행렬의 기본 연산
연산
기능
A+B, A-B
행렬간 덧셈, 뺄셈
A*B
행렬간 곱셈 (A의 열 수와 B의 행 수가 같아야 한다.0
A**k
행렬 A의 k 거듭 제곱
v1.dot(v2)
벡터 v1과 v2의 내적(dot product)

덧셈과 곱셈은 두 행렬의 크기가 같아야 하고 행렬 간 곱셈은 차수 조건에 맞아야 한다. 즉, 첫 번째 행렬의 열 수와 두 번재 행렬의 행 수가 같아야 곱셈이 성립한다.

>>> A=randMatrix(3,4)
>>> B=randMatrix(4,2)

>>> A
[2   48  28  60]
[2   9   18  88]
[79  14  17  25]

>>> B
[10  49]
[47  95]
[18  67]
[60  59]

>>> A*B   
[6380  10074]
[6047  7351 ]
[3254  7815 ]

>>> B*A # 오류발생

 파이썬에서 **가 거듭제곱 연산자이므로 심파이에서도 행렬의 거듭제곱은 ** 연산자로 수행한다. 거듭제곱을 수행하려면 행렬이 정방행렬이어야 한다.

>>>  A=Matrix([[1,2],[2,3]])
⎡1  2⎤
⎣2  3⎦

>>> A**10
⎡514229  832040 ⎤
⎣832040  1346269⎦

sympy 선형대수 2 : 행렬의 indexing, slicing

  행렬 객체에 대해서 파이썬 인덱싱과 슬라이싱도 사용할 수 있다. 주의할 점은 수학의 행렬은 1행, 1열부터 시작하지만 Matrix객체는 인덱스가 0으로 부터 시작한다는 점이다. 따라서 첫 번째 행(열)의 인덱스는 0이고 두 번째 행(열)의 인덱스는 1이다.

>>> M = Matrix(2, 3, [1,2,3,4,5,6])
>>> M
[1 2 3]
[4 5 6]

>>> M[4] # 5
>>> M[1,2] # 6
>>> M[0,0] # 1
>>> M[1,1] # 5

>>> M[0:2, 0:2] # 2x2 부분 행렬
>>> M[1:2, 2]
>>> M[:,2] # 3열 전체

특정한 행이나 열을 뽑아내고 싶다면 row(n), col(n) 멤버 함수를 이용한다.

>>> M.row(0)
>>> M.col(2)
>>> M.row(-1) # 마지막 행을 뽑아낸다.

행렬 M의 복사본을 생성하고 싶다면 다음과 같이 하면 된다.

>>> M2 = M[:,:]
>>> M2[0,0]=100
>>> M

이와 같이 M2를 변경해도 M에는 영향을 미치지 않는다.

>>> M = Matrix(4,4,range(1,17))
⎡1   2   3   4 ⎤
⎢5   6   7   8 ⎥
⎢9   10  11  12⎥
⎣13  14  15  16⎦

>>> M[2,2] = M[0,3] = 0
>>> M
⎡1   2   3   0 ⎤
⎢5   6   7   8 ⎥
⎢9   10  0   12⎥
⎣13  14  15  16⎦

>>> M[2:, 2:] = zeros(2,2)
>>> M
⎡1   2   3  4⎤
⎢5   6   7  8⎥
⎢9   10  0  0⎥
⎣13  14  0  0⎦

행렬의 특정 행이나 열을 삭제하고 싶을 경우는 row_del(), col_del() 멤버함수를 이용하면 된다.

>>> M.row_del(0) # 첫 번째 행을 삭제한다.
>>> M.col_del(1) # 첫 번째 열을 삭제한다.

반대로 특정한 행이나 열을 끼워 넣고 싶다면 row_insert(n), col_insert(n) 을 이용한다. 이 경우 기존 행렬의 요소들을 밀어내고 그 위치에 입력한 행이나 열을 끼워 넣게 된다.

 그리고 A.row_join(B) 는 A행렬의 오른편에 B행렬을 병합시키고 A.col_join(B)는 A행렬의 하단에 B행렬을 병합시킨다.

>>> A=eye(3)
>>> A
⎡1  0  0⎤
⎢0  1  0⎥
⎣0  0  1⎦

>>> B=Matrix(3,2,range(11,17))
>>> B
⎡11  12⎤
⎢13  14⎥
⎣15  16⎦

>>> A.row_join(B)
⎡1  0  0  11  12⎤
⎢0  1  0  13  14⎥
⎣0  0  1  15  16⎦

>>> A.col_join(B.T)
⎡1   0   0 ⎤
⎢0   1   0 ⎥
⎢0   0   1 ⎥
⎢11  13  15⎥
⎣12  14  16⎦

또한 행렬객체의 메쏘드 중에 extract()라는 함수가 있다. 이것을 이용해서 원하는 부분을 뽑아낼 수 있다.

>>> A.extract(rowsList, colsList)

예를 들면 다음과 같다.

>>> M=Matrix(4,3,range(12))
>>> M
⎡0  1   2 ⎤
⎢3  4   5 ⎥
⎢6  7   8 ⎥
⎣9  10  11⎦

>>> M.extract([0,1,3],[0,1])
⎡0  1 ⎤
⎢3  4 ⎥
⎣9  10⎦

이 예를 보면 [0행, 1행, 3행] 과 [0열, 1열]이 겹치는 부부만 뽑아져 나온 것을 알 수 있다. 해당 행과 열에 선을 그어서 선이 겹치는 부분을 확인해 보면 쉽게 이해할 수 있을 것이다.