ボンジュール・マドモアゼル

本サイトの情報は自己責任にてご利用下さい。

[Prolog] SWI-Prolog − 属性付き変数 (Attributed variables)

 
SWI-Prolog の属性付き変数のまとめ 以下、SWI-Prolog 5.11.15 Reference Manual の部分翻訳(非公式)。
誤訳があるかもしれない。色付き文字は訳者の補足。

6.1 Attributed variables
6.1 属性付き変数

属性付き変数は、Prologのユニフィケーション・アルゴリズムを拡張する技法(Christian Holzbaur 1992 フックを使った属性付き変数の束縛)を提供する。Prolog コミュニティにおいて、属性付き変数の定義とインターフェースの形式については合意がない。SWI-Prologのインターフェースは Bart Demoen 2002 によって hProlog Demoen 向けに実現されたものと同じである。このインターフェースはシンプルで、Leuven CHR システムが走るすべての Prolog システムで利用できる。(section 7 と Leuven CHR のページを見よ)
属性付き変数の束縛が起こると、フックを起動するゴールが最初の可能な機会に実行される。現実装では、フックは、属性付き変数が、節の頭部の一部と単一化した直後か、外部のネイティブ関数(foreign language predicate)が成功した後に実行される。
A = 1 という単一化も =(A,1) というゴールが起動され、節 =(X,X):- true. の頭部との単一化を試みることに注意。

それぞれの属性は、モジュールに関連付けられ、そのモジュールの中でフック (attr_unify_hook/2) が実行される。
下の例では、完全ではないが、簡単な有限ドメインの推論を実現している。
:- module(domain,
          [ domain/2                    % Var, ?Domain
          ]).
:- use_module(library(ordsets)).

domain(X, Dom) :-
        var(Dom), !,
        get_attr(X, domain, Dom).
domain(X, List) :-
        list_to_ord_set(List, Domain),
        put_attr(Y, domain, Domain),
        X = Y.

%       An attributed variable with attribute value Domain has been
%       assigned the value Y

attr_unify_hook(Domain, Y) :-
        (   get_attr(Y, domain, Dom2)
        ->  ord_intersection(Domain, Dom2, NewDomain),
            (   NewDomain == []
            ->  fail
            ;   NewDomain = [Value]
            ->  Y = Value
            ;   put_attr(Y, domain, NewDomain)
            )
        ;   var(Y)
        ->  put_attr( Y, domain, Domain )
        ;   ord_memberchk(Y, Domain)
        ).

%       Translate attributes from this module to residual goals

attribute_goals(X) -->
        { get_attr(X, domain, List) },
        [domain(X, List)].

このコードに対する質問とその答え:
?- domain(X, [a,b]), X = c               ==> fail
?- domain(X, [a,b]), domain(X, [a,c]).   ==> X = a
?- domain(X, [a,b,c]), domain(X, [a,c]). ==> domain(X, [a, c])

述語 domain/2 は、(1番目の節に)フェッチするか、(2番目の節で)変数に属性 domain(単一化されることが可能な値の集合)を割り当てる。
2番目の節では、X がすでに属性 domain を持つという可能性に対処するために、まず未束縛の変数 Y に属性を関連付け、その後に Y を X に単一化する。
述語 attr_unify_hook/2 は、フックであり、属性 domain 付き変数に値が割り当てられた直後に呼ばれる。
変数が具体的な値に束縛された簡単なケースでは、その値がドメインにあるかどうかをチェックする。
他方、ドメインの積集合を取るか、積集合が空であれば、失敗する(1番目の例)、
積集合がひとつの値のみある場合は、簡単に値を変数の割り当てる(2番目の例)、
そうでなければ、新しいドメインを変数に割り当てる(3番目の例)。
非終端 attribute_goals/3 は、現在保持されている属性をユーザが読み取り可能なゴール(呼び出されるとき、属性を使えるようにする)の形式に変換するのに使われる。

6.1.1 Attribute manipulation predicates
6.1.1 属性操作述語
attvar( @Term)
項が属性付き変数であれば、成功する。var/1 は、属性付き変数についても成功することに注意せよ。属性付き変数は、put_attr/3 によって作成される。
put_attr(+Var, +Module, +Value)
Var が変数か属性付き変数であれば、Module の名前を持つ属性に Value を設定する。この名前を持つ属性が既に Var に関連付けられている場合、古い値は置き換えられる。バックトラックは古い値を復元する(つまり. 属性は変更可能な項である。setarg/3を参照のこと)。
この述語は、Varが変数でない場合、表記エラーを起こし、Moduleがアトムでない場合、型エラーを起こす。
get_attr(+Var, +Module, -Value)
Moduleの名前を持つ属性の現在の値を要求する。Varが属性付き変数でないか、Moduleで名付けられた属性が Var に関連付けられていない場合、この変数は、静かに失敗する。Moduleがアトムでない場合、型エラーを起こす。
del_attr(+Var, +Module)
Moduleの名前を持つ属性を削除する。もし、Var が最後の属性を失うと、その変数は伝統的なPrologの変数に戻される。Moduleがアトムでない場合、型エラーを起こす。その他のケースでは、その名前の属性が存在するか否かにかかわらず、この述語は成功する。

6.1.2 Attributed variable hooks
6.1.2 属性付き変数のフック

属性名はモジュールに結び付けられる。これは、属性付き変数に関する特定の操作が、属性名にマッチするモジュールのフックを起動することを意味する。
attr_unify_hook(+AttValue, +VarValue)
フックは、属性付き変数が記述されるそのモジュールに定義されなければならない。この述語は、非変数項か、他の属性付き変数と単一化された後に呼び出される。AttValue は変数に関連付けらていたこのモジュールにおける属性であり、VarValueは変数の新しい値である。この述語は、通常、変数とVarValueとの束縛を拒否するために失敗し、束縛を取り消すため、バックトラックを強制させる。もし VarValue が他の属性付き変数の場合、フックは、しばしばそれらふたつの属性値を結合し、結合された属性値を put_attr/3 を使って、改めてVarValue に関連付ける。
attr_portray_hook(+AttValue, +Var)
write_term/2 およびこの類の述語において、オプション attributes(portray) が有効な場合、各属性に対して呼び出される。このフックが成功するなら、属性は、意図された印刷が行われる。そうでない場合、 Module = ... が、変数の存在を示すために印刷される。属性値のやり取りを取り扱う新しい基盤は、 copy_term/3 とそのフック attribute_goals/3 に基づく必要がある。
attribute_goals(+Var)
この非終端述語は、モジュールで定義されるならば、そのモジュールの属性を、属性を残存するゴール (residual goal) として映し出すため copy_term/3 によって使われる。この述語は、また、質問を実行した後、属性を残存するゴールを得るためにtoplevel によって使われる。

6.1.3 Operations on terms with attributed variables
6.1.3 属性付き変数を持つ項の操作

copy_term(+Term, -Copy, -Gs)
Termの属性を持たないコピーとして標準的な項 Copyと、属性を表現するゴールのリストGs を作成する。ゴール maplist(call,Gs) は、Copy の属性を再形成する。その属性に対応するモジュールで定義された非終端 attribute_goals/3 は、属性値をゴールのリストに変換するのに使われる。この構成要素は、移植可能な分かりやすいやり方で、保留された属性をレポートするために toplevel によって使われる。この述語は、制約による項の通信および推論にとって推奨される方法である。
例:foo.pl
:- module(foo,[]).

attribute_goals(X) -->
        { get_attr(X, foo, Value) },
        [fofo(X, Value)].

?- put_attr(X,foo,v1),put_attr(Y,bar,v2),copy_term(a(X,Y),Copy,Gs),del_attrs(X),del_attrs(Y).
Copy = a(_G1107, _G1108),
Gs = [fofo(_G1107, v1), put_attr(_G1108, bar, v2)].

copy_term_nat(+Term, -Copy)
copy_term/2 のように使う。ただし、属性はコピーされず、新しい未処理の変数に置き換えられる。
term_attvars(+Term, -AttVars)
AttVars は、Termに含まれるすべての属性付き変数のリストである。term_attvars/2 は再帰的に動作する。この述語は、循環安全 Cycle-safe である。ゴール term_attvars(Term,[]) は、項 Term が属性を持っていないことを効率的なテストである。つまり、最初の属性付き変数が見つかった時点でスキャンが中断される。

6.1.4 Special purpose predicates for attributes
6.1.4 属性に関する特殊用途の述語

通常のユーザコードは、put_attr/3, get_attr/3 および del_attr/2 で処理される。
この節のルーチンは、変数の全属性のリストをフェッチおよび設定する。
これらの述語の使用は、印刷に限られたものか、ほかの特殊な目的の操作が想定される。
get_attrs(+Var, -Attributes)
Var のすべての属性を取得する。属性は、att(Module, Value, MoreAttributes) の形式の項である。MoreAttributes は、最後に設定された属性を示す。
例:
?- put_attr(X,foo,a),put_attr(X,bar,b),get_attrs(X,Y),del_attrs(X).
Y = att(foo, a, att(bar, b, [])).

put_attrs(+Var, -Attributes)
すべての属性を設定する。Attributes の説明については get_attrs/2 を参照せよ。
del_attrs(+Var)
Var が属性付き変数の場合、すべての属性を削除する。そうでない場合、副作用なしに成功する。
<<SWI-Prolog − モジュール | ホーム | コントロールキー押下時の WM_CHAR メッセージ>>

コメント

コメントの投稿

管理者にだけ表示を許可する

画像の文字を半角数字で下記ボックスに記入ください。
文字が読みにくい場合はブラウザの更新をすると新しい文字列が表示されます。