title: ポイント

ポイント
========================================

プログラムのスタート
----------------------------------------

ルールを読み込ませるとプログラムがスタート
するようにルールを作成すると，ルールの読み込みが
完了する前にプログラムが動作しはじめるような
感じになるので，たぶん駄目．プログラムの
スタートはNotation3の欄で適当な三つ組を入力
することによって行うようにしたほうが妥当．
試しにルールに`-> print('test') .`と入れて
みると，testが2回表示される．ただ，
`-> (:a :b :c)`のようなものは，無害なので
OK．

removeとdropビルトイン
----------------------------------------

removeで三つ組を消すと，そこから導かれる結論の
三つ組も消えてしまうので，要注意．結論が
確定する前に前提の三つ組を消せば，その結論に
ついては大丈夫だと思っていましたが、間違いのようです。
removeで消した三つ組から得られていた結論が、伝搬して
消去されるタイミングがいまいちわかっていません。
dropはそのような伝搬がおこらないのですが、削除した
ことをJenaが認識しないようで、思わぬ無限ループに
なることがあり、要注意です。(この削除したことを
認識しないというのはバグではなかろうか？)

(追記:2007,02/06)上記の現象はJenaのReasonerを
「hybrid」または「forwardRETE」モードにした時の
現象で，「forward」にした時はまた違った動作を
することがわかりました．正確なところはよくわかり
ませんが「forward」の場合dropはエラーになり，
removeがdropのような動作をしているように見えます．

listEntry
----------------------------------------

listEntryを使って，リストの中の要素を取り出して，
変数に代入できるが，この代入はちゃんとした代入で
なく，listEntryのビルトインの後の処理で，別の値に
置き換わってしまうようだ．これは使用なのかバグな
のかわからない．

リストの生成
----------------------------------------

これは，自分の作った所に原因があると思うのだが，
listビルトインやkeitaisoビルトイン
などでリストを生成する場合，一旦ルールを終了
させないと，変なリストがでてくる感じがする．
原因の究明が必要．

フリーズについて
----------------------------------------

知らずしらずのうちに，無限ループができたりすると
フリーズして回復不能となり，JenaCheckを終了しな
ければならなくなります．また，標準入力や
a3readビルトインなどで入力待ちの状態は，フリーズ
ではなく，何か文字を入れれば次に進みます．
ただ，a3readビルトインで入力待ちの時にa3ウィンドウ
を閉じてしまうと，文字を入力できなくなるので，
この場合もフリーズします．

今のところフリーズを解除する方法はないので，
JenaCheckを終了するしか手はありません．

変数
----------------------------------------

様々な状態を保存しておくために変数を使いたくなる．
単純に三つ組を使って(:変数名 :val '値')とかすれば
良さそうだけど，これが曲者．最初に変数を使って，
値をセットするのは問題ないが，それを新しい値に
書換えるルールがどうしても書けない．dropビルトイン
の説明を読むと「rewrite-rulesを書くのに便利」みたいな
ことが書いてあって，本来はこれでいけるはずだと思うのだけ
れど，dropで消したはずの三つ組が前向き推論の
ルールの条件部でヒットしてしまうことがある．
たぶんバグじゃないかと思う．

今のところ，FSMの実装などでは，極力removeもdropも
使わずに，空白ノードを活用して，変数の古い値に
「古い」という印を付けて最新の値と区別することで，
変数の働きをさせている．が，不便だし，ゴミが沢山
出てしまう．

下に，変数の実験をするルールを書いておく．(三つ組
入力を使う例．)なんか途中までは上手く動いてるんだけ
ど，どんどん変数を変化させていくと変なことに…

@prefix in: <http://input.org/namespace#> .
@prefix : <http://test.org/> .
-> (:var :is 'dummy') .
(?b in:input ?x)
noValue(?b :is :old)
(:var :is ?y)
    ->
    print(?x,?y)
    (?b :is :old)
    drop(2)
    (:var :is ?x)
    .

(本来なら，上の「?b :is :old」のような
小細工を使わずに「?b in:input ?x」も
dropで消して良いと思うのだが…．やっぱり，
jenaの開発者が，jenaをルールベースの
エージェントとして使うようなことは，
あまり意識してないのかも…．でも，ほんの
ちょっと改良すれば十分ルールベースの
エージェント開発環境になると思うのだが．)

(追記:2007,02/06)上記の現象はJenaのReasonerの
モードを「hybrid」または「forwardRETE」にした
時の現象のようです．「forward」モードの場合は，
dropがエラーでremoveがdropのような働きをする
ように見えます．なので，「forward」モードで
removeビルトインを活用すれば，だいぶエージェント
が作成しやすくなるかもしれません．
そこで，とりあえずJenaCheckにモード切り替えの
機能を付けました．これから実験していきたいと
思います．

SPARQLを用いた後向き推論のバグ？
----------------------------------------

SPARQLを用いれば後向き推論を実行することが
可能です．実際Jenaでもできるわけですが，
いくつかの引数を渡して，それを計算して
返してもらいたい場合は以下のようなSPARQLを
組みます．

    PREFIX : <http://test.org/>
    SELECT ?ans
    WHERE { (1 2) :add ?ans }

つまり，主語の部分をリストにして，目的語の部分を
変数にしておくというわけです．(1+2を計算して?ansの
検索結果として3を返して欲しい場合)
で，これを処理するための後向き推論のルールは，

    @prefix : <http://test.org/> .
    (?list :add ?ans)
        <-
        listEntry(?list,0,?arg0)
        listEntry(?list,1,?arg1)
        sum(?arg0,?arg1,?ans)
        .

となります．実際これは特殊な条件下では上手く
動作します．でも，通常は動作しないようです．
その特殊な条件とは引数のリストがあらかじめ
モデルに入っているという条件です．つまり，
以下のNotation3を追加しておくと上手く動作
します．

    @prefix : <http://test.org/> .
    (1 2) .

これは，バグなのか使用なのかわかりませんが，
これが使えないのは非常に痛いです．上のN3を
追加すると上手くいくことからして，たぶん，
チョット修正すれば直ると思うのですが…

