This document is written in Japanese.

Anthy

** 本ドキュメントの構成 **
Anthyのドキュメントはパッケージの doc/ 以下に置かれ、
ドキュメントの目次は doc/00INDEX にあります。



** 本ソフトウェアの構成 **
Anthyは変換エンジンの機能などを持つライブラリと、それを利用
するためのいくつかのコマンドなどから構成されています。



** 変換エンジンの構成 **
Anthyはおおまかにわけて次の5つのモジュールで構成されています。
 *データ型モジュール src-diclib/
 *単語辞書モジュール src-worddic/
 *文節境界のモジュール src-splitter/
 *候補の順序の決定のモジュール src-ordering/
 *フロントエンド(変換コンテキストの管理等) src-main/

日本語にはある読みに対して複数の意味や品詞がある同音異義語が
多数存在します。これを扱うために、変換元の文字列(つまり同音の
文字列)を代表するためのデータ型を用意しています。
このデータ型を用いたプログラムの典型的な流れを次に示します。

int n, i;
 /* ある読みに対応するハンドルを取得する */
seq_ent_t seq = anthy_get_seq_ent_from_xstr(yomi_string);
 /* いくつの同音異義語が存在するかを取得 */
n = anthy_get_nr_dic_ents(seq, NULL);
 /* 各異義語に対して */
for (i = 0; i < n; i++) {
   /* 単語を取得する */
  anthy_get_nth_dic_ent_str(seq, NULL, i, &str);
   /* 品詞を取得する */
  anthy_get_nth_dic_ent_wtype(seq, NULL, i, &wt);
 ..
}

同音異義語の中には同じ品詞のものや異なる品詞をもつものもあり、
活用する単語の各種の活用形が含まれます。上記のプログラムでは
いくつの同音異義語があるかを取得したあとに、インデックスを用い
て各種の情報を取得しています。

かな漢字変換の各モジュールはこの辞書ライブラリからデータを
取得することによって動作します。次に各モジュールのおおまかな
構成を説明します。

Anthyライブラリの動作はユーザが変換前の(主に平仮名で構成される)
文字列を渡すことによって開始されます。変換の動作は文節の境界の
検出と候補の生成の2つにわかれます。
文節の境界はユーザが変更することがあるので、境界検出モジュールは
ユーザが設定した境界を制約条件として動作します。最初に文字列を
設定した際にはこの制約条件は無い状態です。
最初に文字列を設定した際に、文字列中の全ての部分文字列に対し
それが自立語かどうかをチェックして自立語ならば接頭辞や接尾辞
付属語を追加したパターンが文中にあるかどうかをチェックして
struct word_listというデータ構造を構成します。
どのような付属語が接続するかは自立語の品詞によって異なり、
そのデータは定義ファイルに記述されています。

候補の生成は上の分割の際に与えられた品詞をもとにして
行われます。


** 例文の利用 **
パラメータ計算の際には例文を変換し、その際に変換結果だけでなく、グラフ中の
通過したエッジの情報も出力します。
(文節区切りの際にはグラフの形はlatticeになります)
変換結果を正解と比較することにより、エッジの種類毎に正解になる確率および
誤変換になる確率を求めます。
変換の結果が正解であればその分母と分子に加算し、誤変換であれば分母のみに
加算するという手法を取っています。
ソースのディレクトリで make update_params を実行することで
例文の変換とパラメータの更新が行われます。


** 文節区切りのアルゴリズム **
分節の区切りは、基本的にはlatticeを構成し、スコアが最小となるパスを
viterbiアルゴリズムで検索することで行います。
スコアは確率を基本としていますが、その他にも各種のバイアスをかけています。


** 変換モジュールの構成 **

文節境界の設定
(文節中の単語境界の検索)
候補の列挙
候補のソート


*変換パイプライン ( コアは src-main/ 以下にある )
 context 変換コンテキスト
  文節境界の検出 ( src-splitter/ 以下にある )
   depgraph
   metaword
   evalborder
   lattice
   compose 文節構造の解析
  候補の順序決定 ( src-ordering/ 以下 )
   candsort 候補の並びかえ
   candhistory
   commit 
   candswap
   infosort
   relation
 personality パーソナリティの管理
*辞書ライブラリ
 conf グローバルな設定
 file_dic 辞書ファイル
 mem_dic メモリ上の辞書
 record ユーザごとの設定
 alloc メモリアロケータ
 logger
 dic_session 辞書エントリのbook keeping
 xchar 文字型
 xstr 文字列
 wtype 品詞
 ext_ent 候補の生成
 ruleparser 設定ファイルの解析
 dic_util 辞書管理プログラムのための関数群


** seq_entについて **
anthyではひらがな列(読み)に対応するデータ構造として、seq_entという
構造体を用います。この構造体はdiclibの中で管理されており、
フロントエンド側からは適切なAPIでアクセスすることができます。
seq_entは同音異義語の配列を持っています。
 seq_entの主要メンバ
  * str: 読み
  * id: 辞書中のインデックス
  * seq_type: ST_ のフラグ
  * dic_ents: 単語(or複合語)の配列


** 辞書ファイルの形式 **
辞書ファイルはエンディアンやバイナリフォーマットの異なるマシン間で
共有できるような形式とする。
辞書のセクションは次のようなものがある
*ヘッダ
*辞書のエントリ
*辞書のエントリへのインデックス
*辞書のインデックス
*辞書のインデックスへのインデックス


** 辞書ファイルアクセスの手法 **
複数の文字列の検索を同時に行うことで効率を高めることを狙っています。
変換対象の文字列の部分文字列を列挙してソートし、それを辞書ファイル内の
ソートされた文字列と比較します。
例えば、「わたし」という文字列を検索する際には部分文字列
「わ」「わた」「わたし」「た」「たし」「し」を列挙し、それをソートした列
「し」「た」「たし」「わた」「わたし」を辞書ファイルの最初から順に
スキャンします。
ただし、システム辞書については、他の工夫も含めて検索の高速化を図っています。


** デバッグの方法 **
anthy-agentは標準入力でユーザとやりとりすることを
利用して次のようなスクリプトを書きます．
--
#! /bin/sh

anthy-agent <<EOF
aho
(space)
 PRINT_CONTEXT
EOF
--
このスクリプトを実行すると手元のanthyでは次のような出力が得られます．
--
(2 ((UL) "あほ" -1 -1) cursor)
(3 ((UL RV) "アホ" 0 3))
|あほ
あほ(アホ:(1N,256)22,485 ,阿呆:(1,256)22,357 ,あほ:(1N,256)22,229 ,):
--
これはemacsでahoと入力して変換動作をする(スペースを押す)操作をしたあとで
コンテキストを表示するコマンドを入れています．

出力の1行目と2行目はプリエディットの変化を表しています．
3行目と4行目はPRINT_CONTEXTの結果です．

 文全体   -> |あほ
 一文節目 -> あほ(アホ:(1N,256)22,485 ,阿呆:(1,256)22,357 ,あほ:(1N,256)22,229 ,):

各候補は   変換結果:(候補のタイプ,文節構造のスコア)文節のスコア
という形式をしています．

anthyのソース中にはanthy_print_*() 系の関数がコメントアウトされている部分が
たくさんあるので，それを有効にして同じことをやると変換パイプラインでどんな
データが流れるかがわかると思います．

ちなみに，デバッグプリントなどを有効にしてmake installすると
anthy.elとのプロトコルに反するので注意しましょう．
