wxMaxima를 설치하고 실행시키면 명령어를 입력할 수 있는 윈도우가 실행된다. wxMaxima에서는 입력 명령어와 출력 결과가 하나의 쌍으로 표시되며 화면 왼편에 다음 그림과 같은 모양의 바가 표시 되는데 이것을 셀(cell)이라고 칭한다.


[그림 1[ 명령 입력 단위인 셀(cell)


하나의 셀을 가리키는 이 바의 상단의 작은 삼각형을 클릭하면 셀의 내용을 접었다 폈다 할 수 있다. 이제 이곳에 명령어를 타이핑해서 입력하면 그 계산결과가 바로 같은 셀 안에 표시된다.

 처음에 wxMaxima에서 주의할 것은 명령을 입력하려면 그냥 [Enter]키가 아니라 󰍬[Shift]+[Enter] 를 눌러야 명령이 입력된다는 것이다. 하나의 명령이 끝났다는 표시는 세미콜론(;) 혹은 달러($)표시를 명령 끝에 타이핑하면 되지만, [Shift]+[Enter]를 입력하면 자동으로 명령 끝에 세미콜론(;)이 붙고 결과가 표시된다.



 한 줄에 여러 개의 명령을 입력하고 싶을 때는 세미콜론(;) 또는 달러($)로 구분하면 되며, 차이점으로는 달러($)로 끝나는 명령의 출력은 화면에 표시되지 않는다는 것이다. 다음 예에서 x^2+2*x$ 명령은 $로 끝났기 때문에 결과가 화면에 표시되지 않는다.



위에서 sqrt()함수는 제곱근(square root) 값을 입력하는데 사용된다. sin( ), cos( )함수는 각각 사인함수와 코사인함수를 입력하는데 사용된다. 사인함수를 입력하는데 그냥 sinx라고 하면 안 되고 반드시 독립변수에 괄호를 쳐서 sin(x)라고 입력해야 됨에 유의하자.




Posted by 살레시오
,

 학부생들에게는 (공대생이라 할 지라도) 수학 계산에 쓰이는 프로그램이 낯설 것이다. 여기서 '수학 계산에 쓰이는 프로그램'이라는 것은 윈도우를 깔면 기본으로 제공되는 계산기 프로그램을 말하는 것이 아니라 수학 문제를 해결하는데 사용되는 전문적인 프로그램을 말하는 것이다.


 사실 공대에 들어와서 <일반 수학>이나 <공학 수학>같은 과목들을 배울 때에는 손으로 풀거나 공학용 계산기 같은 것으로 함수 입력해서 그래프를 그리고 하는 방식이 아직까지는 익숙한 풍경이다. 학부생들이 전문적인 컴퓨터 프로그램을 이용한다는 것은 그리 일반적이지는 않은 것 같다. '곱셈이나 나눗셈' 하면 '계산기'가 보통은 떠오르지만 '방정식'을 푸는데 컴퓨터로 그 식들을 입력하고 엔터키를 치면 그 해를 간단히 구할 수 있다는 것을 아는 학부생들이 얼마나 될까.


 이러한 수학 과목에서 매스메티카(mathematica)나 매트랩(matlab)을 실습에 도입한 교재들이 간간히 있기는 하다. 하지만 이들 패키지는 고가의 상용 제품들이므로 학부생들이 자유롭게 실습에 이용하기에는 제약이 따른다. 하지만 훌륭한 대안이 있는데 바로 Maxima와 Sage라는 프리웨어들이다.

[그림 1] Maxima의 외형

 이 그림의 첫번째 명령에서 보면 입력방정식이 x2+ax+b=0 으로 a와 b라는 기호를 어떤 수치값을 갖는 변수가 아니라 문자상수로 취급하여 그 해를 보여줌을 알 수 있다. 이렇게 문자 상수를 숫자처럼 다루는 것을 기호식 해석(symbolic analysis)라 하고 mathematica, maple, maxima, sage와 같은 프로그램이 사용된다. 반면, 변수 이외의 모든 기호는 어떤 수치값을 지정하여 문제를 푸는 것을 수치 해석(numerical analysis)라고 하고 일반 계산기 (프로그램), MATLAB, SciLab, Octave, FreeMat 등의 프로그램이 사용된다.


[그림 2] Sage의 외형


 개인적인 관심은 <공학 수학>의 교과 과정에 Maxima나 Sage 같은 프로그램의 사용법을 접목시킬 수 있는가이다. 공과 대학의 수학 과목들이 학생들이 주어진 공학적 문제를 수학적으로 모델링하고 그것을 해결하는 능력을 배양하는 데에 목적이 있지만 이제는 컴퓨터를 이용한 문제 해결 능력도 같은 비중으로 다루어져야 한다고 생각하기 때문이다. 즉, 기존에는 수학에서 컴퓨터 이용 능력이 보조적인 역할로 다루어졌지만 이제는 동등하거나 혹은 더 비중있게 다루어져야 하지 않을까 하는 생각이 든다.



Posted by 살레시오
,

 만약 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()함수를 이용한 미분방정식을 푸는 가장 기본적인 방법이다.



Posted by 살레시오
,

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


[표 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.eigenvects(**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    ]




Posted by 살레시오
,

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


[표 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⎦



Posted by 살레시오
,

  행렬 객체에 대해서 파이썬 인덱싱과 슬라이싱도 사용할 수 있다. 주의할 점은 수학의 행렬은 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열]이 겹치는 부부만 뽑아져 나온 것을 알 수 있다. 해당 행과 열에 선을 그어서 선이 겹치는 부분을 확인해 보면 쉽게 이해할 수 있을 것이다.



Posted by 살레시오
,

 심파이(sympy)의 행렬 객체는  Matrix이다. 이 Matrix 객체를 생성할 때는 리스트를 넘겨주면 된다. 넘겨준 리스트의 각 요소는 행렬의 행이 된다. 기본적인 사용 예는 다음과 같다.


>>> Matrix([[1,0],[0,1]]) #[1,0]이 1행, [0,1]이 2행이 된다.
>>> Matrix([[11, 22, 33]]) # 리스트의 첫 번째 요소인 [11,22,33]이 1행이 된다.
>>> Matrix([11, 22, 33]) # 11이 1행, 22가 2행, 33이 3행이 된다.


다른 방법으로 행의 개수와 열의 개수를 명시적으로 지정해 주는 방법이 있다.


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

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


행 요소와 열 요소의 관계를 파이썬 함수로 작성하여 이것을 사용할 수도 있다.


>>> def f(i,j):
 if i==j : return 1
 else : return 0

>>> Matrix(4,4,f)
⎡1  0  0  0⎤
⎢0  1  0  0⎥
⎢0  0  1  0⎥
⎣0  0  0  1⎦


명시적 함수뿐만 아니라 익명 함수도 사용할 수도 있다.


>>> Matrix(3, 4, lambda i,j:1-(i+j)%2)
⎡1  0  1  0⎤
⎢0  1  0  1⎥
⎣1  0  1  0⎦


특수한 행렬을 생성하는 함수도 있다. eye() 함수는 항등 행렬을 생성하며, zeros() 는 영행렬을 그리고 ones()는 일행렬을 만들어 준다.


>>> eye(4)
>>> zeros(2)
>>> ones(3)
>>> ones(1,3)


대각행렬을 생성하는 diag() 함수도 있다. 스칼라나 행렬을 인수로 주면 그것들로 대각행렬을 생성한다.


>>> diag(1,2,3)
>>> diag(-1, ones(2,2), Matrix([5,7,6]))


스칼라는 1x1 행렬로 간주되며 주어진 행렬들을 대각 위치에 놓는다.


 난수 행렬을 발생시킬 수도 있으며 randMatrix() 함수를 이용한다.


>>> randMatrix(4) # 4x4 행렬 생성
>>> randMatrix(3,4) # 3x4 행렬 생성
>>> randMatrix(5, symmetric = True) # 5x5의 대칭행렬 생성


이 행렬의 요소는 100이하의 양의 정수로 채워진다.


[표 1] 행렬 객체의 생성 용례들

용법

내용

Martix(list)

Matrix([list1, list2,...])

Matrix(r, c, seq)

Matrix(r, c, func)

열벡터 생성

행렬 생성

seq를 이용하여 r x c 행렬 생성

함수를 이용하여 r x c 행렬 생성

eye(n)

n x n 단위행렬

zeros(n)

zeros(r, c)

n x n 영행렬

r x c 영행렬

ones(n)

ones(r, c)

n x n 일행렬

r x c 일행렬

diag(arg1, arg2, ...)

args 요소들의 단위행렬 생성

randMatrix(n)

randMatrix(r, c)

n x n 난수행렬 (대칭행렬은 symmetric=True 옵션을 지정)

r x c 난수행렬


 한 가지 주지할 사항은 Matrix 객체는 mutable 하다는 것이다. 따라서 immutability 가 필요한 곳(예를 들어 딕셔너리의 키)에는 사용할 수 없다. immutable행렬이 필요하다면 ImmutableMatrix 를 이용하면 된다.




Posted by 살레시오
,

 심파이(sympy)에서 미리 정의된 상수들은 다음과 같은 것들이 있다.


[표 1] 심파이의 기정의된 상수들

sympy 상수
의미
I, 1j, 1J
허수. (예를 들어 3+4j 는 3+4*I 와 같이 입력해야 한다.)
pi
원주율(3.141592..)
E
자연상수(2.718281..)
nan
not a number
oo
(positive) infinity
zoo
complex infinity


허수로 I를 이용할 때는 허수부와 I 사이에 반드시 곱기호를 넣어 주어야 한다.


>>> abs(1+2*I)
sqrt(5)


무리수의 근사값을 알고 싶다면 evalf() 멤버함수를 이용하면 된다.


>>> pi.evalf()
3.14159265358979

>>> E.evalf()
2.71828182845905




Posted by 살레시오
,

 심파이에서 대수 기호를 사용하기 위해서는 symbols() 함수를 사용하면 된다.


>>> a = symbols(‘a’)


여기서 대입 연산자(=) 왼쪽의 변수명과 symbols()로 생성되어 표기되는 대수기호는 같은 것으로 하는 것이 좋다. (즉 a=symbols(‘b’) 는 바람직하지 않다.)


다음 예와 같이 여러 대수 기호들을 한꺼번에 생성할 수도 있다.


>>> x = symbols(‘x:5’) # x0, x1, x2, x3, x4 를 튜플로 생성
>>> y = symbols(‘y1:11’) # y1, y1, ..., y10 을 튜플로 생성


대수 기호의 종류를 지정할 수도 있다.


>>> a = symbols(‘a’, integer = True) #정수
>>> b = symbols(‘b’, real = True) #실수
>>> c = symbols(‘c’, complex = True) #복소수
>>> d = symbols(‘d’, positive = True) #양수로 정의
>>> f, g, h = symbols(‘f g h’, cls=Function) #함수 기호로 정의


 아래 심파이 라이브 웹페이지를 처음 접속하면 x, y, z, t 는 대수 기호로, k, m, n은 정수 대수 기호로, f, g, h는 함수 기호로 사용할 수 있도록 미리 symbols()함수로 생성된다는 것을 알 수 있다.


[그림 1] live,sympy.org 접속시 실행되는 명령들


따라서 기정의된 대수기호를 이용하여 바로 명령을 입력할 수 있다.



Posted by 살레시오
,

 심파이에서는 변수를 대수 기호로 사용하려면 반드시 symbols()함수를 써서 지정해 주어야 한다. 만약 x, y, z를 대수 기호로 사용하겠다면 다음과 같이 하면 된다.


>>> x = symbols(‘x’)
>>> y,z=symbols(‘y z’)


아래부터는 live.sympy.org 에서 직접 확인해 볼 수 있다.


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

대수 방정식

 이것을 이용하여 수식 x+2y 를 입력해 보자.


>>> expr = x+2*y
x+2*y


여기서 x, y는 마치 파이썬의 변수처럼 사용되었지만 내부적으로는 대수기호로 지정되어 있는 상태이다.


>>> expr+1
x + 2*y + 1

>>> x*expr
x*(x + 2*y)

>>> expr2 = expand(x*expr)
x**2 + 2*x*y

>>> factor(expr2)
x*(x + 2*y)


이와 같이 expand() 함수를 이용하여 수식을 전개할 수 있고 factor()함수로 인수분해를 할 수 있다.


 분수식을 통분하거나 분리할때는 together() 함수와 apart()함수를 이용한다.


>>> a, b, c, d = symbols('a b c d')

>>> together(a/b + c/d)
(a*d + b*c)/(b*d)

>>> apart( (a**2+a+4)/(a+2) )
a - 1 + 6/(a + 2)


 대수 방정식을 풀기 위해서는 solve()함수를 이용하면 된다.


>>> solve(x**2-2,x)
[-sqrt(2), sqrt(2)]


미분

 이제 함수 sin(x)ex 를 미분해 보자. 미분은 diff() 함수를 이용하면 된다.


>>> diff(exp(x)*sin(x),x)
exp(x)*sin(x) + exp(x)*cos(x)


적분

 함수 exsin(x) + excos(x)의 부정적분을 계산해 보자. integrate()함수를 이용하면 된다.


>>> integrate(exp(x)*sin(x)+exp(x)*cos(x),x)
exp(x)*sin(x)


정적분을 구하려면 integrate()함수의 두 번째 인수에 범위를 지정해 주면 된다. sympy에서 무한대는 oo (소문자 o 두 개) 기호를 사용한다.


>>> integrate(sin(x**2),(x,-oo, oo))
sqrt(2)*sqrt(pi)/2


극한

 극한값을 구하려면 limit()함수를 이용하면 된다.


>>> limit(sin(x)/x,x,0)
1


미분방정식

 심파이를 이용하면 미분 방정식도 풀 수 있다.


>>> t=symbols('t')
>>> y=Function('y')
>>> dsolve( Eq(y(t).diff(t,t)-y(t), exp(t)), y(t))
y(t) == C2*exp(-t) + (C1 + t/2)*exp(t)


선형대수

 선형대수도 가능하다. 예를 들어 행렬


[ 1 2 ]

[ 3 4 ]


의 고유값을 구하려면 다음과 같이 하면 된다.


>>> A = Matrix([[1,2],[2,2]])
>>> A.eigenvals()
{-sqrt(17)/2 + 3/2: 1, 3/2 + sqrt(17)/2: 1}


 이와 같이 sympy를 이용하면 다양한 대수식을 표현하거나 방정식을 풀 수 있다.




Posted by 살레시오
,