制約論理プログラミングその1

AZ-Prolog version 7.51から制約論理機能が新しく追加されていました。

簡単な使い方と実用的に使用する際に注意すべき内容をまとめます。

ユーザーズマニュアルはsofnecさんの方で公開していますので、
こちらの内容に記載しているものは解説を省きます。
http://www.az-prolog.com/manual/manuals/manual_clp.html#clp

またmanual述語を使用するとディレクトリ内のhtmlファイルを呼び出して
ドキュメントを閲覧する方法も有ります。
?-manual(clp). 

  • 制約論理機能の使い方
変数に制約を与える方法はin/0などの基本組込述語を使用した方法と、
#などの
拡張ライブラリ組込述語を使った方法が有ります。
詳しくは上記マニュアルを参照して下さい。

  • 基本組込述語
基本組込述語を使用して制約論理プログラミングを記述する方法を紹介します。
例えば、
||?-X in 0..9,X in 9..20.
X       = 9
この場合は変数Xに0~9のいずれかといった制約をin/0述語によって与えています。
次にX in 9..20でXに9~20の値のどれかといった制約を与えています。
この2つの制約条件によってXに9の値が入ります。

それではXに2つ以上の変数となるような条件の場合はどうなるでしょうか?
| ?-X in 0..9,X in 8..20.
no
noになりましたね。
この場合は、get_clp_area/2述語を使用して値をリストとして取り出します。

X in 0..9,X in 8..20,get_clp_area(X,L).
X       = X,
L       = [8,9]

変数が3つ以上の整数の値となる場合は,".."といった表記で値が取れます。
X in 0..9,X in 7..20,get_clp_area(X,L).
X       = X,
L       = [7..9]

※注意点
get_clp_area/2は第2アリティが2つ以上の変数が存在する場合のみ有効です。
| ?-X in 0..9,X in 9..20,get_clp_area(X,L).
no
解が1つしかない場合はFailします。

  • 拡張ライブラリ組込述語
拡張ライブラリ組込述語を使った方法はdlib_require/1述語を使用して
拡張機能の使用を宣言するところから始まります。
以下はXに変数を代入するだけのプログラムです。
#=を使ってXに値を代入しています。
Xの変数を特定するにはlabeling/1述語を使用します。
test:-
 dlib_require(clp),
 X #=12,
 labeling([X]),
 write(X).

ここでは12が表示されると思います。
次にX #=12X #=12+1に変更すると13に計算された値が表示されます。

※注意点
以下の様なプログラムの場合、Failします。
test:-
 dlib_require(clp),
 1+X  #=12,
 labeling([X]),
 write(X).

traceすると変数が未変数と変換されてしまっているため、
未変数をラベリング使用としてエラーとなってしまいます。
[2] 1 Try   : 1+X_9#=12 ?
<< BUILTIN CALL >>
[2] 1 Succ  : 1+_86#=12

この場合は、Xに適当な値を条件として加えます。

test:-
 dlib_require(clp),
 X in 0..100,
 1+X  #=12,
 labeling([X]),
 write(X).
これでX=11となります。

※注意点
inで変数を制限させますが、必要以上に大きい値を設定すると
特定するのに時間がかかるので注意が必要です。
system_get_min_max_int/2で整数の最長値と最大値を取得できますが、
X in 0..100X in MinInt..MaxIntにすると
ラベリング処理の際、MinIntから値を探しに行くので、時間がかかります。
(というか、何分経っても戻ってきませんでした。)


※注意点
整数の条件検索の際、割り算を使うと意図しない結果となります。
test:-
 dlib_require(clp),
 X in 0..100,
 X  #=12/2,
 labeling([X]),
 write(X).
答えは6と期待しますが,X #=12/2でXの値がFloat型に変換されるため、
整数範囲のみを検索する現在の制約論理では対応することもできません。
そのため、以下の様なこともできません。
 dlib_require(clp),
 X in 0..100,
 X  #=13.5,
 labeling([X]),
 write(X).
最終更新:2014年05月09日 11:17