Graph-indexing wavelet tree (gWT)のグラフ検索が超速い

高速文字列解析の流れで、タイミングよく統数研チャンネルの資料が公開されていて、最後のほうのスライド(65枚目)にグラフの類似度検索の実装としてgwtが紹介されていたので遊んでみた。

データベースは、ChEMBLから取ってきた。なぜpubchemじゃないかというと面倒なので略。

入力のフォーマットがgSpanとかGASTONと一緒だったので、昔書いたのを流用しようとしたんだが、昔書いたpythonスクリプトはどうもOBMolAtomIterあたりがバグっていて動かないようだ(OBMolBondIterも動かなかった。)

File "sdf2gsp", line 17, in convert
  for i,atom in enumerate(ob.OBMolAtomIter(mol)): 
File "/usr/local/Cellar/python/2.7.3/lib/python2.7/site-packages/openbabel.py", line 4499, in __init__
  if not self.iter.__bool__():
AttributeError: '_OBMolAtomIter' object has no attribute '__bool__'

しょうがないのでiterateしない版で書き換えた。

#!/usr/bin/env python
import sys
import pybel
import openbabel as ob

def convert(sdf):
    mols = pybel.readfile('sdf',sdf)
    for n, mol in enumerate(mols, 1):
        print "t # %d" % n
        for i in range(mol.OBMol.NumAtoms()):
            print "v %d %d " % (i+1, mol.OBMol.GetAtom(i+1).GetAtomicNum())
        for j in range(mol.OBMol.NumBonds()):
            b = mol.OBMol.GetBond(j)
            print "e %d %d %d" % (b.GetBeginAtomIdx(),
                                  b.GetEndAtomIdx(),
                                  b.GetBondOrder())

if __name__ == "__main__":
    sdffile = sys.argv[1]
    convert(sdffile)

ちなみにこの形式に名前ついているんだろうか?babelとかでサポートされないと使い勝手が悪いんだけどなぁ。

これで、ChEMBLの137万件をgspにコンバートしてみたけど遅すぎるので後でHaskellで書きなおす。sdf単に舐めるだけだからOBMolに変換する必要もないし。

できたchembl_14.gspからindexファイルをつくる。600M(137万化合物)で10分ぐらいかかった@MBA。

./gwt-build -iteration 2 chembl_14.gsp chembl14

検索はみんな大好きImatinibをgspにしたものを使った。

$ ./gwt-search -kthreshold 0.8 chembl14 query.gsp
reading index file:chembl14
end reading
start building rank dictionary
end building rank dictionary
start transferring labels
end transferring labels
id:0 1080597:0.809449 712949:0.838758 413038:0.847826 \
394513:0.826087 391369:0.819028 179393:0.815124 \
175534:0.899647 48523:0.804348 47164:1.000000 16405:0.802727 
cpu time (sec):0.712119
mean cpu time (sec):0.712119

と5,6秒程度で計算終了。ウリィィィィって言いたくなるほど圧倒的に速い。

bayonも感激したけど、それ以上にgwtはすごいなぁと思った。

電子書籍を無名でも100万部売る方法

結論は口コミをうまく使えという事だろうか。

ProductName 電子書籍を無名でも100万部売る方法
ジョン ロック
東洋経済新報社 / 1260円 ( 2012-12-07 )


口コミが生まれやすくなるような印象的なシーンをちりばめろとか、買い手にレビュワーになってもらうためにメールを書けとかそんな感じ。

ゴールから考えるというかマーケット・インの思考的にはそうなるんだろうが、目的が100万部得る方法であっていい本を書く方法じゃないから、やり方がちょっと極端かなと思う。

極論としてはbooklapから適当に選んできてそれに合うようなテーマを探してきてちょこっと書いたら、はてブで話題になりそうなキャッチーなタイトル付けて、twitterで軽く炎上気味なプロモーションやれみたいな印象を持ったが、よく考えたらアルアルな感じか。

とはいえ、はてブでブックマークがつくのは自己肯定感位しか得られなくてお金にならんけど、ブックマーク稼ぐような内容をKindleで読めるようにするっていうのは一種の投げ銭システムとしてはいいやり方ではないかと考えているので、本書のようなやり方もアリだなとは思う。

OS10.8.2にopenbabel2.3.2をインストール

2.3.1のままだったので、昔のログを見ながらインストール。

が、古いswig(/usr/binにあるやつ)を見ていてエラーになるので、SWIGの場所をcmakeに知らせたいのだがオプションがわからない。

調べたトコロ

cmake -L

で一覧が出るらしい。必要なのはSWIG_EXECUTABLEなので

cmake ../openbabel-2.3.1 -DPYTHON_BINDINGS=ON \
-DPYTHON_LIBRARY=/usr/local/lib/libpython2.7.dylib\
-DPYTHON_EXECUTABLE=/usr/local/bin/python \
-DEIGEN2_INCLUDE_DIR=/Users/kzfm/openbabel/eigen-eigen-2.0.17 \
-DRUN_SWIG=ON \
-DSWIG_EXECUTABLE=/usr/loca/bin/swig

でOK

Titanium Studio3.0が動かない場合はPythonのpathとsdkのバージョンを確認する

ドはまっていたTitanium Studioがやっと動いた。

Titanium Studioの Help -> Titanium Studio -> View LogFileを見てみると

File "osx/3.0.0.v20121127170203/iphone/provisioner.py", line 10, in <module>
    from OpenSSL import crypto
ImportError: No module named OpenSSL

って出ていたのでprovisioner.pyの先頭行が

#!/usr/bin/env python

で、brew経由の/usr/local/bin/pythonを見ていてそっちにOpenSSLがインストールされていないのが原因だった。早速インストールしようとするとgccがないって怒られた。

$ sudo pip install pyOpenSSL
gcc-4.2: error trying to exec '/usr/bin/i686-apple-darwin11-gcc-4.2.1': execvp: No such file or directory

これはsof見て解決。

これでmobileprovisionを認識するようになったけれど、今度は

Available developer names:
[ERROR] :  Unable to find an iOS Developer Certificate for "NAME (NUMBER)"

ってのが出るようになったんだけど、これはTISTUD-2969にあるようにバグらしいのでバージョンをあげればいい。

$ titanium sdk install --branch 3_0_x --default

で最新のバージョンを入れた(3.0.0.v20121127170203 -> 3.0.1.v20130108000206)。Titanium Studioでバージョンを切り替える場合はtiapp.xmlをいじる。

追記13.01.09 titanium コマンドで実機に送る

実機に送る場合

titanium build -p iphone -T device -P [UUID] -f -V [NAME]

Shimehariというwaf

pypiのパッケージチェックをしていたらShimehariというwafを見つけてもしや!!と思ってクリックしたら予想通り〆張鶴インスパイアだった。

もうちょい調べたらFlaskとDjangoの中間あたりの規模を目指しているらしい

それからDocに使われているsphinx-bootstrapっていうテーマがいいなと思った。

Haskellで型宣言に型クラスを使う

今まで型宣言には具体的な型を書くものだと思っていたのだけど、型クラスを書いてもいいのね

myequal :: (Eq a) => a -> a -> Bool
myequal a b = a == b

RWHの15.8(Hiding the IO monad)では型クラスを使って抽象化していた。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan
オライリージャパン / 3990円 ( 2009-10-26 )


Bioisosteres in Medicinal Chemistry

見逃してた。これは超欲しい。

opensourceでRXNかSMIRKSのあつかえるchemoinformaticsのライブラリが欲しいなぁ。

高速文字列解析の世界が素晴らしかった

丸4日かけて8章(最終章)以外を読んだ。正月休みの後半の時間をこの本を読むのに費やしたのは正解だった。新年開始早々、知的な満足感が得られた。

本書を読めば、BWT、簡潔データ構造、ウェーブレット木、FM-Indexが理解できる。

LF-mappingのところ(p.28の補題3.4)を理解するのに時間がかかったが、これを理解できればFM-Indexのアルゴリズムが理解できる。ついでにWavelet Matrixも理解できた。ひとつひとつ丁寧に読み進めていけば理解できるようになっていたので良かった。

本や論文で書いてあるなら、まず読んで知っているのが必要条件(slide 24)と著者のスライドに書いてあるように、BWT、簡潔データ構造、ウェーブレット木、FM-Indexは知らないといけない知識になるんだろうなぁと。

pubmed調べたら、bioinformatics用途でしかみつからないのでchemoinformatics方面で応用できたらいいなぁと思った。

その他

  • LZEndはちゃんと理解していない
  • Boyer-Mooreは昔やった

Free Monadを調べている

Free Monadとは

さて、この「Freeモナド」について、オレオレ定義で簡単に言葉にすると。「Functorと組み合わせて様々な挙動を実現できるモナド」です。capriccioso String Creating(Object something){ return My.Expression(something); }

つまるところ

要はFree Monadは、Pureな値が何かの型によってリストのように順々にくるまれた構造をもつデータ型を表していて、Listにおけるfoldのような畳み込みと同様に、Impureな部分をたどっていってPureな部分に到達するまでfmapを繰り返して処理を行いますみょんさんの

もう少し圏論的な説明は

じゃあこの操作を普通の関手でもできるようにしてやろうということを考えると自然とFreeモナドが構成できる。直和が定義できる圏であれば、自由モノイドを作るのと同じ要領でモナドを作ればよい。北海道苫小牧市出身のPGが書くブログ

実際どう使うか

インターフェースを定義するみたいなイメージでいいのかな、Functorが具象クラスで。

RWHの15章を読みなおすのもいいらしい(これから読む)。

簡潔データ構造

4章

簡潔データ構造は、操作が高速でありながら作業領域量が小さいという2つの性質を兼ね備えたデータ構造であり、データ圧縮と索引の技術が組み合わさったものである

完備辞書(FID)

  • access: B[i]を返す
  • rank:B[0,i)中のb∈{0,1}の数を返す
  • select:B中で伝統から見てi+1番目に出現したb∈{0,1}の位置を返す

p.48の式がo(n)ビットに抑えられていると書いてあるのだが手で計算して確かめていない(ので後で計算する)。 (13.01.05 libcdsのチュートリアル読んだら理解した)

簡潔木の説明がさらりとしすぎてあまり触れられていない気もするが、本書においてあまり重要でないってことでいいのかな(全体を読んでみないとわからない)。

それから読んでいて索引が貧弱だなと思った。RRRとかselectとか引けない。