- 更新日: 2014年10月10日
- Ruby
類似文字列検索ライブラリSimStringをRubyから使う
類似文字列検索ライブラリの SimString を Ruby から使ってみましたのでその記録。とりあえず SimString とその Ruby 用モジュールをインストールして、irb からサンプルコードを試してみるところまでです。
SimStringは,類似文字列検索のための高速かつシンプルなライブラリです. 類似文字列検索とは,文字列集合(データベース)の中から,クエリ文字列との類似度が閾値以上のものを,見つけ出す操作です. クエリ文字列と完全に一致しなくても,データベース中の似ている文字列を検索することができるので,スペル訂正,あいまい計算,柔軟な辞書マッチング,重複レコード検出,データベース統合など,様々なアプリケーションを構築できます.
— 環境 —
CentOS 6.5
SimString 1.0
SWIG 3.0.2
Ruby 2.1.2
以降の作業は、とりあえず動作確認のため Vagrant 上仮想マシンで行いました。
SimString のインストール
まずは、SimString 本体をソースからインストールします。
1 2 3 4 5 6 7 8 9 10 |
$ mkdir work $ cd work $ wget http://www.chokkan.org/software/dist/simstring-1.0.tar.gz $ tar zxvf simstring-1.0.tar.gz $ cd simstring-1.0 $ ./configure $ make $ sudo make install |
SimString のインストール確認。
1 2 3 4 5 6 |
$ which simstring /usr/local/bin/simstring $ simstring --version SimString 1.0 Copyright (c) 2009,2010 Naoaki Okazaki |
ヘルプ確認。
1 2 3 |
$ simstring --help |
SWIG のインストール
続いて、Ruby 用モジュールの動作に必要な SWIG をインストールします。SWIG(Simplified Wrapper and Interface Generator)は、C++ と Ruby など高級言語をつなぐためのソフトウェア。
まず、swig インストールの前に swig に必要な pcre-devel を前もって入れる。
1 2 3 |
$ sudo yum -y install pcre-devel |
yum でインストールできる swig パッケージのバージョンが 1.3.40 と古かったため、swig をソースコードからインストールしました。
1 2 3 4 5 6 7 8 9 |
$ cd ~/work $ wget http://prdownloads.sourceforge.net/swig/swig-3.0.2.tar.gz $ tar zxvf swig-3.0.2.tar.gz $ cd swig-3.0.2 $ ./configure $ make $ sudo make install |
swig バージョン確認。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ which swig /usr/local/bin/swig $ swig -version SWIG Version 3.0.2 Compiled with g++ [x86_64-unknown-linux-gnu] Configured options: +pcre Please see http://www.swig.org for reporting bugs and further information |
SimString の Ruby 用モジュールをビルド
続いて、SimString を Ruby から使うためのモジュールをビルドします。
1 2 3 4 5 6 7 8 9 10 11 |
$ cd ~/work/simstring-1.0/swig/ruby/ $ ./prepare.sh --swig $ ruby extconf.rb $ make compiling export_wrap.cpp linking shared-object simstring.so $ sudo make install /usr/bin/install -c -m 0755 simstring.so /usr/local/rbenv/versions/2.1.2/lib/ruby/site_ruby/2.1.0/x86_64-linux installing default simstring libraries |
これで Ruby 用モジュールがビルドできました。このステップの作業で少々エラーにはまったのですが、詳細はエントリー末尾に記載しました。
irb で SimString の動作確認
Ruby からの SimString 操作を確認するために、サンプルコードを irb 上で試してみました。SimString: A fast and efficient implementation of approximate string matching のページに書いてある、Ruby の A basic sample コードを irb で実行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
$ irb irb(main):001:0> require 'simstring' => true irb(main):002:0> db = Simstring::Writer.new('sample.db') => #<Simstring::Writer:0x007f097e92f250 @__swigtype__="_p_writer"> irb(main):003:0> db.insert('Barack Hussein Obama II') => nil irb(main):004:0> db.insert('James Gordon Brown') => nil irb(main):005:0> db.close() => nil irb(main):006:0> db = Simstring::Reader.new('sample.db') => #<Simstring::Reader:0x007f097e8e9ef8 @__swigtype__="_p_reader"> irb(main):007:0> db.measure = Simstring::Cosine => 2 irb(main):008:0> db.threshold = 0.6 => 0.6 irb(main):009:0> p(db.retrieve('Barack Obama')) ["Barack Hussein Obama II"] => ["Barack Hussein Obama II"] irb(main):010:0> p(db.retrieve('Gordon Brown')) ["James Gordon Brown"] => ["James Gordon Brown"] irb(main):011:0> p(db.retrieve('Obama')) [] => [] irb(main):012:0> db.measure = Simstring::Overlap => 4 irb(main):013:0> db.threshold = 1 => 1 irb(main):014:0> p(db.retrieve('Obama')) ["Barack Hussein Obama II"] => ["Barack Hussein Obama II"] |
キタ━(゚∀゚)━! ばっちし動いてますね!試しましたところ、どうやら db.threshold の値を小さくすると、類似判定を甘くできる模様です。db.threshold を1にすると、完全一致の時のみ一致判定が真になるのかな。
ここまで来れば、Rails製ウェブアプリケーションの検索フォームで、スペルミスや誤字による検索文字列を訂正する機能を実装できる見通しが立ちました。Google の「もしかして: ○○」でお馴染みのあれ。
最後に遭遇したエラーなどまとめ
最初、Ruby 用モジュールのビルドで、SimString 公式の手順を参考に以下の通りやりましたところ…
1 2 3 |
$ ./prepare.sh |
その後の make でエラーが発生しました。
1 2 3 4 5 6 7 8 |
$ ./prepare.sh $ ruby extconf.rb $ make compiling export_wrap.cpp export_wrap.cpp:4051:109: error: マクロ "rb_str_new_cstr" に引数が 2 渡されましたが、1 しか受け取りません ... |
export_wrap.cpp を確認したところ、swig 1.3.** と古いバージョンの swig でファイルが作成されていた。本当ならインストールした swig 3.0.2 で export_wrap.cpp が作成されるべきなはず。
ということで prepare.sh を確認したところ、–swig オプションを使うとシステムの swig コマンドを使って、export_wrap.cpp を生成するコードであることを確認できました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ vi ./prepare.sh #!/bin/sh # $Id:$ ln -s ../export.cpp ln -s ../export.h ln -s ../export.i if [ "$1" = "--swig" ]; then swig -c++ -ruby -o export_wrap.cpp export.i fi |
なので –swig オプションを付けてやり直し。
1 2 3 |
$ ./prepare.sh --swig |
こうすると、インストールした swig 3.0.2 で export_wrap.cpp が作成されます。
1 2 3 4 5 6 7 |
$ vi export_wrap.cpp /* ---------------------------------------------------------------------------- * This file was automatically generated by SWIG (http://www.swig.org). * Version 3.0.2 * ... |
これで、その後の make, make install まで上手く行けました!
1 2 3 4 5 |
$ ruby extconf.rb $ make $ sudo make install |
SimString を使うと簡単に類似文字列検索を実装することができ、とても便利です。作者の Naoaki Okazaki さんに感謝、ありがとうございます。
- – 参考リンク –
- SimStringをRubyから使ってみた – #詰んでる日記
- SWIGのインストール / SWIGメモ – サンプルコードによるPerl入門 ~ 伝統と信頼のPerlを学ぼう ~
- Fast and intelligent record search with Simstring, its PHP Extension and SimstringBundle for Symfony | Mapado Blog
- Ruby の関連記事
- Gemの作り方(Ruby Gem)
- ローカル開発中のgemをGemfileに書いてインストール
- 熊本地震の余震が夜に多いのは本当か?Rubyプログラムで検証してみた
- El Capitanでgemのnative extensionビルド失敗に対応
- Rubyで親クラスから子クラスの定数を参照
- MacabをRubyで使う
- rbenv/ruby-buildでRuby最新バージョンをインストール
- Rubyでクラスインスタンス変数にインスタンスメソッドからアクセス
- 距離1kmあたりの緯度・経度の度数を計算(日本・北緯35度)
- Google Maps Geocoding APIで住所から緯度・経度を取得するRubyコード
Leave Your Message!