2011년 1월 31일 월요일

원소기호 모으기

매스매티카를 만든 울프램 사가 선보인 울프램알파는 여느 검색엔진과는 달리 계산 가능한 검색결과를 내놓는다. 즉, 연구에 필요한 자료를 쓰기 좋은 형태로 제공해 준다. 이점을 원소기호로 이루어진 가장 긴 단어를 찾는 파이썬 프로그램의 원소기호 목록을 울프램알파에서 받아오도록 바꿔보자.

울프램알파 API의 2.0 버전은 개인에 한해 무료로 공개되어 있다. 몇몇 제약이 있긴 하지만, 울프램알파 API를 체험해 보기엔 충분해 보인다. 울프램알파 API를 상용하려면 먼저 울프램알파에 계정을 만들고, AppID를 발급받아야 한다. 프로그램마다 별도의 AppID를 발급받아야 하며, 30개까지 발급받을 수 있다.

울프램알파 API는 파이썬, 자바 등 다양한 언어에 대한 바인딩도 제공하지만, 별도의 설치과정이 필요없는 웹서비스를 사용해보자. 울프램알파에서 검색에서 원소기호의 목록을 얻을 수 있는 검색어는 elements symbol이다.

울프램알파의 원소기호 검색 결과

몇몇 옵션으로 검색 결과에 제한을 두어 검색 결과를 더 간단하게 받을 수 있다. 먼저, 우리는 검색 결과를 웹브라우저를 통해 볼 것이 아니므로, html 형식으로 받을 필요가 없다. 또한 Input interpretation, Result, Table 등의 팟 중에서 Result만 필요하다. 이러한 옵션을 포함한 URL은 다음과 같다. xxx 부분에는 발급받은 AppID를 넣는다.

http://api.wolframalpha.com/v2/query?appid=xxx&input=elements%20symbol&format=plaintext&scanner=Identity&includepodid=Result

이 URL을 웹 브라우저에 한 번 넣어보자.

울프램알파 API를 이용한 원소기호 질의 결과

결과를 보면, 원하는 정보가 없다. 대신 recalculate라는 항목이 보인다. 이유를 알 수는 없지만, 울프램알파는 바로 원소기호를 알려주지 않고 별도의 파일에 결과를 기록한 후, 이 파일의 위치를 알려준다. 이 값을 다시 웹브라우저로 열어보자.

울프램알파 API를 이용한 원소기호 질의 결과

이제야 원하는 결과가 나왔다. plaintext 항목의 값이 우리가 원하는 원소기호이다. 이걸 이용하는 파이썬 코드는 아래와 같다.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import urllib, sys
from xml.dom.minidom import parse

url = 'http://api.wolframalpha.com/v2/\
query?appid=xxx\
&input=elements%20symbol&format=plaintext&\
scanner=Identity&includepodid=Result'

try:
   f = urllib.urlopen(url)
   dom = parse(f)
   queryresult = dom.getElementsByTagName('queryresult')
   recalculate = queryresult[0].getAttribute('recalculate')
   
   f2 = urllib.urlopen(recalculate)
   dom2 = parse(f2)
   plaintext = dom2.getElementsByTagName('plaintext')[0]
   symbols = ''.join(plaintext.firstChild.data.split())
   pattern = r"^(" + symbols + ")+$"
except Exception, e:
   print e
   sys.exit(1)
이렇게 만든 정규식 패턴을 조승연씨의 파이썬 코드에 적용하면 가장 긴 단어를 찾을 수 있다.

2011년 1월 14일 금요일

블로그스팟에 예쁜 코드 넣기

google-code-prettify라는 자바스크립트 프로그램을 이용하면 블로그스팟에 코드를 예쁘게 넣을 수 있다. 이 프로그램을 블로그스팟에 적용하는 방법을 살펴본다.

블로거에 로그인해서 ‘꾸미기’-’HTML 편집’으로 들어간다. ‘스킨 수정’에서 <head> 태그 다음 줄에 아래 내용을 추가한다.
<link href='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css' rel='stylesheet' type='text/css'/>
<script src='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js' type='text/javascript'>  </script>
<body> 태그를 수정한다.
 <body onload="prettyPrint()">
글을 작성하고, ‘HTML 편집’을 눌러서 글에 넣을 코드를 다음 태그로 둘러싼다.
<pre class="prettyprint">
    // add your code here
</pre> 
써보니, C++의 템플릿 코드에서 약간 문제가 발생한다. 이 문제는 C++ 코드를 '글쓰기'에서 입력하면 말썽을 일으키는 문자를 자동으로 변경해주니 해결된다. 매스매티카 언어를 지원하지 않는 문제도 있는데, 이건 직접 src/lang-nb.js 파일을 만들어서 등록해야 할 것 같다.

GMES 이야기를 시작하며...

내 전공은 정보통신공학인데, 국내의 여느 과와 달리 포토닉스 관련 분야를 다룬다. 그중에서도 컴퓨터 모의실험을 주로 하는데, 그 결과로 개발하고 있는 프로그램이 GMES이다. 모의실험에 사용하는 수치해석 프로그램을 개발하다 보면, 수많은 버그와 만나게 되는데 단순한 자판 입력 실수에서부터 프로그램 언어나 알고리듬의 구현 오류와 물리적 이해의 부족에서 발생하는 오류까지, 유형이 참 다양하다. 앞의 두 이유는 다른 분야의 프로그래밍에도 흔하니, 나는 물리적 이해의 부족으로 발생하는 버그에 대해 다뤄보고자 한다.

GMES는 맥스웰 방정식을 수치해석적으로 푸는 FDTD라는 방법을 구현한 프로그램이다. 맥스웰 방정식을 푼다는 점은 전자기 현상을 다룬다는 의미와 이를 양자역학적 해석보다는 고전역학적 해석으로 다룬다는 의미가 있다. FDTD는 우리가 생활하는 공간과 같은 시공간을 그대로 사용하는 방식으로 주파수 공간이나 파수 공간을 사용하는 방식과는 달리, 실제 실험과 유사한 방식으로 계산 공간을 설정할 수 있는 장점이 있다. 즉, 실험 모형과 입력 광원 등을 모두 머릿속에 쉽게 그려볼 수 있다.

GMES의 검증도 겸할까 해서, 학부 물리학과 2학년에 전자기학에서 배우는 쉬운 실험 모형을 하나 골랐다. 바로 두 유전체의 경계면에 입사하는 평면파 모형이다. 이중에서 입력 광원에 대해 살펴보자. 먼저, 이 모의실험에 사용할, 제대로 된 평면파의 모습은 아래와 같다.
정상적인 평면파의 모습
대략 y축의 0.8부터 -1.2까지 사선 방향으로, 완벽하진 않지만, 일정한 위상을 갖는 평면파의 모습을 관찰할 수 있다. 그림의 위와 아랫부분에 평면파가 없는 것은 흡수경계조건과 입력 광원의 위치 때문이다. x축의 -1.0부터 -2.0까지와 1.0부터 2.0까지는 CPML이라는 흡수경계조건을 사용해서 반사 없이 전자기파를 흡수하고, x축의 0.8에 위치한 입력 평면에서 오른쪽 위를 향해 평면파를 입력한다. y축의 왼쪽과 오른쪽 끝은 주기적경계조건(Periodic Boundary Conditions, PBC)이 설정되어 있어서 오른쪽 끝에 다다른 전자기파는 다시 왼쪽으로 입력된다. 그런데 이렇게 나와야 하는 녀석이 아래 그림처럼 나왔다.
허수부 위상을 맞추지 못해 변형된 평면파
사실 연구실에서 직접 만든 모의실험 프로그램은 뭔가 새로운 것을 시도할 때마다 한번에 제대로 된 결과를 내놓는 경우가 거의 없다. 앞에서 말한 세 가지 버그의 유형 중의 하나 이상이 꼭 말썽을 부린다. 이번에는 내 세심함이 부족해서 생긴 문제인데, 세 가지 유형 중의 하나로 따지자면, 물리적 이해의 깊이 부족이지 않을까 한다.

첫 그림의 왼쪽과 오른쪽 끝을 비교해보자. 오른쪽 경계에 다다른 전자기파는 다시 왼쪽 경계로 다시 입력된다고 했는데, 뭔가 이상하지 않은가? 왼쪽과 오른쪽의 경계를 맞춰보면 일치하지 않고 약간 틀어져 있는 것을 알 수 있다. 즉, 어느 정도의 위상차가 있다. 평면파의 위상을 맞추려면, 오른쪽 끝의 전자기파와 왼쪽 끝의 전자기파에 일정 위상차를 주어야 하는데, 이런 위상차를 주려면 전자기파를 복소수로 나타내야 한다. 복소수로 나타낸 전자기파는 단순한 곱셈으로 진폭의 변화 없이 일정 위상만큼 변화를 줄 수 있다.

그럼, 위에서 열거한 것 중에서 뭐가 문제일까? 개별 요소들은 각기 다른 환경에서 검증을 진행해 온 상태이다. 아직 검증하지 못한 부분에 버그가 존재할 수도 있고, 이들의 조합에서 문제가 발생할 수도 있다. 아니면, 내가 뭔가 잘 못 생각하고 있을 수도 있다. 내가 뭘 놓치고 있을까? 모든 가능성을 염두에 두고 print를 이용한 디버깅 정보 수집에 나섰다. 그러던 중 우연히 프로그램 일부가 실수 전자기파를 사용하고 있음을 알 수 있었다. 그리고 그 부분을 찾아보니 입력 광원 구현부였다. 입력 평면을 따라 전자기파의 실수부는 계속 변하는데, 허수부는 일정 위상(0)을 유지하고 있으니, 당연히 문제가 되었던 것이다. 이를 수정하니, 첫 번째 그림과 같은 정상적인 평면파를 볼 수 있었다.