2011年8月11日木曜日

Scheme の set! の読み方

"set bang" つまり「セットバン」と発音する。「The Seasoned Schemer」「Scheme修行」の注に書いてあった。

「"!"を"bang"と読むのかー、へー」と思ったが、そういえばUnixスクリプトの "#!" も「シェバン」と読むからごく自然な発想だ。

2011年8月8日月曜日

スタンフォード大のオンラインクラス - Introduction to Artificial Intelligence

「Paradigms of Artificial Intelligence Programming」を書いた Peter Norvig の講義を無料で受けられる、という企画を発見した。

ここ「Introduction to Artificial Intelligence - Fall 2011」に登録フォームや動画がある。

ざっと読んだところ、宿題やテストの回答を送れば採点してくれて、最後には評価メールのようなものをくれるらしい(You will receive a letter of completion from the instructors which will include information on how well you did. と書いてあった)。期間は10週間で、リアルの講義は今年の9月末、オンライン版は10月から開始予定。

ちなみに教科書は PAIP ではなく「Amazon.co.jp: Artificial Intelligence: A Modern Approach (3rd Edition) (Prentice Hall Series in Artificial Intelligence): Stuart Russell, Peter Norvig: 洋書」という本。申し訳ないが存在すら知らなかった。PAIP と内容が似ているのだろうか、Lisp を使うのだろうか…

さらにここ「Stanford University CS 221 Introduction to Artificial Intelligence」にも情報があった。前提条件として、線形代数と確率の知識が必要とのこと。

2011年8月7日日曜日

JavaでJSONのパース/シリアライズ - Gson

久しぶりにJavaの仕事。

JSONを処理するにあたってGsonというライブラリを使ったのでメモ。

Gson

そもそもGoogle社内で開発・利用していたものを、一般に公開したとのこと。

google-gson - A Java library to convert JSON to Java objects and vice-versa - Google Project Hosting から現在の最新版である google-gson-1.7.1-release.zip をダウンロードし、コンパイル&実行に必要な gson-1.7.1.jar を抽出しておく。

JSONのパース/シリアライズ

Gsonクラスをインスタンス化して、インスタンスメソッドである fromJson(), toJson() でそれぞれパース、シリアライズを行う。

JSONオブジェクトのキーがJavaの予約語と一致してしまう場合、つまり {"try":1, "class":2} のような場合、そのままではパースができないためアノテーション @SerializedName を使って対応する必要がある。

サンプルコード

Gsonを使ってパースとシリアライズを行う。パースするJSONは {"class":999} でキーにJavaの予約語"class"を含むため、@SerializedName を使ってJavaオブジェクトのフィールド_class と対応させる。

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;

public class Test{

    // JSONに対応するクラス。フィールド1個だけ。
    private class Myobj {
        // _classフィールド
        // 対応するJSONのキーがJava予約語(class)なのでアノテーションを付ける
        @SerializedName ("class") private int _class;

        // toString()
        public String toString() {
            return "_class: " + this._class;
        }
    }

    // main
    public static void main (String[] args) {
        // JSON
        String json = "{\"class\":999}";

        // JSONをパース
        Gson gson = new Gson();
        Myobj myo = gson.fromJson(json, Myobj.class);
        System.out.println("fromJson: " + myo);

        // Javaオブジェクトをシリアライズ
        String s = gson.toJson(myo);
        System.out.println("toJson: " + s);
    }
}

コンパイル&実行結果。ちなみに環境は Mac OS X 10.6.8 (Darwin 10.8.0 x86_64)。

$ javac -classpath gson-1.7.1.jar Test.java
$ java -classpath ./:gson-1.7.1.jar Test
fromJson: _class: 999
toJson: {"class":999}

2011年8月4日木曜日

オイラー・丸山法とPythonのMatplotlib

MatplotlibはPython向けの2次元プロットライブラリ。Wikipediaの記事「Euler-Maruyama method - Wikipedia, the free encyclopedia」(確率微分方程式の数値解法「オイラー・丸山法」)の、サンプルプログラムの中で使われていたので、インストールすることになった。

以下、Mac OS 10.6.8にMatplotlibをインストールして、Wikipediaのサンプルプログラムを実行したという話。

Matplotlibのインストール

Mac OSの場合、特にMacPortsやHomebrewなどのパッケージ管理ソフトを使っているとインストールがうまくいかないことが多いらしい。というのは、Matplotlibが最新の共有ライブラリにリンクされずに、パッケージ管理ソフトであらかじめ導入されていた別の共有ライブラリにリンクされる、といった現象が起こりやすいから。開発者の人も認識しているようで、README.osxというファイルに"Building mpl on OSX has proven to be a nightmare because of all the different types of zlib, png and freetype that may be on your system."と書いてあった(まるでナイトメアらしい)。

Mac OS X 10.6.8 (Darwin 10.8.0 x86_64) では、次の手順でインストールができた。

1. PythonとNumPyを確認

前提条件として、Python 2.5以上と、NumPyモジュール(version 1.1以上)が必要とのこと。これは以下のコマンドで確認できる。

$ python --version
Python 2.6.1
$ python -c "import numpy;print numpy.__version__"
1.2.1

自分で入れたのか最初から入っていたのか記憶が無いが、とりあえず自分の場合はすでに必要なものがインストールされていた。

2. githubからMatplotlibを取得
$ git clone https://github.com/matplotlib/matplotlib.git
3. make.osxの一部を書きかえる
$ cd matplotlib
$ vi make.osx
$ git diff make.osx
diff --git a/make.osx b/make.osx
index 4639eac..8dc60c7 100644
--- a/make.osx
+++ b/make.osx
@@ -3,6 +3,7 @@
 # make -f make.osx PREFIX=/Users/jdhunter/dev PYVERSION=2.6 fetch deps mpl_install
 # (see README.osx for more details)
 
+PREFIX=/usr/local
 MPLVERSION=1.1.0
 PYVERSION=2.6
 PYTHON=python${PYVERSION}
@@ -16,8 +17,8 @@ ARCH_FLAGS=-arch i386 -arch x86_64
 # but the download URLs are subject to change.
 
 ZLIBVERSION=1.2.5
-PNGVERSION=1.5.1
-FREETYPEVERSION=2.4.4
+PNGVERSION=1.5.4
+FREETYPEVERSION=2.4.6

変更点は3つ。第一に、共有ライブラリのインストールパスを"/usr/local/lib"にしたいので、PREFIX=/usr/local を追加。それから、libpng と freetype のバージョンを現時点で最新の番号にした。

4. makeする
$ make -f make.osx fetch deps mpl_install_std

これを実行すると、fetch, deps, mpl_install_stdという3つのターゲットが処理される。fetchがzlib等のライブラリのソースをダウンロードしてきて、depsがライブラリのコンパイルとインストールをして、最後にmpl_install_stdがMatplotlib自身のコンパイルとインストールを行う流れ。

完了したら、/usr/local/lib と /Library/Python/2.6/site-packages/matplotlib を確認してみる。

$ ls -t1 /usr/local/lib/
libz.1.2.5.dylib
libz.1.dylib
(略)

$ ls -t1 /Library/Python/2.6/site-packages/matplotlib
mlab.pyc
mpl.pycf
offsetbox.pyc
(略)

$ otool -L /Library/Python/2.6/site-packages/matplotlib/_png.so
/Library/Python/2.6/site-packages/matplotlib/_png.so:
 /usr/local/lib/libpng15.15.dylib (compatibility version 20.0.0, current version 20.0.0)
 /usr/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
 /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

ポイントは(1)共有ライブラリができていて、(2)matplotlibのモジュールができていて、(3)モジュール内の共有ライブラリが(1)の共有ライブラリに依存していることの3つ。

オイラー・丸山法

常微分方程式の世界における「オイラー法」に対応するのが「オイラー・丸山法」らしい。「丸山」のフルネームは丸山儀四郎。

Euler-Maruyama method - Wikipedia, the free encyclopedia のExample code(Python)をそのままコピー&実行するとグラフができる。

コードでrandomとか使ってるからあたり前だけど、「実行する度に結果が変わってOK」という考えが新鮮。これまで確定的な微分方程式の数値計算しか扱ったことが無かったので変な感じがする。

ざっと検索したところ、普通のプログラミング環境ではなくエクセルを使って計算する人もいる(そういう方向性の本が出版されている)。

Mac OS で XZ形式アーカイブを使う

今日まで知らなかったが、Mac OS標準のコマンドでは "tar xJf *.tar.xz" ができない。

大抵は gzip か bzip2 を使えば済む話だが、どうしても xz しか選択肢が無い状況なら XZ utils と GNUのtarをインストールするとよい(詳しいことは「Mac で XZ 形式を圧縮・解凍したいときの備忘録 - takkan_mのNo planな日常」に書いてあった)。

あとどうでもいいが tar のオプションは人によって揺らぐ。Jxf だったり xJf だったり -Jxf だったり… 自分の場合は x か c が必ず最初に来る。コマンドを打つとき、開く(x)か閉じる(c)かが最初に頭の中で決まるから。

2011年8月3日水曜日

GoogleのBloggerに関連記事を表示する(brps - gas.js)

クリボウの Blogger Tips: Blogger で「関連記事」リストを表示する 2 つの方法 を参照して「3行コピペでできる方法」を今日試したのだが、期待どおりに動作しなかった。具体的には、関連記事のリストが表示されるべき位置に「キーを取得してください」という旨のエラーメッセージが表示されてしまった(英語だった)。

問題のJavaScriptを提供しているbrpsプロジェクトページ brps - Blogger Related Posts Service - Google Project Hosting を調べたら、「ClientGasJs」のページに違う方法が書いてあった。BRPSデータベースを使う方式から、Google AJAX Search APIを使う方式に変えた、ということらしい。

こちらの方法はうまく動作したので、メモしておく。

1. Blogger 管理画面「レイアウト > HTML の編集」ページを開く
「ウィジェットのテンプレートを展開」にチェックを入れる
2. 関連記事を表示したい場所に <div id='gas-results'/> 等を追加
  <b:if cond='data:blog.pageType == &quot;item&quot;'>
    <div>
      <h3>Related Posts</h3>
      <div id='gas-results'/>
    </div>
  </b:if>

見出しに相当するh3の部分は、利用しているテンプレートに依存する(h2やh4を使うほうが適切な場合もあるだろう)。<b:if>...</b:if>で囲んでいるのは、一つの記事だけが表示される場合に限り関連記事を表示するため。トップページやアーカイブページのように複数記事が表示される場合、今回の方法はうまく動作しない(1番上にある記事しか関連記事が表示されない)。

3. </body>の前あたりにJavaScriptを追加
<b:if cond='data:blog.pageType == &quot;item&quot;'>
  <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'/>
  <script>
window.brps_gas = {
//  remove_tags: ['unwanted_tag1', 'unwanted_tag2'],
//  tag_selector: 'a[rel=tag]',
  limit: 5,
//  add_sites: ['secondblog.blogspot.com', 'thirdblog.blogspot.com'],
  remove_string_regexp: /^.*?: /,
  exclude_url_regexp: /(\/search\/label\/|(archive\.html|blog\.example\.com\/|\.blogspot\.com\/)$)/,
  html_loading: '<span>Loading...</span>',
  html_no_results: '<span>Found no results.</span>'
  };
  </script>
  <script src='http://brps.appspot.com/gas.js'/>
</b:if>

jQueryをすでに利用している場合、<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'/>は必要ない。動作を調整するためにremove_tags, tag_selector, limit等のオプションを指定できるので、状況に合わせて調整する。自分の場合は不要だったので//でコメントアウトしたが、

  • 関連記事を洗い出すときに無視して欲しいラベル(tag)があれば、remove_tagsの所に列挙する
  • ラベル(tag)のhtmlコードをカスタマイズしているのであれば、tag_selectorの所で変更する
  • 複数のドメインでブログを書いているのであれば、add_sitesの所に列挙する。

以上の操作を行ってレイアウトを保存すればhtmlに反映される。あとは必要に応じてCSSを調整すればOK。

2011年8月2日火曜日

コマンドを手軽にマルチプロセス実行 GNU Parallel

GNU Parallelというプログラムを今さら知ったのでメモしておく。これは、複数のプログラムを並行して実行したいときに便利。

インストール

GNU Parallelのダウンロードページから最新版の parallel-20110722.tar.bz2 をダウンロードし、configure, make, make install する。

$ wget ftp://ftp.gnu.org/gnu/parallel/parallel-20110722.tar.bz2
$ tar xvjf parallel-20110722.tar.bz2
$ cd parallel-20110722
$ ./configure
$ make
$ sudo make install

ちなみに環境は Darwin 10.8.0 x86_64。

試してみる

とりあえずPerlで簡単なプログラムを作って試す。

print_argv0.pl
#!/usr/bin/perl
sleep(1);
print "$ARGV[0]\n";
exit;
1秒間スリープして引数を表示するだけのもの。これにlsの結果を入力する処理を、prallelコマンド経由で実行してみる。
同時に実行するジョブ数 = 20 で実行した場合(-jオプション)
$ time ls|parallel -j 20 ./print_argv0.pl {}
COPYING
Makefile
Makefile.am
Makefile.in
NEWS
README
aclocal.m4
config.h
config.h.in
config.log
config.status
configure
configure.ac
install-sh
missing
print_argv0.pl
src
stamp-h1

real 0m1.396s
user 0m0.229s
sys 0m0.259s
1.396s で終了したので、確かに同時に実行されている様子。lsの結果が18行なので順番に実行すれば18秒はかかってしまうはず。
ジョブ数 = 1 で実行した場合
$ time ls|parallel -j 1 ./print_argv0.pl {}
COPYING
Makefile
Makefile.am
Makefile.in
NEWS
README
aclocal.m4
config.h
config.h.in
config.log
config.status
configure
configure.ac
install-sh
missing
print_argv0.pl
src
stamp-h1

real 0m18.517s
user 0m0.231s
sys 0m0.243s
19.517s かかった。

プロセス

ついでにプロセスの状態を調べるため、ジョブの数を3にして parallel をバックグラウンド実行した後、psコマンドを打ってみた。

$ time ls|parallel -j 3 ./print_argv0.pl {} &
[1] 5140
$ ps axl
  UID   PID  PPID CPU PRI NI      VSZ    RSS WCHAN  STAT   TT       TIME COMMAND
(略)
  501  5142  5140   0  29  0  2443672   8584 -      S      p0    0:00.18 /usr/bin/perl -w /usr/local/bin/parallel -j 3 ./print_argv0.pl {}
  501  5172  5142   0  30  0  2437344   1048 -      S      p0    0:00.01 /usr/bin/perl ./print_argv0.pl Makefile.in
  501  5173  5142   0  30  0  2437344   1048 -      S      p0    0:00.01 /usr/bin/perl ./print_argv0.pl NEWS
  501  5174  5142   0  31  0  2437344   1048 -      S      p0    0:00.01 /usr/bin/perl ./print_argv0.pl README
(略)

parallel自体もperlで書かれており、/usr/bin/perl -w により実行されている(プロセスID 5142)。中ではforkしているらしく、子プロセスが3つ生成されている(5172, 5173, 5174)。