Mercurial > freewnn
view Wnn/manual/intro @ 23:e1aadb6dcbd4
- fixed the build rule for build_stamp.h. keywords in template for hg tip should surrounded by curly braces instead of hash marks.
- fixed usage of libtool in building jlib.V3. newer libtool does not work without mode specifier.
- replaced some libtool related files. (should remove these?)
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Fri, 23 Jan 2009 16:36:13 +0900 |
parents | bbc77ca4def5 |
children |
line wrap: on
line source
Wnn V4 について 0,序 Wnnのバージョン4について、バージョン3からの変更点を中心にまとめて おきます。一応、バージョン4.0について述べますが、これからのバージョ ンアップでどのようなことが計画されているかといったことも述べます。 変更点は、主に、次の4つの領域に分けられます。 (1) 変換 (2) 辞書 (3) ライブラリ (4) アプリケーション (1) 変換アルゴリズムの改良は、今回のバージョン・アップの中心課題でした。 これまで、Wnnでは、接頭語、接尾語、助数詞などに対する処理があまいこ とが指摘されてきました。これを解決するために、今回のバージョンでは、大 文節という概念を導入し、接頭語、接尾語、助数詞などを、本体となる文節と 合わせて一つの大文節とみなして変換を行ないます。これについては、後で詳 しく述べます。 (2) 辞書に関しては、以下の点について変更されました。 ●辞書の読みに、2 バイトコードを許す。 ●自立語の品詞の種類を増やす。 ●ユーザ・形式、システム・形式の間の差違を、単語登録可能かどうか の点だけに留める。(それに伴い、名前も、登録可能形式、固定形式とする。) ●辞書ファイル、頻度ファイルにパスワードを設ける事により、辞書、頻 度の更新が可能な人を制限する。それにより、辞書の大きさを問題にしなけれ ば、登録可能形式のみを用いて辞書の管理を行なえるようにする。 ●atou, atos, utoa, stoa というコマンドを、atod (テキスト to 辞書)、 dtoa (辞書 to テキスト) にまとめ、登録可能形式、固定形式の選択を、オプシ ョンで行なう。 ●変換方式の変更に伴う変更を、付属語ファイルにくわえる。 ●付属語ファイルをクライアント毎に指定することを可能にする。 ●辞書の upload, download の機能を加える。 (3) 今までのライブラリは、サーバ内でクライアントの変換の状態を記憶し ていたので、「連文節変換をする」、「ある文節の次候補を取る」、「文節の 区切りを切り直して変換を行なう」、「頻度の更新を行なう」といったプリミ ティブで編集を行なってきました。しかし、これは、変換の流れを一つ固定し ているため拡張性に乏しいと思われます。実際に、幾つかのアプリケーション では、ここで提供している以外の操作を行なうために、このプリミティブの上 に新しいライブラリを独自に作って、それを用いています。しかし、ここで提 供しているプリミティブが一つの変換の流れを仮定した比較的高機能なもので ある以上、どうしても無理が生じてきます。実際、頻度の更新が正確に行なわ れないなどの障害が出てきています。 そこで、 ●これらの操作を、よりプリミティブな操作である、「読みとなる文字列に 対して連文節変換を行ない第一候補を返す」、「読みとなる文字列に対して単 文節変換を行ない第一候補を返す」、「読みとなる文字列に対して単文節変換 を行ない全ての候補を返す」、「ある辞書エントリの頻度値をある値にセット する」といった操作に分け、低レベル・ライブラリとして提供する。 ●より高機能な操作は、高レベル・ライブラリとして、低レベル・ライブラ リを用いて構成し、Cライブラリの形で提供する。そのライブラリと異なる操 作を行ないたい場合は、低レベル・ライブラリを用いて自分でライブラリを作 ることを可能にする。 という方針で、ライブラリを設計することにしました。 また、変換に用いる辞書セット、付属語辞書、パラメーターなどの設定は、 クライアントごとに持つのではなく、サーバ内に「環境」というものを設け、 それに対して設定を行なうことにより、一つのクライアントが複数の環境を用 いたり、一つの環境を複数のクライアントが用いたりすることを可能にしまし た。 これらの変更により、サーバ内に、クライアントの変換の状態、辞書の状 態などを持つ必要がなくなり、サーバがステートレスになりました。 変換アルゴリズムの変更にともない、ライブラリの返す情報の構造は、V3 と かなり異なっています。その点を含めて、低レベル、高レベル・ライブラリを 用いる時の注意点について、後にふれます。 (4) アプリケーション 現在までは、開発者側で用意するアプリケーションは、フロントエンド・プ ロセッサwnn のみでしたが、今回は、wnn をバージョン4用に書き換えた uum に加えて、gmw ウィンドウ・システムの中から、直接Wnnの機能を用いるた めのg言語 Wnn インターフェース、および、それを用いた仮名漢字変換機能 付のストリング・フォルダなど(このシステムは、総称して WoG と呼ばれ ている)を提供します。uum は、このバージョンで一応のものを提供しますが、 WoG は、もう少しかかりそうです(一応動くものは出来ている。)。 1.変換アルゴリズム V4 の変換アルゴリズムは、V3 の場合と同じく、文字列の最後から前に向かっ て文節を切り出す作業が基本となります。その際、V3 では、文節の定義とし て 文節 := 自立語一つ + 付属語連鎖 付属語連鎖 := 付属語* (ただし、自立語と付属語、付属語と付属語は接続条件を満たし、 文節内で最後の語は、ある特定の品詞の集合(文節の最後に 来ることのできる品詞の集合)に属している。) という定義をもちいていました。ここで、自立語は、辞書ファイルのエントリで あり、それぞれの自立語は、読み、自分の品詞、変換後文字列、それに頻度を 持っています。また、付属語は、付属語ファイルのエントリであり、読み、自 分の品詞、それに前にこれる品詞の集合(接続ベクトルと呼ばれる)を持ってい ます。付属語どうしの接続関係、および、付属語と自立語の接続関係は、この 接続ベクトルによってチェックされます。付属語が漢字を持っていないことに 注意して下さい。付属語が漢字を持っていないことにより、付属語連鎖がどの ような品詞の付属語から構成されているかという情報を持たなくていいので、 簡易で、高速な変換アルゴリズムを実現することができるのです。 V3 の解析では、接頭接尾語の処理、助数詞の処理は行なっていませんでし た。これらの語は、自立語として一文節を構成することにより処理されていま す。しかし、接頭接尾語をこのように一文節として取り扱っていたのでは、誤 変換が多くなることは避けられません。例えば、人名につく接尾語「さん」よ り「三」の方が評価値が高い時に、「こばやしさん」を変換すると「小林三」 となるといった誤変換が現れます。もし、「小林」が人名で、人名には「三」 より「さん」が優先的に付くという情報があれば、この種の誤変換は少なくす ることが可能だと考えられます。このような誤変換を少なくするには、文節の 定義を拡張するか、あるいは現在の方法を少し拡張し、文節間のつながり具合 を見る方法をとることが考えらます。Wnn Ver.4で採用した方法は、両者の折 中案と言えるものです。 Wnn Ver.4では、「大文節」と「小文節」と呼ばれる、二つのレベルの文節 を考えます。「小文節」の定義は、Ver.3における「文節」の定義と同等であ り、「大文節」は、小文節の列で、接続条件を満たすものと定義されます。 ここで、自立語、付属語と呼ばれているものは、我々が直感的に自立語、付属語 として理解して来たものと異なります。しかし、ここではこれらの名前を 流用する事にします。 語 := 自立語 | 付属語 小文節 := 自立語 + 付属語連鎖 大文節 := 小文節+ 付属語連鎖 := 付属語* (ただし、小文節内で、自立語と付属語、付属語と付属語は接続条件を満たし、 小文節内で最後の語は、後ろの小文節の自立語と接続条件を満たす。最後の小文 節の最後の語は、ある特定の品詞の集合(大文節の最後に来ることのできる品 詞の集合)に属している。最初の小文節の自立語は、ある特定の品詞の集合 (大文節の先頭になれる品詞の集合)に属している。) (例) 小文節、大文節の例 第 2 回の 小 文節は -- -- ---- -- ------ 小 小 小 小 小 ------------ --------- 大 大 約 123 グラムぐらいの -- ------ -------------- | | | | | 小(助数詞+付属語) 小 | (接頭数詞) 小(数詞列) お 食べ 下さい -- ---- ------ 小 小 小 ------ ------ 大 大 小文節同士の接続条件は、上で述べたように、後の小文節の自立語と前の小文節 の最後の語の間の接続条件として与えます。この情報は、それぞれの自立語毎に 持っていては情報量が大き過ぎるので、自立語品詞ごとに品詞の前端ベクトル として持つものとします。自立語品詞の前端ベクトルは、辞書ではなく、付属語 ファイルに与えます。これらは、それぞれの辞書に固有なものではなく、付属 語間の接続情報と共に指定されるべきものだからです。この意味で、付属語ファ イルという名前は不適切で、接続情報ファイルとでも名前を変えるべきかもし れませんが、「付属語ファイル」のほうが馴染みがあって、付属語ファイルを 指定するライブラリ関数名でも、set_fuzoku という名前がわかりやすいので、 この名前を引続き使うものとします。辞書の持つ情報については、基本的に Ver 3 と変わっていません。 どれが小文節になるかは、付属語ファイルによります。上に挙げた例は、現在 使っている付属語ファイルによるものです。最後の例に対して、一つの大文節 になって欲しいと要望する人もいるでしょう。これからも、自然で正確な変換 を目指して、付属語ファイルの内容は書き換えられていくでしょう。 #自立語の品詞については、後ろに続く付属語を規定するという役割と、前に続 #く小文節を規定するという役割を兼ねています。これでいいかということにつ #いて議論がありましたが、今更変えることはないでしょう... 今までの「文節」に当たるものは、この「大文節」です。この定義に従って 大文節を切り出した後は、基本的には、Ver.3 と同様な操作を行ないます。す なわち、大文節を n 個切り出してきて、それらの評価値の和が最大なものの 最後の大文節を確定するという動作を、文字列の前端に来るまで繰り返すので す。今まで文節の評価値を計算していたところが、「大文節」の評価値を計算 することになるのですが、パラメータの数は、Ver.3 よりずっと多くなり、 パラメータの定め方が結構大変で、四苦八苦しています。しかし、パラメータ の定め方いかんで、かなり良い変換が得られそうです。 (興味のある方は、パラメータをいじって遊んで下さい。) あと、変換に関して、細かい点が色々変わっていますが、そのなかでも 数字に対する変換が、面白いです。 たとえば、「2456」を変換すると、2456 が返ってきて、次候補として、 2456 2456 二四五六 二千四百五十六 2,456 2,456 弐阡四陌伍拾六 が返ってきます。ここで、二千四百五十六 を選択すると、次に 123 などの数 字を変換した時に、百二十三 が返ってくるという具合に、どの形式で以前選 択されたかを内部的に記憶しています。また、アスキ文字も、a を変換したら a も返ってくるという具合に、半角、全角間の変換をサポートしています。 (以前選択された値のセットは、頻度値の設定のライブラリで行ないます。) また、pubdic の付属語ファイルでは、(現在のところ、)数詞同士がつながっ て大文節を作るようになっています。ですから、「ごじゅうに」を変換すると、 「五十二」という大文節になります。 2.辞書 今までは、辞書に、読みとして許される文字の字種がかなり制限されていま した。一方で、読みに任意の2バイトコードを許すようにすれば、漢字仮名変 換の可能性が出てきます。漢字仮名変換は、音声合成と組み合わせれば、文章 の「自動読みあげ」に応用できます。また、フリガナをつけたり、索引などを 読みの順にソートしたり、一度変換したものを再変換したり、あるいは、実際 に存在する文章からバッチ式に頻度を集めたり、応用範囲の広い技術です。 Ver.4 では、読みを 2 バイトで扱っています。よって、読みの部分と漢字 の部分をひっくり返した辞書を作ることによって、漢字仮名変換を行なうこと ができます。実際に漢字仮名変換に使ってみた結果では、かなりの正確さでで 変換されました。 #辞書に関しては、現在、uum, WoG などは、かな漢字変換用の環境と、漢字 #かな変換用の環境をつくって、それぞれにかな漢字変換、漢字かな変換の辞書 #を設定して、環境を切り変えていますが、この場合、かな漢字変換の辞書を追 #加した時に、漢字かな変換の辞書も追加する必要があります。また、単語登録 #した場合にも、逆変換用の辞書にも単語登録する必要が出てきます。これらの #ことは、WoG では、自動的に行なうように出来ていますが、uum はそこまで真 #面目に作っていません。このように、辞書と逆変換辞書の間の統一をとるのは、 #困難です。さらに、辞書と逆変換辞書の間で頻度を共有できないなどの問題点 #があります。 #そこで、一つの辞書に、読みからのインデックスと漢字からのインデックスを #両方つけようという計画があります。これは、辞書のサイズが大きくなるのと、 #変換のスピードがやや落ちるというトレードオフが問題ですが、時間があれば、 #やりたいと思っています。 自立語品詞の種類は、今まで 32 個に制限されていましたが、これは、256 まで拡張されました。それに加えて、複合品詞をほぼ無制限に定義することが できます。これらの品詞に関する情報は、品詞ファイル (/usr/local/lib/wnn/hinsi.data)に書かれています。自立語の品詞は、サー バが用いるだけではなく、辞書を作る時、辞書をテキストに戻す時などに必要 になる情報です。また、クライアントも、単語の品詞に関する情報を表示する 時、単語登録で品詞を指定する時などに必要となる情報です。これらの品 詞に関する情報は、クライアントからは、ライブラリを用いてサーバに聞くこ とにより得られます。しかし、atod, dtoa などの辞書ユーティリティプログ ラムは、直接品詞ファイルを読みにいきます。 付属語ファイルを書くためには、新しい自立語品詞が必要になることが多々あ るでしょう。かといって、勝手に書き換えられては困るものです。ユーザごと に持てるようにすればいいかも知れませんが、辞書を用いる時に、異なる品詞 情報を元に作られた辞書を混ぜて使うことはできないため、かえって混乱をき たすことになります。そのような複雑なものは、管理し切れないと思われます。 そこで、「品詞ファイル」(/usr/local/lib/wnn/hinsi.data)は、世の中に一 つだけ存在するということにしました。品詞ファイルに対しては、エントリの 追加は認めるが、削除、並べ変えは認めません。品詞ファイルは、以下のよう に、品詞、複合品詞の情報を書き並べた単純な構造をしています。 .... .... 名詞 人名 地名 人地名/人名:地名 ;人名, 地名 .... .... #jserver を複数動かす事、あるいは、辞書ファイルや付属語ファイルを書き変 #えるために、品詞ファイルも各サイトで書き変えていくことを考えると、品詞 #ファイルの管理は、一つの課題となってきそうです。また、atod, dtoa など #を動かそうとすると、品詞ファイルがあるpath に存在していなくてはならず、 #問題となります。(atod, dtoa もjserverと通信した方がいいのかも知れませ #ん。) # # そこで、現在のところ、それぞれの辞書ファイルや付属語ファイルに品詞ファ #イルの情報を持たせようという計画があります。品詞名と、品詞番号の対応関 #係は、各辞書ファイルや付属語ファイルが持ちます。そして、辞書を読み込む #時に、jserver 内の番号と対応付けを行なって、辞書による、品詞番号と品詞 #名との対応関係の違いを吸収しようというものです。これは、辞書の読み込み #時の処理が多くなって、クライアントの立上りが遅くなるという欠点と、辞書 #のサイズが少し大きくなるという欠点がありますが、非常に有望な方法だと思 #います。次のリリースまでには、実現したい機能です。 今までは、ユーザ形式、システム形式の2種類の辞書を用いていました。前 者は、単語登録可能だけど、頻度ファイルを外部に持つことができない形式で、 後者は、単語登録はできないけれど、頻度ファイルを外部に持つことができ、 同じ語数の場合、辞書を小さく作ることができる形式でした。しかし、ユーザー 形式の辞書が頻度ファイルを外部に持つことを可能にするのは技術的に決して 難しい問題ではなく、そうすることにより、辞書の大きさが比較的問題になら ないサイトでは、辞書の形式としては今までユーザ形式の辞書と呼ばれていた もの1種類だけで済むようになります。そこで、Ver.4 では、今までユーザ形 式の辞書と呼ばれていたものに対して、頻度ファイルを外部に持つことを許し ました。 こうなると、ユーザ形式、システム形式という名前は不適切です。そこで、 今までユーザ形式と呼ばれていたものは登録可能形式、システム形式と呼ば れていたものは固定形式と名前を改めました。ユーザ形式の辞書が広く使わ れることを考え、辞書の内部形式も、辞書を引くのが早くなるような変更を加 えてあります。また、今まで存在した語数などに対する制限はほとんどありません。 ただ、漢字文字列が(外部UJISで)255バイト以内という制限は残っています。 辞書の大きさは、今までとほとんど変わっていないと思います。 辞書 kihon_1 語数 59,717 テキスト形式 1,567,388 旧ユーザ形式 1,783,214 旧システム形式 956,294 登録可能形式 1,735,680 固定形式 1,190,742 登録可能形式の辞書を皆で共有することにより、辞書の内容に「バグ」があっ た時に、動的にバグを修正することができます。今までだと、一旦テキスト形 式に直して、バグを直して、それを再びインストールするという手続きを踏ま なくてはならず、面倒なばかりか、それをすると、今まで個人が持っていた頻 度ファイルがすべて使えなくなるという非常に不便な状態にあったわけです。 ただ、辞書の品質を保つためには、誰でも単語の登録、削除が行なえるので は問題があります。そこで、辞書にパスワードをつけることにしました。これ によって、辞書のメンテナンスをする以外の人が、間違って、あるいは悪意的 に辞書を書き換えるということを防ぐことができます。このパスワードは、辞 書を書き換えるのを防ぐだけで、辞書を変換に用いることを制限するものでは ありません。 もちろん、個々のユーザが自分の辞書にパスワードをつけて用いることも可 能です。その時、辞書を使う度にパスワードを打ち込むのではやっていられま せん。そこで、高レベル・ライブラリでは、初期化ファイルの辞書指定のとこ ろでパスワードの入っているファイル名を指定することにより、ライブラリが そのファイルを読んで、パスワードをサーバに送るようになっています。後は、 UNIX ファイルシステムの read permission でパスワードの入ったファイルを 保護すれば良いのです。辞書と同様に、頻度ファイルもパスワードを付けられ るようになっています。パスワードの入ったファイル名は、高レベル・ライブ ラリでは、V3 の wnnrc に相当するものをパースして、辞書などのの初期設定 をするものが存在するのですが、その初期化ファイルの中で、パスワードファ イル名を指定できるようになっています。ですから、uum では、通常の使用で は、パスワードを入力する必要は生じません。 #辞書のパスワードについては、辞書をちゃんと管理するためには必要がある #と思ってつけましたが、実際には、そんなめんどくさいもの誰も使わないで #しょう。:-) Wnnでは、頻度ファイルの他に、辞書の内部にも、頻度情報を一組持って います。この頻度情報は、旧バージョンでは、ユーザ形式辞書では頻度として、 システム形式辞書では、頻度ファイルを作る時の初期値として用いられていま した。すなわち、新しく頻度ファイルを作った時には、辞書内の頻度部分の内 容をコピーして、頻度の初期値としていました。しかし、これでは、後で頻度 を集めてテキスト形式の辞書に戻そうとした時に、頻度値の集計が難しくなり ます。また、頻度値として、もともとの値と自分が使った値と別々に見たいと いう要求もあるでしょう。そこで、Ver.4 では、頻度ファイルを新しく作った 時には、すべての項目の頻度値が 0 であるような頻度ファイルを作り、頻度 値として、辞書内の頻度値と頻度ファイルの頻度値を足したものを用いること にします。 自分一人しか使わない辞書の場合、頻度ファイルを辞書の外部に作るのは無 駄です。また、複数の人で同じ頻度を用いる場合にも、頻度は辞書内にあった 方がいいでしょう。そういうわけで、頻度ファイルを指定せずに辞書を用いる と、辞書内の頻度を用い、それを更新するようになっています。ディスクの容 量が足りないなどの理由で、頻度ファイルを共有する場合に、楽になります。 また、pubdic などで集計した頻度を、元となる頻度として反映する場合に、 個々のユーザの頻度ファイルを作り直さなくても、辞書内頻度を用いる状態で 辞書を読み込んで、頻度値変更のライブラリを使って頻度値を新しい値にセッ トし直すことが可能になります。一つの辞書に対して、辞書外に頻度ファイル を作って使用するという使用法と、辞書内の頻度を用いるという使用法を併用 するのは、一般には望ましい使い方ではありません。そのようなことを防ぐた めに、辞書の頻度部分にもパスワードをつけることが可能になっています。そ れによって、(パスワードが一致しない場合、)頻度ファイルを指定せずに、頻 度を更新するモードでその辞書を使用する事が不可能になります。 # pubdic プロジェクトが、Wnn V4 で、どのような形態で辞書を管理してい #くのかは、私は知りません。 誰にも使うことのできないパスワード(辞書を作る時に、atod -n -N で事が出 来ます)が辞書本体、辞書頻度部分についている場合、 辞書本体 辞書頻度部分 パスワード有 パスワード有 頻度ファイルを用い、登録不能 パスワード無 パスワード有 頻度ファイルを用い、誰でも登録可能 パスワード有 パスワード無 頻度は共有、登録はできない パスワード無 パスワード無 頻度は共有、誰でも登録可能 といったところでしょうか。もちろん、頻度部分にパスワードがついてなくて も、頻度ファイルを辞書外部に作って辞書を用いることは可能ですし、パスワー ドの無い辞書でも、今までとおり、辞書本体、あるいは頻度部分をリード・オ ンリーで用いることもできます。 頻度については、新しく、頻度値を用いてエントリの一時的削除を行なうこ とを可能にしました。すなわち、頻度値をある値にセットすれば、そのエント リーは、変換の時に用いられないというものです。このある値は、ライブラリ では(実頻度) -1(WNN_ENTRY_NO_USE) になっています。頻度ファイルを指定し ていない場合には、辞書内頻度値がこの値ならば、また、指定している場合に は、頻度ファイル値もしくは辞書内頻度値のどちらかがこの値ならば、そのエ ントリは、一時削除されたことになります。これによって、皆で共有して使用 している辞書に自分にとって不適当な単語が存在している場合に、それを変換 の対象から除外することができます。テキスト形式では、削除されたエントリ は頻度の部分が "-" で示されます。テキスト形式で、エントリを消す時に、 コメントアウトなどの方法で実際に消してしまうと、atod で辞書を作ってそ れを dtoa で再びテキストに戻した時に、エントリーが消えてしまいます。頻 度部分を "-" にする事により消したエントリは、実際に消えたわけではあり ませんから、辞書の内容を編集する時に、便利です。高レベル・ライブラリで は、エントリの一時削除のためのライブラリ関数が用意されています。 Ver.4 では、辞書にコメントを付けることが出来るようになっています。 (コメントというより、ニックネームと言った方がいいかも知れません)uumで は、これを、単語登録などの時の辞書名の指定に用いるようにしています。 usr/pubdic/pd-chimei といった辞書名を見ながら登録する辞書を選ぶよりも、 「地名辞書」といったニックネームを見ながら登録する辞書を選べた方が便利 なのは、理解していただけるでしょう。 また、コメントは、各辞書エントリにつけることも可能となっています。これ は、テキスト形式に直して辞書を編集する時も見えますので、辞書の編集時に 便利だと思われます。 辞書のパスワード、コメントなどは辞書の作成時に指定しますが、すでに存在 する辞書に対して、これらの部分を書き換えるコマンドが用意されています。 これは、今のところ、新バージョンのgmw上で動くように作ってあります。 いままで atou, atos, utoa, stoa と呼ばれていたコマンドは、atod (テキ スト to 辞書)、dtoa (辞書 to テキスト) の二つにまとめられています。登 録可能形式、固定形式の選択は、atod のオプションで行ないます。 辞書のテキスト形式に対しても、見やすさの観点から変更が加えられていま す。品詞は数字ではなく、品詞名が現れます。頻度値として、圧縮された値で はなく、実際の使用頻度(に近い値)が出されます。atod を行なう時に辞書を ソートし直すので、テキスト形式の辞書を作成する時には、辞書項目はどのよ うな順でも構いません。これにより、テキスト形式の辞書の編集がしやすくな ります。dtoa は、読みの順にソートされた形で出力します。 付属語ファイルは、jserver 内に一つ存在するのではなく、環境毎 に設定できるようになりました。環境については、ライブラリの項を参照して 下さい。 #これによって、名簿などを入力している時には付属語がつながらないような #状態で入力するだとか、手紙文を入力している時には大阪弁などの口語も入っ #た付属語ファイルを用いるといった設定が可能になります。残念ながら、現在 #の uum や WoG では、この機能を簡単に利用できるようにはなっていません。 #将来への課題です。 変換方式の変更にともない、付属語ファイルの内容、および、atofコマン ドも変更を受けています。このことについては、ここでは省略します。 辞書をクライアントからupload、downloadする機能が付け加 えられます。これにより、ユーザの個人の辞書や頻度ファイルを、自分のホー ムディレクトリの下に置くことが可能です。jserver は、ファイルの同一性の チェックを厳しくやっているので、nfs でマウントされた同一の辞書を二つの 計算機から upload しても、jserver 内では一つのファイルとして扱われます。 # WoG では、デフォルトの設定で、ユーザのホームディレクトリの下にユー #ザ毎の辞書や頻度ファイルは置かれるようになっています。 3. ライブラリ Ver.4 では、ライブラリとして、jserver との通信と基本的に1対1に対応し ている低レベル(js)ライブラリと、jsライブラリを用いて作られた、高レベ ル(jl)ライブラリがあります。 低レベル・ライブラリは、細かいプリミティブから構成され、高レベル・ライ ブラリは、仮名漢字変換の流れに沿った高レベルの処理を実現しています。例 えば、変換に関しては、jsライブラリでは、 読みに対して、連文節変換をした第一候補を返す(kanren) 読みに対して、単文節変換をした第一候補を返す(kantan_dai, kantan_sho) 読みに対して、単文節変換をした全候補を返す (kanzen_dai, kanzen_sho) あるエントリの頻度値をある値にセットする(hindo_set) といった関数が基本となります。 これに対して、jlライブラリは、変換の履歴を文節の列として持っており、 読みを与えて、連文節変換をする(ren_conv) 文節の区切りを変えて変換し直す(nobi_conv) ある文節の次候補を返す。(zenkouho, zenkouho_dai) (変換の履歴に基づいて)頻度値の更新を行なう(update_hindo) といった関数が基本となります。 低レベル・ライブラリの関数は、js_ ではじまる名前を持っており、高レベル・ ライブラリの関数は、jl_ ではじまる名前を持っています。ここでは、まず、 低レベル・ライブラリについて説明し、その後に、高レベル・ライブラリにつ いて説明します。 3.1 低レベル・ライブラリ まず、低レベル・ライブラリにおいて使用される以下の概念について、まとめ ておきます。 クライアント 環境 ファイル 辞書No. ●クライアント jserver と通信路を持つアプリケーション・プログラムのことをクライアン トと呼びます。複数の計算機上で jserver が動いている時に、一つのプログ ラムは、複数の jserver のクライアントに同時になることが出来ます。 ●環境 仮名漢字変換の実行結果は、使用する辞書と頻度ファイル、使用する付属語 ファイル、あるいは、変換パラメータの設定といったものによって、変わって きます。これらの設定は、jserver 内に「環境」と呼ばれるものを作り、それ に対して行ないます。そして、変換の操作は、引数として読みの文字列と共に、 環境を指定して行ないます。 一つのクライアントは、jserver 内に複数の環境を作り、変換の度に異なる 環境を用いることができます。また、一つの環境を複数のクライアント間で共 有することも可能です。その時には、その環境に対する辞書追加などの操作は、 その環境を使用している他のクライアントにも反映されます。 環境は jserver 内に作られるものですが、js_ライブラリでは、jserver id と その jserver 内の環境の idのペアを環境としています。ですから、環境 の指定は、変換を行なう jserver の指定を含んでいます。 ●ファイル Wnn においては、辞書ファイルなどのファイルを jserver 内に読み込む動 作と、ファイルを辞書として用いるなどといったファイルの使用を開始する動 作は、区別されています。それは、jserver が用いるファイルには、辞書ファ イル、頻度ファイル、付属語ファイルといった種類があり、種類ごとに使用方 法は異なるのですが、ファイルとしての動作(メモリ上への読み込み、書きだ し、使用されていないファイルをメモリ上から捨てる)は、どの種類のファイ ルであっても共通だからです。特に、ファイルの読み込み、書き出しに関して は、jserver が直接行う場合と、クライアントが読み込んで jserver に送信 する(あるいは、逆に、jserver から受信してクライアントのファイルシステ ムに書き込む)場合があります。クライアントのローカルからの送信か、サー バーのファイルシステムからの読み込みかをファイルの種類ごとに、ファイル の使用開始時に指定するのより、ファイルの読み込み、送信を一つのプリミティ ブとした方が明確だろうという趣旨です。 高水準ライブラリでは、ファイルの作成と読み込みと使用を一つにまとめたラ イブラリ関数群が用意されています。 ●辞書No. 辞書は、頻度ファイルを指定して使用することも、指定せずに使用すること もできます。ですから、環境にセットするのは、辞書と頻度ファイルの組、ま たは、辞書だけです。環境に辞書をセットする事によって ID が返されますが、 この ID を 辞書No.と呼びます。 辞書No.に付随する情報として、辞書ファイル、頻度ファイルの他に、辞書 のプライオリティ、辞書のenable/disable、辞書、頻度の書き込み許可の情報 があります。 ○簡単な例を通した低レベル・ライブラリの説明 以下、かな漢字変換、及び、漢字かな変換を行なう簡単なプログラムを例とし て、低レベル・ライブラリの使い方を説明します。 #変換関係のライブラリの引数や、パラメータの個数は、配布開始までに 変更されるかもしれないので、このままでは、動かないかもしれません。 ------------------------------------------------- #include <stdio.h> #include "jslib.h" /*#include "commonheader.h" */ #define FZK_FILE "/usr/local/lib/wnn/dic/pubdic/full.fzk" #define KIHON_DIC "/usr/local/lib/wnn/dic/pubdic/pd-kihon.sys" #define SETTO_DIC "/usr/local/lib/wnn/dic/pubdic/pd-setsuji.sys" #define REV_DIC "/usr/local/lib/wnn/dic/pubdic/pd-kihon.sysR" #define REV_DIC_SETTO "/usr/local/lib/wnn/dic/pubdic/pd-setsuji.sysR" WNN_JSERVER_ID *js; struct wnn_env *env, *rev_env; static struct wnn_ret_buf rb = {0, NULL}; int dcnt,scnt; char yomi[1024]; char kanji[5000]; int kihon_file, setto_file, rev_file, fzk_file, rev_setto_file; int kihon_dic_no, setto_dic_no, rev_dic_no, rev_setto_dic_no; main(argc, argv) int argc; char **argv; { char *mname = ""; rb.buf = (char *)malloc((unsigned)(rb.size = 0)); if(argc > 1) mname = argv[1]; if((js=js_open(mname)) == NULL) err(); if((env=js_connect(js, "kana")) == NULL) err(); if((fzk_file = js_file_read(env,FZK_FILE)) == -1) err(); if((kihon_file = js_file_read(env,KIHON_DIC)) == -1) err(); if((setto_file = js_file_read(env,SETTO_DIC)) == -1) err(); if(js_fuzokugo_set(env,fzk_file) == -1) err(); if((kihon_dic_no = js_dic_add(env,kihon_file,-1,1,WNN_DIC_RDONLY, WNN_DIC_RDONLY, NULL, NULL)) == -1) err(); if((setto_dic_no=js_dic_add(env,setto_file,-1,1,WNN_DIC_RDONLY, WNN_DIC_RDONLY, NULL, NULL)) == -1) err(); p_set(env); if((rev_env=js_connect(js, "kanji")) == NULL) err(); if((fzk_file = js_file_read(rev_env,FZK_FILE)) == -1) err(); if((rev_file = js_file_read(rev_env,REV_DIC)) == -1) err(); if((rev_setto_file = js_file_read(rev_env,REV_DIC_SETTO)) == -1) err(); if(js_fuzokugo_set(rev_env,fzk_file) == -1) err(); if((rev_dic_no = js_dic_add(rev_env,rev_file,-1,1,WNN_DIC_RDONLY, WNN_DIC_RDONLY, NULL, NULL)) == -1) err(); if((rev_setto_dic_no = js_dic_add(rev_env,rev_setto_file,-1,1,WNN_DIC_RDONLY, WNN_DIC_RDONLY, NULL, NULL)) == -1) err(); p_set(rev_env); #ifdef DEBUG printf("Now discard file push any key\n"); getchar(); js_file_discard(rev_env, rev_file); printf("Now discard file\n"); #endif henkan(); js_close(js); } henkan() { wchar u[1024]; struct wnn_env *c_env = env; struct wnn_dai_bunsetsu *dp; for(;;){ if(c_env == env){printf("yomi> ");fflush(stdout);} else {printf("kanji> ");fflush(stdout);} if(gets(yomi) == NULL)return; if(yomi[0] == '!')return; if(yomi[0] == '@'){ c_env = (c_env == env)? rev_env:env; continue; } strtows(u,yomi); dcnt =js_kanren(c_env,u,WNN_BUN_SENTOU, NULL, WNN_VECT_KANREN, WNN_VECT_NO,&rb); dp = (struct wnn_dai_bunsetsu *)rb.buf; print_kanji(dp,dcnt ); } } print_kanji(dlist, cnt) struct wnn_dai_bunsetsu *dlist; int cnt; { int i; struct wnn_sho_bunsetsu *sbn; if (dlist == 0) return; putchar('\n'); for ( ; cnt > 0; dlist++, cnt --) { sbn = dlist->sbn; for (i = dlist->sbncnt; i > 0; i--) { putws(sbn->kanji); printf("-"); putws(sbn->fuzoku); printf(" "); sbn++; } printf("|"); } putchar('\n'); fflush(stdout); } p_set(env1) struct wnn_env *env1; { struct wnn_param pa; pa.n= 2; /* n_bun */ pa.nsho = 10; /* nshobun */ pa.p1 = 2; /* hindoval */ pa.p2 = 40; /* lenval */ pa.p3 = 0; /* jirival */ pa.p4 = 100; /* flagval */ pa.p5 = 5; /* jishoval */ pa.p6 = 1; /* sbn_val */ pa.p7 = 15; /* dbn_len_val */ pa.p8 = -20; /* sbn_cnt_val */ pa.p9 = 0; /* kan_len_val */ js_param_set(env1,&pa); } putwchar(x) unsigned short x; { putchar( x >> 8); putchar( x ); } putws(s) unsigned short *s; { while(*s) putwchar(*s++); } strtows(u,e) wchar *u; unsigned char *e; {int x; for(;*e;){ x= *e++; if(x & 0x80) x = (x << 8) | *e++; *u++= x; } *u=0; } err() { printf(wnn_perror()); printf("\n bye.\n"); exit(1); } このプログラムの実行例を示しておきます。 % kankana yomi> だいぶんせつは、しょうぶんせつのれつで、せつぞくじょうけんをみたすものと ていぎされます。 大- 文節-は、 |小- 文節-の |列-で、 |接続- |条件-を |満た-す |もの-と |定義-さ れます。 | yomi> このぷろぐらむのじっこうれいをしめしておきます。 この- |プログラム-の |実行- 例-を |示-しておきます。 | yomi> @ kanji> 大文節は、小文節の列で、接続条件を満たすものと定義されます。 おお- ぶんせつ-は、 |こ- ぶんせつ-の |れつ-で、 |せつぞく- |じょうけん-を |み た-す |もの-と |ていぎ-されます。 | kanji> このプログラムの実行例を示しておきます。 この- |ぷろぐらむ-の |じっこう- れい-を |しめ-しておきます。 | > ^D ------------------------------------------------- プログラムの説明 このプログラムを用いで、低レベル・ライブラリの使い方について説明します。 #include "jslib.h" include/jslib.h には、jsライブラリで用いる構造体、マクロなどの定義が なされています。ライブラリで提供する関数名、構造体名、マクロ名は、 "js_*" または、"wnn_*" (高レベル・ライブラリでは "jl_") という名前をつ けていますので、名前の衝突が起こらないように注意して下さい。 static struct wnn_ret_buf rb = {0, NULL}; rb.buf = (char *)malloc((unsigned)(rb.size = 0)); 今までのライブラリでは、変換などの変値を入れる領域は、ライブラリを呼ぶ 側で用意し、その領域に入り切らない場合には、エラーになりました。一般に、 ライブラリを用いる側で、どれだけの領域が必要かはわからないので、大きな 問題となります。そこで、Ver.4 では、必要があれば、ライブラリの側で reallocを行なうという仕様になっています。不定長の変値を返す関数は、 (struct wnn_ret_buf *) の引数を取ります。このポインタの先には、malloc または realloc で取られた領域と、その大きさのペアが与えられる必要があ ります。 if((js=js_open(mname)) == NULL) err(); この一行で、jserver との通信路を設立し、jserver のクライアントになりま す。mname には、jserver の存在する計算機名が与えられます。計算機名として ヌル・ストリングが与えられた時には、UNIX ドメインの通信を行ないます。 js_open は、返値として、jserver_id を返します。この通信路は、js_close をによって明示的に切断するか、プログラムが終了するまで有効です。 if((env=js_connect(js, "kana")) == NULL) err(); 次に、js_connect により、環境を jserver 内に作ります。どの jserver 内 に環境を作るかは、引数で jserver_id を渡すことにより指定します。 "kana" は、環境名です。js_connect は、同じ環境名を持つ環境が jserver 内存在する時にはその id を返しそれ以外の時には新しく環境を jserver 内 に作り、その id を返します。環境名は、複数のプロセスで一つの環境を共有 するために用います。すなわち、他のプロセスが同じく "kana" という環境名 を引数としてjs_connect を呼んだ場合、そのとき得られる環境は、ここで 作られたものと同じです。他のプロセスと共有することの無い環境(間違って、 共有されたくない環境)を作りたい場合がありますが、その場合には、第一引 き数として空文字列を渡してやります。それにより、jserver は常に新しい環 境を作り、それを返します。その場合、返されてきた環境が、共有されること はありません。 環境の使用を終るには、js_disconnect を用います。また、通信路が閉じられ た時には自動的に環境の使用を終えます。環境は、その環境を用いているクラ イアントがなくなった時に、jserver 内からなくなります。以下のライブラリ 関数では環境を引数としたものが多く存在しますが、それらの環境は、 js_connect でそのプロセスが受け取ったものである必要があります。それは、 他のプロセスに勝手に環境に対してアクセスされることを防ぐためです。 if((fzk_file = js_file_read(env,FZK_FILE)) == -1) err(); if((kihon_file = js_file_read(env,KIHON_DIC)) == -1) err(); if((setto_file = js_file_read(env,SETTO_DIC)) == -1) err(); ここで、付属語ファイル、および辞書を jserver に読み込んでいます。 js_file_read は、そのファイルが jserver 内に存在しない時には、ファイル jserver 内に読み込みその Fid(ファイル ID) を返し、jserver 内に既に存在 している時にはその id を返します。また、js_file_send は、クライアント・ サイトのファイルを読み込むのに使用します。jserver は、ファイルの同一性 のチェックを厳密に行なっていますので、クライアントとサーバから同一のファ イルを読み込んだとしても、同一のファイルがメモリー上に二つ以上存在する ことはありません。js_file_read, js_file_send を行なうことにより、ファ イルは環境に接続されます。Fid は、jserver 内でユニークに存在するもので すが、そのファイルに対してアクセスするためには、ファイルが接続された環 境を持っている必要があります。js_file_send, js_file_receive は、現在の バージョンでは、まだサポートされていません。 jserver のサイト上のパス名の指定は、フルパスで指定するか、JSERVER_DIR と呼ばれるディレクトリからの相対で指定するかします。JSERVER_DIR は、 jserverrc の中で指定されています。 jserver 内に読み込まれたファイルは、js_file_discard によって、環境か ら切り離されます。また、環境が先に消滅すれば、自動的にその環境から切り 離されます。そして、ファイルに対して接続している環境が無くなった時、そ のファイルは jserver 内から消滅します。ファイルによっては、jserver が 読み込んでいる間に内容が更新されているため、その更新された内容をファイ ル・システムに書き戻す必要が出てきます。それを行なうのが、js_file_write, js_file_receive です。 js_file_write, js_file_receive で、読み込んだファイルと異なるファイル に書き出すことが可能です。その場合には、ファイルがすでに存在していれば、 それが wnn のファイルの場合のみ、上書きされます。 # js_file_write, receive が明示的に呼ばれた時以外に、ファイルが #jserverないから消滅する時に自動的に書き戻しを行なってはどうかという意 #見もあったが、クライアント・サイトのファイルの場合には不可能なので、 #しない。 この他に、ファイルに関するライブラリとしては、js_file_list (環境に接 続されているファイルの情報一覧を得る)、js_file_list_all (jserver に読 み込まれているファイルの情報一覧を得る)、js_file_info (特定のファイル についての情報を得る。)があります。 また、アプリケーションを書くためには、jserver のあるサイトのファイル・ システムに関する情報を得る必要が生じてきます。そのために、jserver サイ ト上でのパス名を引数として取るライブラリとして js_access 指定されたファイルの(jserver に対する)アクセス権を調べる。 js_file_stat 指定されたファイルの内容(辞書、頻度ファイル。付属語ファイル の別、ファイルに付けられているコメント)を得る js_file_loaded 指定されたパス名のファイルが jserver 内に 読み込まれているかどうか調べる。 ファイルシステムに関して、始めてアプリケーションを使う人のためのユーザ 辞書や頻度ファイルを作る必要があります。そのためのライブラリとして、 js_mkdir 指定された名前のディレクトリを作る。 相対パスは、JSERVER_DIR からの相対で指定する。 指定されたところにどこでも作ってしまうので、 jserver に強い権限を与えてはいけない。 (root で走らすなどもってのほか。) js_dic_file_create 指定された名前で、語数 0 の登録可能形式の辞書を作る。 js_hindo_file_create 指定されたファイル id を持ったファイルの頻度ファイルを 指定されたパス名で作る。 js_dic_file_create_client 指定された名前で、語数 0 の登録可能形式の辞書をクライ アントサイトに作る。 js_hindo_file_create_client 指定されたファイル id を持ったファイルの頻度ファイルを 指定されたパス名で、クライアントサイトに作る。 js_file_remove Wnn のファイルをファイルシステムから消す。 があります。 if(js_fuzokugo_set(env,fzk_file) == -1) err(); これは、fzk_file という file_id で示されたファイルを env の付属語ファ イルとして設定しています。 if((kihon_dic_no = js_dic_add(env,kihon_file,-1,1,1,-1,NULL, NULL)) == -1) err(); if((setto_dic_no=js_dic_add(env,setto_file,-1,1,0,0,-1,NULL, NULL)) == -1) err(); これは、kihon_file, setto_file という file_id で示されたファイルを envの辞書として設定しています。 js_dicadd(env, file_id, hfile_id, prio, rdonly, hrdonly, passwd_file, passwd_hfile) によって、file_id で示され たファイルを、hfile_id で示されたファイルを頻度ファイルとし、prio で示 された優先度で、辞書、頻度がそれぞれ rdonly, hrdonly で示された状態で env に追加することを意味しています。頻度情報として辞書ファイルの内部に もつものを使用する場合には、第三引数で -1 を設定します。また、rdonly は WNN_DIC_RW の時、読み書き可能、WNN_DIC_RDONLY の時更新不能を意味し ています。また、辞書には、パスワードがついていることがあります(参照)。 パスワードつきの辞書、頻度を、リード・オンリーでない状態で用いたい時に は、それぞれのファイルのパスワードを第八、第九引数として与える必要が あります。dic_add は、返値として、辞書No.を返します。それ以降の辞書、 頻度ファイル関する操作は、この dic_No を用いて行ないます。付属語ファイ ルは環境に対して一つ存在するものですが、辞書は、一つの環境に複数設定し てそれら全てを変換に用います。ここでは、二つの辞書を設定しています。 環境に設定されている 辞書No.に関する情報を得るライブラリとして、 js_dic_list があります。また、辞書No.を環境から無くさずに、一時的に無 効にするためのライブラリ (js_dic_use)があります。 辞書No.を環境から外すには、js_dic_del を用います。 環境に対する設定としては、辞書、付属語ファイルの他に、変換パラメーター があります。変換パラメータに関しては、js_param_set によって設定を行な い、js_param_get によって現在の設定の状態を得ます。変換パラメータに関 しては、デフォルト値が jserverrc に書かれていて、環境が js_connect で 作られた時には、その設定が用いられます。 if((rev_env=js_connect(js, "kanji")) == NULL) err(); if((fzk_file = js_file_read(rev_env,FZK_FILE)) == -1) err(); if((rev_file = js_file_read(rev_env,REV_DIC)) == -1) err(); if((rev_setto_file = js_file_read(rev_env,REV_DIC_SETTO)) == -1) err(); if(js_fuzokugo_set(rev_env,fzk_file) == -1) err(); if((rev_dic_no = js_dic_add(rev_env,rev_file,-1,1,WNN_DIC_RDONLY, WNN_DIC_RDONLY, NULL, NULL)) == -1) err(); if((rev_setto_dic_no = js_dic_add(rev_env,rev_setto_file,-1,1,WNN_DIC_RDONLY, WNN_DIC_RDONLY, NULL, NULL)) == -1) err(); 上記のかな漢字変換用の環境とは別に、もう一つ、漢字かな変換用の環境を作 り、それに対して設定を行なっています。ここで、fzk_fileとしては、同じファ イルIDが返ってくるはずですが、fzk_file に関係するfile_read を再度行なっ ていることに注意して下さい。先程述べたように、その環境に対して file_readを先に行なっていないと、そのファイルがその環境で使えないからです。 henkan(); henkan の中身は、御覧のように、読み文字列を得て、内部 UJIS コードに変 換して、仮名漢字変換を行ない、結果を表示するというものです。jserver と の通信は、日本語のコードとして、全て内部 UJIS を用いて行ないます。 dcnt =js_kanren(c_env,u,WNN_BUN_SENTOU, NULL, WNN_VECT_KANREN, WNN_VECT_NO,&rb); これは、連文節変換を行なうライブラリ関数です。先に説明した通り、変換 の関数は、全て、環境(c_env)と、読み(u), 結果を入れる領域へのポインタ (&rb)を引数として持ちます。後の4つの引数は、変換結果に影響を与える パラメータとなるものです。 第3、4引数は、変換文字列の先頭に関する設定、 第5,第6引数は、変換文字列の終端に関する設定です。 前にも述べたように、Ver.4 では、大文節と小文節を扱います。連文節変換で は、変換の結果返してくるものは大文節の列ですが、指定の仕方によっては、 先頭の大文節および最後の大文節は、完全な大文節ではなく、大文節の部分を 返させることが可能です。それによって、前端と終端に接続条件の制約を 与えて変換を行なうことができます。 具体的には、前端の設定については、ある小文節の自立語の品詞と付属語列を第 3、第4引数で指定することにより、先頭の大文節として、その小文節とつながっ て大文節を構成する小文節列を得ることができます。前端の設定を行わない時 には、WNN_BUN_SENTOU を第3引数として指定すれば、前端が大文節の前端と なるように変換を行います。WNN_ALL_HINSI を第3引数として指定すれば、 前端が小文節の前端となるように変換を行います。この場合には、先頭の大文 節は擬似的なものとなります。 終端の設定については、ベクトル(品詞の集合)の番号を第5,第6引数に指定 することにより、最後の大文節として、そのベクトルを終端ベクトルとして解 析した結果を返します。第5引数で指定されたベクトルが優先されて探索され、 第6引数で指定されたものは、それより低い評価値として計算されます。この ように、二つベクトルを指定するのは、全候補を得る時などに、「ある品詞で 終る文節を得たいが、それが存在しない時には、他の品詞のものでもよい」と いうことが生じるからです。ベクトルとしては、jslib.h で define されてい る 3つのベクトル、WNN_VECT_KANREN、WNN_VECT_KANTAN、WNN_VECT_KANZEN、 および、 解析結果としてかえされる、各小文節の前端ベクトル(前につながる ことのできる小文節の最後の品詞) を用います。これらのベクトルの内容は、 付属語ファイルで指定されます。また、WNN_VECT_NO を第6引数に指定すると、 そのベクトルは無視されます。 具体的に、この機構がどのように使われるかを説明します。 各[i]を小文節とし、‖ を大文節の区切りとします。最初の変換で、 ‖[1][2][3]‖[4]‖[5]‖[6][7]‖[8][9]‖ という結果が得られたとします。ここで、[1],[2],および、[7]以降は正しく 変換されていて、[3] から [6] は読みを入れ間違えたために誤変換が起こっ ているとします。これに対して、[3] から [6] までの文節を解除して読みを 直して変換し直したいとします。その時、[2] の文節の情報を第3、4引数とし て与え、[7]の小文節の前端ベクトルを第5引数として与え、[3] から [6] ま での読みを与えることによって、例えば [3']‖[4'][5']‖[6'] といった文節列で、[3'] は [1],[2] とつながって大文節を構成し、[6'] は [7]とつながって大文節を構成するような変換結果が得られます。高レベル・ ライブラリは、前後の指定を自分で行なわなくても、このような変換が行え るように作られています。 最後の大文節以外の大文節の終端ベクトルは、WNN_VECT_KANREN が用いられま す。 前端の接続条件を指定して変換を行った時に、その接続条件を満たすものが無 い場合には、そこが大文節の先頭となるような結果を返します。それも存在し ない場合には、そこが小文節の先頭となるものを返します。この場合には、返 してくるものは、擬似的な大文節です。 それぞれの小文節は、その status として、前への接続状況を持っています。 status がWNN_CONNECT ならば、前の小文節に接続している、 WNN_SENTOU なら、大文節の先頭である。 WNN_NOT_CONNECT なら、大文節の先頭でもないし、前に接続もしない。 WNN_GIJI なら、擬似小文節です。 この、接続状況の設定は、大文節というものを考える限り必要ではありますが、 中々難しい所です。特に、 #現在のところ、前端の文節が前に接続する時、および、後端の文節が後ろに接 #続する時の、文節の評価値の決め方が結構いい加減です。また、疑似文節に対 #する評価値の決め方も、かなりいい加減なところがあります。それで、 #これらの文節の評価値の決め方を変更しようという計画があって、 #リリース時には、すでに、変更されているかもしれません。 #現在の所、前者の問題に付いては、前に接続する文節列は、評価値を2倍とし #て評価を進めることにより、優先して出されるようにし、大文節の先頭となら #ない小文節を先頭として解析が終了した時には、その文節列の評価値を1/2 #にして、大文節の先頭となるものが優先されるようにしています。ただし、前 #端条件として WNN_BUN_SENTOU を指定して変換した時には、前者の処理は行わ #ず、WNN_ALL_HINSI を指定して変換した時には、両方の処理を行いません。 #将来的には、変換の時に、変換文字列の前の小文節列の評価値も送ってやって、 #それを元に、前に接続する文節列の評価値を決めるようにする方向に議論が進 #んでいます。 #また、終端に付いても、同様です。 変換に付いては、js_kanren の他に、kantan, kanzen がありますが、これら も前端、終端の接続条件を指定して変換を行います。 kantan, kanzen については、kantan_dai, kantan_syo 、kanzen_dai, kanzen_syo という区別があります。kantan_sho, kanzen_sho は、与えられた 文字列が一つの小文節を成すものとして変換を行います。kantan_dai, kanzen_dai は、一つの大文節の部分を成す小文節の列を 返すように変換を行います。 頻度の更新に付いては、js_hindo_set(env,dic_No,entry,ima,hindo) (ある辞 書のあるエントリの頻度、今使ったよビットの値をある値にセットする。) を 用います。ここで、与える頻度地は、実頻度値(jserver の中で圧縮して持っ ている値ではなく、実際に使われた回数) です。今使ったよビット、頻度の値 は、別々に指定し、どちらか一方の値しか変化させない時には、もう一方の値 をWNN_HINDO_NOP としていします。頻度に付いては、値を指定してセットする だけではなく、WNN_HINDO_INC (頻度を1上げる) WNN_HINDO_DEL (頻度を1 下げる)があります。WNN_HINDO_INC をしても、内部的には頻度は圧縮して持っ ているので、必ずしも上がるとは限りません。この他に、WNN_ENTRY_NO_USE を指定すると、そのエントリは、それ以降の変換で用いられなくなります。 (マイナス無限大にセットするという感じでしょうか。) js_close(js); 最後に、js_close を呼んで、コネクションを切断しています。コネクション を切断することにより、そのコネクションから起こした全ての環境は、他のク ライアントと共有していない限りなくなり、それらの環境で読み込んだファイ ルで、他の環境から読み込まれていないものは全てメモリー上から開放されま す。 その他の低レベル・ライブラリとして、品詞関係のものがあげられます。品詞 は、品詞ファイルの中で、階層的に分類されています。階層の途中に位置する ものは、品詞の集合を表すノードで、リーフに当たるものが、本当の品詞です。 この情報は、単語登録時に、品詞を選択するのに用いられます。 現在作られている 品詞ファイルの設定では、次のようになっています。 ------------------------------------------------------------ /|普通名詞/:固有名詞/:動詞/:特殊な動詞/:動詞以外の用言/\ :その他の独立語/:接頭語,接尾語/:単漢字:疑似品詞/ 普通名詞/|名詞:サ行(する)&名詞:一段&名詞:形容動詞&名詞:数詞 固有名詞/|人名:地名:人名&地名:固有名詞 動詞/|一段:一段&名詞\ :カ行五段:ガ行五段:サ行五段:タ行五段:ナ行五段\ :バ行五段:マ行五段:ラ行五段:ワ行五段\ :サ行(する):サ行(する)&名詞:ザ行(ずる) 特殊な動詞/|カ行(行く):ラ行(下さい)\ :来(こ):来(き):来(く):為(し):為(す):為(せ) 動詞以外の用言/|形容詞:形容動詞:形容動詞&名詞:形容動詞(たる) その他の独立語/|副詞:連体詞:接続詞,感動詞 接頭語,接尾語/|接頭語:接尾語:接尾人名:接頭地名:接尾地名\ :接頭数詞:助数詞:接頭助数詞:接尾助数詞\ :形容動詞化接尾語:サ行(する)&名詞化接尾語:接尾動詞:形容詞化接尾動詞\ :接頭語(お) 疑似品詞/|数字:カナ:英数:記号:閉括弧:開括弧:付属語 ------------------------------------------------------------ 品詞に関するライブラリは、以下の3つがあります。 js_hinsi_list ノード名を引数にとり、そのノードに属する品詞名の一覧を得る。 js_hinsi_name 品詞番号から名前を取る。 js_hinsi_number 品詞名を品詞番号に変換する。 この他のライブラリについては、 js_dic_info(env,dic_No,ret) dic_No の辞書に付いての情報を得る。 js_word_add(env,dic_No,読み,漢字,品詞) dic_No の辞書No. に、単語を登録する。 js_word_delete(env,dic_No,Yomi,jisho_entry) dic_No の辞書から単語を削除する。 js_word_search(env,dic_No,読み,ret_buf) dic_No の辞書に単語検索を行う。 js_word_search_by_env(env,読み,ret_buf) 環境中の全ての辞書No.に対して単語検索を行う。 js_word_info(env, dic_No, entry, ret_buf) dic_No の辞書の entry 番目の entry について、細かい情報を得る。 js_who jserver の使用者の一覧を得る。 js_kill jserver の使用者がない時に、jserver を終了させる。 などがあります。 #ライブラリの引数は、このドキュメントを書いた時点から変更されているか #もしれないので、マニュアルの方を見て下さい。また、最近つけ加わったライ #ブラリについては、ここでは述べていません。 3.2 高レベル・ライブラリ 高レベル・ライブラリでは、ユーザの変換の履歴を「バッファ」に残すことにより、 ●それぞれの変換を行う時の前端、後端の接続条件などの設定を行う。 ●頻度更新する時に、選択されなかった語に対し今使ったよビットを落とす。 といった処理をします。また、 ●次候補列をつくり、その中からの設定の便宜を計ります。 次候補列を作る時には、最初の変換で返ってきた候補を次候補列の先頭に持っていく、 同じ候補が重複しないようにするなどの処理をおこないます。 「バッファ」は複数持つことが出来ます。その時、不必要になった環境、 jserver との通信路の破壊などの面倒も見ます。 Ver.4 では、「環境」、「ファイル」、「大文節」といった複雑な概念が存在 しましたが、高レベルライブラリではこれらの概念について知らなくてもライ ブラリを用いたプログラムが組めるようになっています。もちろん、大文節、 環境などを直接扱いたい場合には、扱うことが出来ます。 また、 ●環境に関する初期設定を行う。 ●辞書追加の時、存在しない辞書、頻度ファイルの作成 といった処理も行います。 4.アプリケーション 4.1 uum uum は、バージョン3で wnn と呼ばれていたものと、ほとんど同じです。 小さなところは色々手が加えられていますが、大きな違いは、 ●小文節を反転、大文節を下線によって表す。 ●大文節に対する操作を可能にする。(デフォルトとする) ●inspect, 単語検索、辞書検索の画面から、単語や辞書の 削除や使用の変更の指定が行なえるようになっている。 ●大文節に対応した、今までより統一的なキーバインドをデフォルトとする。 といったところでしょうか。 uum では、文節に対する基本的操作は、主に大文節に対して行なわれます。基 本的な操作とは、次候補、伸ばしなどです。 しかし、小文節についての編集を行ないたいこともあると考えられるので、 そのためのバインドも行なっています。 (文節の移動については、小文節単位のものがデフォルトになる予定です。 というか、大文節のものは、作るのを忘れていた。) (デフォルトのキーバインドは、いままでよりかなり統一的なものとなっています。) uum のもう一つの特徴として、inspect の画面(デフォルトでは、Ctrl_Vにバ インドされると思います。)の中から、単語の削除や単語使用の中断が出来る ことがあります。単語の削除は Ctrl_D、使用の中断は Ctrl_U にデフォルト でバインドされると思います。これにより、「こんな単語が辞書にあるから変 換がおかしくなるんや」と思った時に、その単語を含む小文節のところにカー ソルを持っていって、Ctrl_Z + Ctrl_Uをすることにより、それ以降その単語 が変換に用いられなくなります。 また、単語検索の画面でも、 Ctrl_D、Ctrl_U で単語の辞書からの削除、単語 の使用状態の変更(すなわち、変換に使われていたものの使用を中断したり、 使用を中断されているものの使用を再開したり)が可能になっています。(使用 を中断されている単語は、単語検索時に、頻度が "---" で表されています。) さらに、辞書検索の画面からも、辞書の削除、使用状態の変更が Ctrl_D, Ctrl_U で出来るようになっています。