たつをの ChangeLog : 2008-04-10

自分用のメモ。
SUFARY を 64bit FreeBSD で configure & make しようとしたら、configure が通らなかったので、試行錯誤してなんとかなった記録。
思い出しながら書いているので不正確かも。

- SUFARY 臨時復旧ページ
http://ta2o.net/tools/sufary/

まず、libtool-1.5.22 を入れて、それから下記の手順で。
% tar zxvf sufary-2.3.8.tar.gz
% cd sufary-2.3.8
% libtoolize --force
% ./configure
% make
% src/mkary README; src/sass a README
最後のは動作確認。

あと、sed っぽいエラーが出たら下記を。
SED=sed ;export SED
(ref. http://gimmix.org/max/article.php?id=311)

どうも libtool まわりはよく分からないんだよなあ。
奥が深い、というか。どうやって勉強すればいいんだろう。
- Manpage of LIBTOOL
http://www.linux.or.jp/JM/html/gnumaniak/man1/libtool.1.html

ついでに、MacBook (Mac OS X Tiger) へインストールする手順も。
開発環境が入っているのは前提です。
はまるのは host type。なので configure で適当に指定(正しいのをご存知でしたら教えて!)。
% ./configure --host=i686-apple-macosx
% make
% src/mkary README; src/sass a README

例えば、巨大なコーパスに対して出現する単語の共起情報を計算するときなどに、
(1) 各単語をあらかじめ ID (例えば整数) に変換して、
(2) その ID で内部処理を行い、結果をその ID で出力し、
(3) 出力結果 の ID を元の単語に戻す、
というロジックをよく使う。
機械学習の学習データの feature や、ログデータ分析なんかもこのロジックでやったりする。

SUFARY を用いてこの作業を効率的に行う方法をメモ。
速度よりも省ディスクスペースを優先する人向け。
巨大な単語集合(例えば100万とか1000万とか1億とか)に有効。
小規模なら、ありもののDBやハッシュで良いかと。

まず準備。
各行はキー文字列と付加情報をスペースでつないだもの。
mkary でインデックスを作成しておく。
% cat a.txt
foo フー
bar バー
hoge ほげ
uhyo うひょ
% mkary -l a.txt

コード (idstr.pl)。
#!/usr/bin/perl
use strict;
use warnings;
use SUFARY;

my $fn = shift @ARGV;
my $sa = SUFARY->new($fn);

# convert (demo)
for (my $i = 0; $i < $sa->{arraysize}; $i++) {
    my $str = id2str($sa, $i);
    my ($key, $info) = split(' ', $str, 2);
    print qq(id:$i => key:"$key", info:"$info"\n);
    my $id = str2id($sa, $key." ");
    print qq(key:"$key" => id:$id\n);
}

# error
my $str = id2str($sa, 100);
print qq(error1: "$str"\n); # empty
my $id = str2id($sa, "dummy");
print qq(error2: $id\n); # -1

sub id2str {
    my ($sa, $id) = @_;
    return "" unless 0 <= $id and $id < $sa->{arraysize};
    my $str = $sa->get_line($sa->get_position($id));
    chomp $str;
    return $str;
}

sub str2id {
    my ($sa, $key) = @_;
    my ($left, $right) = $sa->range_search($key);
    return -1 if not defined $left or $left != $right;
    return $left;
}

実行結果。
% ./idstr.pl a.txt
id:0 => key:"bar", info:"バー"
key:"bar" => id:0
id:1 => key:"foo", info:"フー"
key:"foo" => id:1
id:2 => key:"hoge", info:"ほげ"
key:"hoge" => id:2
id:3 => key:"uhyo", info:"うひょ"
key:"uhyo" => id:3
error1: ""
error2: -1
fooとbarの順番が入れ替わっているのは、suffix array の性質上アルファベティカルにソートされてるため。

もうちょっと実用的なスクリプト id2str.pl と str2id.pl も作ってみた。
#!/usr/bin/perl
# id2str.pl
use strict;
use warnings;
use SUFARY;
my ($id, $fn) = @ARGV;
my $sa = SUFARY->new($fn);
print id2str($sa, $id), "\n";
sub id2str {
    my ($sa, $id) = @_;
    return "" unless 0 <= $id and $id < $sa->{arraysize};
    my $str = $sa->get_line($sa->get_position($id));
    chomp $str;
    return $str;
}
#!/usr/bin/perl
# str2id.pl
use strict;
use warnings;
use SUFARY;
my ($key, $fn) = @ARGV;
my $sa = SUFARY->new($fn);
print str2id($sa, $key." "), "\n";
sub str2id {
    my ($sa, $key) = @_;
    my ($left, $right) = $sa->range_search($key);
    return -1 if not defined $left or $left != $right;
    return $left;
}

実行結果。
% ./id2str.pl 0 a.txt
bar バー
% ./id2str.pl 3 a.txt
uhyo うひょ
% ./str2id.pl foo a.txt
1
% ./str2id.pl uhyo a.txt
3

- SUFARY 臨時復旧ページ
http://ta2o.net/tools/sufary/

先日のサーバ移転[2008-03-16-1]により、それ以前に頂いたトラックバックのデータが壊れていたので修復しました。

以下、修復に用いた使い捨てスクリプト。
tb-standalone のコードを削りに削って作りました。
ざっと見れば、分かる人には、何が問題だったのかが分かります。

#!/usr/bin/perl
use strict;
use warnings;

my $fn = shift @ARGV;
my $data = load_data($fn);
store_data($fn, $data);

sub load_data {
    my ($fn) = @_;
    require Storable;
    scalar eval { Storable::retrieve($fn) } || [];
}

sub store_data {
    my($fn, $data) = @_;
    require Storable;
    Storable::nstore($data, $fn);
}

ref.
- [を] Perl の Storable モジュールのメモ[2006-05-09-2]
- 技術文書:くっつきトラックバック
http://ta2o.net/doc/tech/kuttuki-trackback.html

たつをの ChangeLog
Powered by chalow