このページではJavaScriptを使用しています。

10.付属プログラム/資料

10-1.ベンチマークプログラム

プログラムの格納場所
ベンチマーク起動プログラム一式は次の場所に格納されています。
Makefileがありますので、ディレクトリごと作業場所へコピーしてLinuxではコンパイルしてください。(Windows版ではコンパイル済みです。)
Windows: %AZProlog%¥bench
Linux:  ${AZProlog}/share/azprolog/bench
Mac: ${AZProlog}/share/azprolog/bench
コンパイル
ベンチマーク用プログラムはSICStus-Prolog様のサイトにあるものを利用します。
http://sicstus.sics.se/performance.html からダウンロードして解凍し、内容物すべてを「bench/source」下へコピーし「bench」下でmakeします。
( Windowsで再コンパイルするときは、 ~/xxxx/bench> nmake )
起動

ターミナルからbenchmarkを起動すると次のメニューが表示されます。
番号または各メニュー項目の頭文字(r,s,l,t,g,b,e)を投入します。
<例>

<< AZ-Prolog.V8 BenchMark Test Menu >>

1) Run  All BenchMark Program (if Added,Parameter File Load)
2) Save AZ-Prolog-Benchmark-Result to Current Directory
3) Load All Result-File From Current Directory
4) Table-Style Result Display
5) Graph-Style Result Display
6) Break to Interpreter (Type "?-unbreak." To Return Here)
7) Exit 
Enter No.>r  <== "r"の投入でベンチマークが走ります

Module名のプログラムを()内の回数繰り替えした秒数が表示されます。

******  Running Benchmark Programs :: AZ-Prolog.V8 ******
 
ModuleName  Verify Iterate C-Compile  Byte-Compile  Interpreter   [SWI-Prolog]
-----------+-CBIO-+-------+----------+-------------+-------------+------------
boyer       [Tttt]     100 0.796 (1)  1.892 (2.37)  4.970 (6.24)  2.506 (3.14)
browse      [Tttt]     100 1.319 (1)  2.360 (1.78)  4.375 (3.31)  2.957 (2.24)

「C-Compile」がフルコンパイルコードでの処理時間
「Byte-Compile」がバイトコンパイルコードでの処理時間
「Interpriter」がインタプリタでの処理時間

他社製Prolog処理系との比較

同ディレクトリには他社製Prolog処理系用起動バッチファイル「iso_main_swi.pl」が含まれています。
SWI-Prolog がインストールされているとして、次の手順で結果を“SWI-Prolog.rslt”に出力します。

~/xxxx/bench$ swipl
    Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.4)
    Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam

For help, use ?- help(Topic). or ?- apropos(Word).

?- [iso_main_swi].

結果は、ベンチマークメニューの「l」コマンドで読み込みます。

Enter No.>l

[AZ7-B.rslt,AZ7-C.rslt,AZ7-I.rslt,SWI-Prolog.rslt] Loaded

「t」コマンドでテーブルスタイルで結果の表示をします。

Enter No.>t

      << AZ-Prolog V8.11 LINUX x64 BenchMark Ubuntu1404 on Core i7-4790k >>

                           <========  AZ-Prolog  ==========>  
ModuleName  Verify Iterate C-Compile  Byte-Compile  Interpreter   [SWI-Prolog]
-----------+-CBIO-+-------+----------+-------------+-------------+------------
boyer       [Tttt]     100 0.796 (1)  1.892 (2.37)  4.970 (6.24)  2.506 (3.14)
browse      [Tttt]     100 1.319 (1)  2.360 (1.78)  4.375 (3.31)  2.957 (2.24)
chat_parser [Tttt]     100 0.205 (1)  0.691 (3.37)  0.861 (4.20)  0.675 (3.29)
crypt       [Tttt]   10000 0.428 (1)  1.227 (2.86)  2.295 (5.36)  2.865 (6.69)
deriv       [Tttt]  100000 0.191 (1)  0.365 (1.91)  0.545 (2.85)  0.495 (2.59)
dynamic_uni [Tttt]   10000 0.306 (1)  0.817 (2.66)  1.037 (3.38)  0.827 (2.70)
fast_mu     [Tttt]   10000 0.132 (1)  0.262 (1.98)  0.609 (4.61)  0.525 (3.97)
flatten     [Tttt]  100000 0.763 (1)  1.881 (2.46)  4.106 (5.38)  3.083 (4.04)
itak        [Tttt]     100 0.854 (1)  1.069 (1.25)  1.220 (1.42)  1.523 (1.78)
meta_qsort  [Tttt]    5000 0.433 (1)  0.988 (2.28)  2.302 (5.31)  1.036 (2.39)
mu          [Tttt]   10000 0.093 (1)  0.196 (2.10)  0.433 (4.65)  0.376 (4.04)
nreverse    [Tttt]  100000 0.188 (1)  0.350 (1.86)  3.027 (16.1)  1.792 (9.53)
nreverse_bu [Tttt]  100000 0.191 (1)  0.279 (1.46)  0.444 (2.32)  1.821 (9.53)
poly        [Tttt]    1000 0.679 (1)  1.330 (1.95)  2.389 (3.51)  2.170 (3.19)
primes      [Tttt]   10000 0.105 (1)  0.306 (2.91)  0.815 (7.76)  0.777 (7.40)
prover      [Tttt]   10000 0.124 (1)  0.273 (2.20)  0.603 (4.86)  0.379 (3.05)
qsort       [Tttt]  100000 0.645 (1)  1.644 (2.54)  3.963 (6.14)  3.161 (4.90)
queens      [Tttt]   10000 0.143 (1)  0.280 (1.95)  0.981 (6.86)  0.988 (6.90)
query       [Tttt]  100000 0.496 (1)  1.700 (3.42)  2.231 (4.49)  3.374 (6.80)
reducer     [Tttt]     500 0.258 (1)  0.741 (2.87)  1.135 (4.39)  0.805 (3.12)
sendmore    [Tttt]     500 0.395 (1)  1.074 (2.71)  2.971 (7.52)  3.441 (8.71)
simple_anal [Tttt]     500 0.119 (1)  0.340 (2.85)  0.607 (5.10)  0.438 (3.68)
tak         [Tttt]    1000 0.955 (1)  2.911 (3.04)  10.33 (10.8)  5.902 (6.18)
unify       [Tttt]   20000 0.447 (1)  1.470 (3.28)  3.665 (8.19)  2.374 (5.31)
zebra       [Tttt]     500 0.284 (1)  0.317 (1.11)  0.594 (2.09)  0.717 (2.52)
-----------+-CBIO-+-------+----------+-------------+-------------+------------
      Total(Average)       10.54 (1)  24.76 (2.37)  56.50 (5.47)  45.00 (4.71)

Verify列の[Tttt] は各プログラムの結果がすべて等しいことを示しています。 ()内の数字はAZ-Prologのフルコンパイルコードの実行時間を1としたときの倍率です。

10-2. AZLINT

AZ-PrologコンパイラでPrologソースのリント(プログラム・チェッカー)をおこなうことができます。従来はazlint.exeという独立したスタンドアローンアプリケーションでしたが、Ver7からはコンパイラオプションに「/lint」をつけることで、コンパイルせずに診断のみをおこなうことにしました。

C:¥>azpc -p /lint ファイル名並び {/log} ↓

「/log」を付けると、画面と同時に、azpc.logというファイルに診断内容を出力します。 各ファイル、1モジュール毎に次のような情報を得ることができます。

(1)シンタックスエラーのチェック
(2)決定性にコンパイルされる述語の一覧
(3)非決定性にコンパイルされる述語の一覧
(4)インタプリティブコールとなるゴールの一覧
(5)使用している組込述語の一覧
(6)extern宣言群のうち、使用しているものの一覧
(7)組込述語のオーバーライト定義のワーニング
(8)public宣言をしている述語が1つもないときそのワーニング
(9)無視するpublic宣言、無視するコマンド
(10)publicでない述語でモジュール中でも使われていない述語の一覧


ただし、これらの情報は「コンパイルされた場合にどうなるか」ですので、インタプリタコード上では非決定であってもコンパイル時には決定性述語という場合もあります。(主にモード宣言に関して発生する点です。ただしインタプリタ上でも厳密にモード宣言どうりに使われていれば、効率上はともかく同じ結果にはなります。)

各情報について順番に説明しながら、azlintを使ったデバッグについても言及しましょう。

(1)シン夕ックスエラーのチェック

ファイルにシン夕ックスエラーがあると、その節位置番号(つまりファイル中の何番目に書かれている節か、であって述語の何節めかではありません)とエラーとなった周辺の内容を表示して処理を停止します。
シンタックスエラーは、単純な括弧の対応不良、ピリオドの付け忘れといったレベルからオペレータの定義内容に係わる複雑なものまで多岐にわたりますから、エラー箇所の前後を注意して良く見る必要があります。オペレータやオペレータと同じアトムを使っている場合は、まずオペレータ定義の内容を調べて下さい。大抵は括弧を補ったり、正規の表現にすることで何とかなります。
<例>

test(X):-X= = spy → true.
= = , spy, →
がオペレータ定義
↓
test(X):-X = =(spy)→ true.

シンタックスエラーはインタプリタ上で、“echo(_,on).”としてからコンサル卜するか、AzEdit上でコンサル卜することでも判りますが、AZLINTが最も簡便です。

(2)決定性にコンパイルされる述語・非決定性にコンパイルされる述語

決定性に書ける処理(述語)は決定性にすべきです。メモリ効率処理効率が違って来るからです。決定性と判定された述語は、他モジュールで使う(他モジュールでextern宣言する)ときにはその情報を付加しておきましょう。(detプレフィックスを付ける)
<例>

: extern det :述語名/アリティ.

決定性にするには、カットオペレータ、モード宣言を積極的に使うことのほかに、externの述語を使うときにその述語が決定性であるかどうかも重要です。
<例>

決定性とならない		決定性となる

append([],L,L).			append([],L,L):-!.
append([A|L],B,[A|C]):-		append([A|L],B, [A|C]):-
	append (L,B, C).		append(L,B,C).
 
または左の定義のままで
:-mode append(+,+,-).を追加する。

決定性になるように記述したつもりでも、非決定性と判定されたときは要注意です。本来のロジック上の誤りである場合以外に、バグが潜んでいる可能性があります。

a) externの述語を使っており、これが決定性なのにdet:宣言がない、またはextern宣言そのものを忘れ、イシタプリティブcall(組込が非決定述語
b) ゴールの一部にスペルミスした述語callがあり、インタプリティブcallとなっている。
c) モード宣言の引数ミス。
d) ピリオドとカンマをまちがえて次の単位節を最終ゴールと見なしている。
(意外に多いミスです。)

<例>

a:-b,c,←本来はピリオド。
b.

(3)インタプリティブcallとなる述語

本来、動的に「assert」または「consult」して使われる述語以外のものが表示された場合は,前項の中のa)、b)であることは間違いありません。

(4)使用組込述語の一覧

一部の組込述語(主に画面制御用)を使っているプログラムは、コンパイルオプションとして「/curses」または「/i」が必要です。 使われている組込述語の一覧を見ることでチェックできます。

(5)組込述語のオーバーライト定義のワーニング

インタプリタでは、組込述語と同じファンクタ、アリティを持つ述語のコンサルトはエラーとなりますが、コンパイルすることはできます。 すなわち、低レベルの組込述語を組み上げて上位の組込述語の動作を定義しなおす(putを使ってwriteを最定義、getを使ってreadを最定義する等)ことなどができます。ただし、こうした意図でないのにこのこのワーニングが出たときは、明らかにソースファイル中のミスです。

<例>

a:-b,  
    c.

ピリオドとカンマの書きまちがい。

   

write(a).

 

 
       
   

write/1の定義になってしまう。

(6)使われていないスタティック述語の一覧

AZ-Prologでは、外部モジュールから呼ぶことの出来る述語は、publicの宣言をするようになっています。
:-public 述語名/アリティ.
:-publicall.(全述語)
とすることで、他モジュールから呼ぶこともできますし、インタプリタからも使うことができます。(組込述語として登録される)。
もう1つ書き方があり、
:-public invisible :述語名/アリティ.
とすると、組込述語の登録は行いません。すなわち、他モジュールで使うことはできますが、必ずそのモジュールではextern宣言を入れなければなりません。
publicでない述語は、モジュール内のみにおいて使うことが出来ます。言い換えると、他の述語のサブ述語となります。
こうした述語を「static述語」と呼びます。static述語は他から見えませんので、同じ述語名、アリティのものが他モジュールにあってもリンクエラーを起こすことがありません。
ただし、同一モジュール中でまったく使われていないstatic述語は外からも呼ばれないので、結局はムダとなります。開発中では良く起きることではありますが、完成したアプリケーションをコンパイルするときには、ファイルから削除するかコメントにしておきましょう。

(7)定義述語の一覧

多くの節からなる述語で引数の数のミスをした節が混じっていると、当然のことながら別述語となってしまいます。一覧表を見て同一述語名で引数違いが含まれていれば、意図したものか見なおしましょう。

(8)その他のワーニング

前記の説明で十分でしょう。必要に応じて役立てて下さい。

(9)その他の使い方

AZ-Prologコンパイラでは、モジュール単位にオブジェクトになり、ファイル中には任意にモジュール宣言を入れることになっています。この時、自己モジュールになく、他モジュール中で定義されている述語を使うときは、extern宣言を入れた方が、直接関数呼び出しとなり、高速化されます。 しかし、実際問題として開発中に複数モジュール中の定義を常にチェックしながら宣言を書いていくのも面倒です。 こんな場合には、「azlintでlogをとり、そのログファイルをエディタに読み込んで、“interpritive call”として出力されている述語名一覧を切り出して、extern宣言に一括変換したものを元のファイルに追加すれば簡単に出来ます。

(10)その他

Prologによくあるバグで、「Lint」には反映されないものとして変数名のミススペルがあります。Prologは変数宣言の必要も型指定も不要で、また未束縛変数であっても引数として許されるので、他言語のように、コンパイル時やリントユーティリティではチェックしようがなく、実行時に組込述語でエラーが発生してわかる場合があります。

ANS=3,X is Ans+4, …… 〈実行時エラー〉
    〈別変数となるケース〉

次のようなケースではケースをよくながめる以外ないでしょう。

定義 a(l,one)   実行 ?-SP=2,a(Sp,X).
  a(2,two)      

述語情報の中に、頭に数字の付いた定義したおぼえのない述語が含まれていることがありますが、これはLint自身がソースプログラムを読み込む時に、解析しながら、展開/たたみ込みをして生成したものです。
主に節中にOR述語、IFThen、ゴール列を引数とした述語(call、errorsetなど)などの切り出し部分です。
「azlint」は、AZ-Prologコンパイラのソースー次解析部と同一ルーチンを使って記述されています。

10-3.システムプログラム

パッケージにはAZ-Prologの機能拡張プログラムが付属しています。
カスタマイズインタプリタの生成、スタンドアローンアプリケーション生成など、必要に応じて作業場所へコピーし、コンパイルしてください。
プログラムの格納場所
Windows: %AZProlog%¥system
Linux:  ${AZProlog}/share/azprolog/system
Mac: ${AZProlog}/share/azprolog/system
各プログラムの概要
system/ext/ 拡張ライブラリ(.dll .so .dylib) のソースとMakefileです。
azedit、clp、mecab、oniguruma、redis、websock、socket などのディレクトリごとに分かれています。
system/C/ C言語で記述された拡張用ソースが格納されています。
system/make/ インタプリタの再Make参考Makefile,azpc入力ファイルがあります。
system/pl/ 機能拡張、スタンドアローンアプリケーション用のprologソースです。
<システムプログラム>
azserve.pl OLEオートメーションサーバのトップレベル述語
prologcgi.pl CGI用インタプリタ"prologcgi"トップレベル述語
mlt_child.pl 並列処理用子プロセストップレベル述語
mlt_parent.pl 並列処理用親プロセス述語
setof.pl setof,bagof,findall,s_qsort のソース
iso_pred.pl Prologで記述されたISO 19述語
 abolish/1 once/1 atom_concat/3 atom_codes/2 atom_chars/2 number_chars/2 char_code/2
 get_char/1 get_char/2 open/3 current_predicate/1 current_prolog_flag/2 set_prolog_flag/2
 copy_term/2 sub_atom/5 uppercase_atom/2 lowercase_atom/2 downcase_atom/2 number_codes/2
utility.pl Prolog定義の正規表現などのユーティリティ
odbc_prolog.pl ODBCをsql風に利用する上位述語
fs_utility.pl 素性構造メタ述語のソース
macro_consult.pl マクロ制約記述を展開してコンサルトする述語のソース
<ユーティリティプログラム>
cgi2bytecgi.pl
dump.pl
error.pl
puttxt.pl
count.pl
lil2az.pl 
PrologCGIソースバイトコード変換ツール
バイナリファイルの16進ダンプツール
エラーメッセージ変更用ツール
CGIソースをブラウザに出力するプログラム
Prologプログラムの節行数カウントツール
LilFeSプログラムをAZ-Prolog用にコンバートするユーティリティ
ユーティリティプログラムの使い方の例としてcount.pl を動かしてみましょう。

コンパイル:

> azpc -p /e count /no count.pl 

スタンドアローン実行形式プログラム「 count 」が生成されます。

 C:¥>count -p        ファイル名並び↓

と入力することにより、各ファイルのライン数・節の数・述語数が表示され、最後に全ファイルのライン・節・述語の合計が表示されます。出力をファイルに落としたければ、リダイレクトを使って次のようにしてください。

 C:¥>count -p queen.pl setof.pl>outfile↓

Prologの場合、1行中にゴールを並べて書くことがあり、またコメントや空白行を入れて、見易くすることがありますので、エディタ上のライン数がそのままプログラムの大きさにはなりません。
本ユーティリティでは、プログラムだけを扱いますので、ソースの管理に役立つと思います。尚、ライン数のカウントは、頭部は1ライン、ボディ部の各ゴールも各1ラインとし、ORゴール、callゴールなど、ゴールを引数とするゴールは更にそのゴール数を加えています。
その他の用途として、述語に含まれる節数が、どうであるか、また一節に平均して何ライン含まれるかなどの調査にも応用できます。

10-4.サンプルプログラム

パッケージにはAZ-Prologの各機能ごとのサンプルプログラムが付属しています。
ディレクトリごと作業場所へコピーしてLinuxではコンパイルしてください。

プログラムの格納場所
Windows: %AZProlog%¥sample
Linux:  ${AZProlog}/share/azprolog/sample
Mac: ${AZProlog}/share/azprolog/sample


各ディレクトリでコンパイルして実行させるものは、ソースファイルとともにコンパイラの使い方の参考になるようにMakefileが含まれています。また、各ソースファイルには使い方などのコメントが書かれていますのでお読みください。

各サンプルプログラムの概要
sample/cgi_demo CGIのデモが格納されています。
環境設定の詳細は、HowToInstall.txtに書かれています。
sample/C_InterfaceSample C言語で述語を記述するサンプルソース格納されています。
sample/HDP 分散したPrologプログラムをパイプ連結して結果を求めるサンプルです。
実行バッチ(queentest.bat、queentest.sh)で起動します。
コンパイルMakefileが含まれています。
sample/LargeCapacityMemory 大容量のメモリ空間を使うテストプログラムが格納されています。
sample/ext 動的リンクされるようにコンパイルされた拡張ライブラリを使用するサンプルです。
現在は、mecab、redis、websockの三種類です。
sample/neuralnet バックプロパゲーションニューラルネット述語を使ったサンプルプログラムです。
ソースファイル(font.pl)をお読みください。
sample/oleauto Windowsのみの機能です。OLEオートメーション機能のサンプルプログラムです。
readole.txt に詳細が書かれています。
sample/parallel 並列処理のサンプルプログラムが格納されています。
1)AZ-Prologインタプリタに、parallel_test.plをコンサルトし、|?-test. で全実行します。
2)pentomino.exe を起動し、|?-menu. で実行し、複数の方法でペントミノパズルを解きます。
コンパイルバッチ(make_pen.bat)が含まれています。
sample/clp
制約論理のサンプルプログラムです。
起動方法などの詳細はファイルに書かれています。
使用方法は各ソースに書かれています。
magic.pl 
sendmore.pl
sudoku.pl
魔方陣を解くプログラムです。
覆面演算の例題です。
数独を解くプログラムです。
sample/nlu 自然言語処理関係のサンプルプログラムです。
trans.pl DCG による簡単な日英翻訳プログラム
hpsg.pl ICOTのCU-Prolog付属サンプルのAZ-Prolog書き換え版
素性構造型を使った単一化文法(HPSG)の簡易版です。
jpsg.pl ICOTのCU-Prolog付属サンプルのAZ-Prolog書き換え版
素性構造型を使った単一化文法(JPSG)の簡易版です。
tree.pl hpsg.pl jpsg.pl で使われているCU-Prolog組込述語の翻案プログラムです。
lil_hpsg.pl  東大辻井研究室でのLilFes課題演習・日本語構文解析プログラムのAZ-Prolog版
sample/other AZ-Prolog.V1から附属している。アプリ使用方法は各ソースに書かれています。
formula.pl 
del_app.pl
s_utility.pl
queen.pl
azlisp.pl
式の展開プログラム(Written by Kaba)
appendを含むリスト処理を差分リストへ変換するプログラム
リスト処理例題
マニュアルで説明しているN-Queenのプログラムです
Prologで書かれたLispインタプリタ
サンプルプログラムの使い方の例としてazlisp.pl を動かしてみましょう。
起動方法
> prolog
?- [-'azlisp.pl'].
?-lisp(con).↓

でRead-Eval-Printループに入ります。
S式評価はlisp_Eval(X,V)で、XにPrologのリスト形式で評価するS式を与えるとVにその評価した値が返されます。


LISP言語仕様

*シンタックス
キャラクタコード:32以下の文字は空白文字として扱われます。
「'(シングルクォート)」と「()」、空白」文字以外の文字はアトムを構成する通常の文字となります。大文字、文字の区別はあります。
数字のみからなるアトムは整数となります。


*特殊型式は以下のものがあります。
(quote x):x自身を返す
(progn forml…formn):form1,‥‥,formnを順に評価、formnを評価した値を返す。
(cond clause1‥‥clausen):clause1,‥‥,clausenの第1要素を順に評価する。
最初に「 nil 」以外のものを返した「 clause 」について、第2要素以外を「prognに与えられたように評価し、その値を返す。但し、clauseでただ1つの要素しかもたないときは、その返した値自体を返す。 それ以降の「 clause 」の第1要素の評価はおこらない。 (de function-name argumet-list・body) function-nameが(lambda argument-list・body)の大域的な名前として登録される。


*特殊型式以外のものは関数呼出しとして扱われる。従って、その引数がまず順に評価され、結果のリストに関数がupplyされます。
組込関数として以下のものがあります。

・基本5関数:car,cdr,cons,eq,atom
・(print x):xを出力する。値はx自体.
・(+xy),(-xy):それぞれx+y,x-yを返す。
・(read):入力したS式を返す。
・(terpri):改行の出力。値はt.
・(help):組込関数,特殊型式名,現在定義されている関数名を出力する。値はt.
・(bye):Read-Eval-Printループを抜ける。
・(gefdef fname):fnameの関数定義をラムダ式の形で返す。
・(load file)(save file):現在の関数定義をファイルにロード/セーブする。


<例>

(de append(x y)
(cond((eq x nil) y)
(t (cons(car x)(append (cdr x) y)))))
→ append
(append '(1 2 3) '(4 5))
→(1 2 3 4 5)

10-5.システムインプリメンテーション

(1)スタック

AZ-Prologの実行制御には次のスタックが使われます。

グローバルスタック
グローバル変数、及びReadされた項、ユニブ(=../xfy)等で内部的に作られる構造体が積まれるスタックです。

ローカルスタック
Prolgの実行をコントロールする制御フレーム、及びローカル変数、組込述語の引数バッファに使われるスタックです。

トレイルスタック
ユニファイされた変数の情報を記録し、バックトラック時に元へ戻すために使われるスタックです。

尚、本システムはC言語でインプリメントされており、これ以外にマシンスタック(C言語レベルで使用されるスタック)があります。
グローバルスタック・ローカルスタック、トレイルスタックのサイズは、AZ-Prologコンパイラによって再構成されたインタプリタ、または単独実行モジュールを生成するときに指定するようになっています。

(2)Successful pop と Last call Optimization

AZ-Prologでは、スタックの使用量を減らため「 Successful pop 」と「 Last call Optimization 」を行なっています。


Successful pop
ある述語が決定性の終了をしたとき(この述語の実行に「オルタナティブ(他の可能性)がない」という意味です)この節の実行に使われた制御フレーム、ローカル変数部分をローカルスタックから取り除く事を“successful pop”といいます。
このため、組込述語を含む述語の実行が決定的に終了することによって、このゴールは再充足されなくなります(例えそれ以後にそのゴールに新しい可能性が出来たとしても、その新しい可能性は試されない)ので、次のような注意が必要です。
a(1).

b:-a(X),write(X),assertz(a(2)),fail.

     
?-b.
1
no

ゴール①の実行は、定義節「 a/1 」が一つしかありませんので決定性の終了をし、このゴールに対応する制御フレームをローカルスタックから取り除きます。
このあとで、ゴール②により、「 a/1 」の代替節を「 assert 」してから、「 fail/0 」によりバックトラックしても、①が再充足されることなく、「 b/0 」の実行が失敗します。

非決定性の組込述語も、決定性終了をした場合は同様です。

a(1).

b:-retract(a(X)),write(X),Y is X+1,assertz(a(Y)),fail.
   ①      
?-b.
1
no

「 retract/1 」は、引数に指定された削除を試みるべき節がヒープ領域に残っている間は非決定性の終了をし、制御フレームが残っていますが、この場合のように一つだけ定義されている節を削除した後では、決定性の終了になります。


Last call optimization
Prologにおいて、再帰はもっとも基本的なプログラミング技法の一つです。
次の例を見て下さい
write_n(0) :-!.
write_n(X) :-write(X),put(32),Y is X-1,write n(Y).
            
|?-write_n(10).
10 9 8 7 6 5 4 3 2 1
yes

「 write_n/1 」は引数の値を出力し、1つずつ減じながら再帰し、引数の値が0になることによって停止します。
「 write_n/1 」の第2節の最後のゴールを実行するとき、この節自体と、それまでの各ゴールにオルタナティブ(他の可能性)がない状態になっています。すなわち、この最後のゴール①が失敗したとしても、この節には、代替節も、各ゴールの再充足もないわけですから、この節自体に要したフレームを残さなくても良いことになります。
このようなフレームを削除することを“Last call optimization”といいます。
この制御は、特に自分自身に再帰している場合(Tail recursion)ばかりでなくともおこなわれます。
また、カットオペレータが使用されることにより節の代替節、再充足すへきゴールがカットされた場合も同様な最適化を行ないます。
リストの結合を行なうプログラム「 append/3 」において次の3つの書き方が可能ですが、①よりも②、③の方がスタックの消費が少なくて済みます。

append([A|B],C,[A|BC]):-append(B,C,BC).
append([],L,L).
append([],L,L).
append([A|B],C,[A|BC]):-append(B,C,BC).
append([A|B],C,[A|BC]):-!,append(B,C,BC).
append([],L,L).
このようにLast callを効果的に生かすと、スタックの使用を押え、実行も早いプログラムにすることができます。 前掲の「 write_n/1 」はローカルスタックが全く延びずに実行することができます。
(3)ガベージコレクション

AZ-Prologは、ヒープ領域・アトム領域・グローバルスタックのガベジコレクション(ちり集め:GC)がそれぞれの領域が不足した場合に起動されます。

グローバルスタックは、バックトラック時に解放されますが、前掲の「 write_n/1 」のようにバックトラックを起こさずに実行するものに関しては、この節の中に現れたグローバル変数が解放されません。(変数Ⅹがグローバル変数の扱いとなる)
その結果、グローバル変数領域が不足した時に、必要な変数セルとそうでない変数セルを区分けし、前者のみを回収する処理(グローバルGC)がおこなわれます。
この機構のために「 write_n/1 」は、引数がいくら大きい数値であっても、スタックオーバーフローを起こさずに動くことができるのです。
尚、プログラム全体の流れの中で、部分的にバックトラックを引き起こすことで、グローバルスタックの解放を計画的に行ない、グローバルGCの発生をおこえることができます。

write_n1(X) :- write_n(X),fail.
     
write_n1(_).

「 write_n/1 」の中でグローバルスタックを多量に使用した後、「 fail/0 」で解放し、GCが発生する前に解放することができます。(ただし、①の中でGCが発生しないという事を前提とします)

10-6.エラー・メッセージ一覧

1 Syntax error 構文エラー。
2 Can't see the file 指定されたファイルをリードオープンできない。
3 Can't tell the file 指定されたファイルをライトオープンできない。
4 End of file encountered ファイルエンドを越えてリードしようとした。
5 Illegal file name ファイル名が正しく指定されていない。
6 Too many variables 節または項中の変数が多すぎる。
7 Too complex term 項が複雑すぎる。
8 builtin or C pred exist 組込述語が既に存在しているのにそれと同じ述語名・アリティを持つユーザ述語あるいはシステム述語を定義しようとした。
9 Illegal argument supplied 組込述語に対して正しくない引き数が与えられた。
10 Illegal Goal 整数あるいは未代入変数をゴールとして実行しようとした。
11 Illegal clause 節として認められない。
12 Illegal define tag システムエラー。
13 Illegal throw tag throw述語の引数のタグ指定が不正だった。
14 Illegal catch tag catch述語の引数のタグ指定が不正だった。
15 unknown predicate call unknown(_,error)を実行後定義されてないゴールを実行しようとした。
16 Heap area exhausted ヒープ領域(プログラムを入れておく領域)がオーバーフローした。
17 Trail stack overflow トレールスタックがオーバーフローした。
18 Global stack overflow グローバルスタックがオーバーフローした。
19 Local stack overflow
ローカルスタックがオーバーフローした。
20 Malloc failed メモリアロケーションが出来ない。
21 No more break ブレークレベルが深くなりすぎてこれ以上ブレーク出来ない。
22 Evaluation error: zero_divisor 0による除算を実行しようとした。
23 Too complex arithmetic 数式が複雑すぎて評価出来ない。
24 Evaluation error: Arithmetic Overflow フロート演算の結果が大きすぎる。
25 Evaluation error: Arithmetic Underflow フロート演算の結果が小さすぎる。
26 Illegal Arithmetic 値のセットされていない変数などが入った式を評価しようとした。
27 Illegal character code 漢字コードにないキャラクタコードを指定した。
28 Edit buffer no space エディタバッファがオーバーフローした。
29 Kill buffer no space キルバッファがオーバーフローした。
30 out of buffer  e_jump/1 でバッファ内にない位置を指定した。
31 ^Gerror CTRL-G がコンソールから入力された。
32 Search string is too long 検索しようとした文字列が長すぎる。
35 Instantiation error 初期化をせず演算を実行しようとした。
36 Type error: integer expected 変数は整数のみ対応。
37 Type error: float expected 変数は実数のみ対応。
38 Type error: number expected 変数は数値のみ対応。
39 Type error: not evaluable 演算式などが評価できなかった。
40 Evaluation error: float_overflow 実数がオーバーフローした。
41 Evaluation error: int_overflow 整数がオーバーフローした。
42 Evaluation error: undefined 変数値が定義域ではない。
43 Evaluation error underflow 変数値がアンダーフローした。
44 Evaluation error: random seed not initialized 乱数のシードが初期化されていない。
45 Type error: predicate_indicator expected 変数は述語指定子(pred/アリティ)のみ対応。
46 Type error: atom expected 変数は文字列のみ対応。
47 Type error: character expected 変数はアトムのみ対応。
48 Type error: list expected 変数はリストのみ対応。
49 Type error: variable expected 変数は未代入変数のみ対応。
50 Type error: byte code expected 変数はバイトコードのみ対応。
51 Atom area exhausted アトムの文字列格納領域が不足した。
52 Feature name already exists  同じ素性が二度以上登場する
53 Feature name has to be an atom  素性がアトムではない
54 Feature and non-feature mixed  <素性と値の対>と素性以外の項とが混在している
55 Typed FS: Type already exists 型がすでに定義されている
56 Typed FS: Attribute already exists 素性がすでに定義されている
57 Typed FS: Supertype undefined 継承元の型が未定義
58 Typed FS: Same type appears twice in supertypes 継承元に同じ型が二度以上登場する
59 Typed FS: Attribute value has an inconsistent type 素性値の型が不整合
60 Typed FS: Unification result not unique 型を単一化した結果が一意に定まらない
61 Typed FS: Attribute-Type is not defined 素性の型が未定義
62 Typed FS: Type&FStructure is inconsistent 型と素性構造が不整合
200 user errors limit  error/1 でユーザエラーの限界を越えた。
225 abort  abort/0 を実行するとこのエラーが発生した事になり errorset/2 で受け止める事が出来る。

10-7.エデイタ(AzEdit)コマンドー覧

カーソルの移動
CTRL-F カーソルを一文字前に移動 (Forward character)
CTRL-B
カーソルを一文字後ろに移動 (Backward character)
CTRL-N カーソルを一行下に移動 (Next line)
CTRL-P カーソルを一行上に移動 (Previous line)
ESC-F カーソルを現在の単語の次に移動 (Forward word)
ESC-B カーソルを一つ前の単語の先頭に移動
(Backward word)
CTRL-A
カーソルを行の先頭に移動  
CTRL-E カーソルを行の最後に移動  
CTRL-V 次の画面を表示  
CTRL-Z 前の画面を表示 (End of line)
ESC-< カーソルをテキストの先頭に移動 (View the next screen)
ESC-> カーソルをテキストの最後に移動  
CTRL-X CTRL -X カーソルとマークの交換 (Exchange)
ESC-Space カーソルの位置にマークを付ける  
挿入と削除
Return NLをカーソルの前に挿入  
CTRL-O NLをカーソル位置に挿入 (Open line)
Tab タブをカーソルの前に挿入  
CTRL-Q 特殊文字の挿入 (Quoted insert)
CTRL-D カーソル位置の文字を削除 (Delete character)
BS,CTRL -H カーソルの前の文字を削除 (Back Space)
ESC-D カーソルのある単語を削除 (Delete word)
ESC-BS カーソルの一つ前の単語を削除  
CTRL-K カーソルより右を削除 (Kill line)
CTRL-W カーソルとマークの間を削除 (Kill region)
CTRL-Y ESC-D,CTRL-K,CTRL-Wで削除したテキストをカーソルの前に挿入 (Yank)
探索と置換
CTRL-S文字列ESC 前向きの探索 (Search)
CTRL-R文字列ESC 後ろ向きの探索 (Reverse search)
CTRL-S CTRL-S 同じ文字列の前向き探索  
CTRL_RCTRL-R 同じ文字列の後ろ向き探索  
ESC_R 文字列1ESC
文字列2ESC
文字列1を文字列2に置き換える (Replace)
ESC-Q 文字列1ESC
文字列2ESC
文字列1を文字列2にキーボードからの指示に従い置き換える (Query replace)
ファイル操作
CTRL-X CTRL-V ファイル名 ファイルをバッファに読み込む (Visit file)
CTRL-X CTRL-I ファイル名 ファイルをバッファに読み込む (Insert file)
CTRL-X CTRL-W ファイル名 テキストをファイルに書き出す (Write file)
プログラム領域への転送
CTRL-X CTRL-S テキスト全体のreconsult  
CTRL-XS 領域のreconsult  
バッファの領域確保・切替・切り離し
CTRL-C バッファの切替  
CTRL-X CTRL-B バッファの切替  
CTRL-X CTRL-C バッファを切り離し(領域開放)  
AzEditの終了
CTRL-X CTRL-Z PROLOGへ戻る  
CTRL-XZ 画面の下の部分にスクロール領域を設定してPROLOGへ戻る  
その他のコマンド
CTRL-L カーソルを中心に画面を再配置  
ESC-+ AzEditの使用する行数を一行増やす  
ESC— AzEditの使用する行数を一行減らす  
ESC-W AzEditの使用する行数を最大にする  
ESC-U 単語を大文字に変換 (Upper case)
ESC-L 単語を小文字に変換 (Lower case)
ESC-C 単語を先頭だけ大文字に変換 (Capitalize)

10-8.コンソール ヒストリ、テンプレートコマンド一覧

ヒストリー
CTRL-X ヒストリーの表示
テンプレート
CTRL-F 現在の行にテンプレートから1文字コピーする
CTRL-A 現在の行にテンプレートに残っている全ての文字をコピーする
CTRL-E テンプレート内の1文字をスキップする
CTRL-W 挿入モードに入る。もう1度押すと挿入モードを解除する
CTRL-T 現在の行の内容をテンプレートにコピーする
CTRL-Q 現在行の先頭まで戻り最初の2文字をスキップする
CTRL-U 現在のテンプレートより一つ古いヒストリーをテンプレートにコピーし同時に現在行の最初からコピーする(CTRL-A) (最初のCTRL-UはCTRL-Aと同じ)
CTRL-N 現在のテンプレートより一つ新しいヒストリーをテンプレート にコピーし同時に現在行の最初からコピーする(CTRL-A)

10-9.ISO対応一覧

No. ISO述語 AZ-Prolog
対応
1 !/0  *1
2 **/2 
3 */2 
4 +/2 
5 ,/2   
6 -/1 
7 -/2 
8 (//)/2 
9 (/¥)/2 
10 ;/2 
11 </2 
12 <</2 
13 =/2 
14 =:=/2 
15 =</2 
16 ==/2 
17 =¥=/2 
18 >/2 
19 >=/2 
20 >>/2 
21 @</2 
22 @=</2 
23 @>/2 
24 @>=/2 
25 ¥+/1 
26 (¥/)/2 
27 ¥/1 
28 ¥=/2
29 ¥==/2
30 truncate/1
31 log/1
32 abolish/1
33 abs/1
34 arg/3
35 assert/1
36 assert/2
37 asserta/1
38 assertz/1
39 atan/1
40 atan2/2   
41 at_end_of_stream/0  
42 at_end_of_stream/1  
43 atom/1
44 atom_chars/2
45 atom_codes/2
46 atom_concat/3
47 atomic/1
48 atom_length/2
49 bagof/3
50 call/1
51 catch/3   
52 ceiling/1
53 char_code/2
54 char_conversion/2
55 clause/2
56 close/1
57 close/2  
58 compound/1
59 copy_term/2
60 cos/1
61 current_char_conversion/2
62 current_input/1  
63 current_op/3
64 current_output/1  
65 current_predicate/1  
66 current_prolog_flag/2
67 discontiguous/1   
68 dynamic/1  
69 ensure_loaded/1
70 exp/1
71 fail/0
72 findall/3
73 float/1
74 float_fractional_part/1
75 float_integer_part/1
76 floor/1
77 flush_output/0
78 flush_output/1  
79 functor/3
80 get_byte/1   
81 get_byte/2   
82 get_char/1
83 get_char/2
84 get_code/1
85 get_code/2
86 halt/0
87 halt/1
88 include/1   
89 initialization/1  
90 integer/1
91 is/2
92 mod/2
93 multifile/1   
94 nl/0
95 nl/1
96 nonvar/1
97 number/1
98 number_chars/2
99 number_codes/2
100 once/1
101 op/3
102 open/3
103 open/4  
104 peek_byte/1  
105 peek_byte/2  
106 peek_char/1  
107 peek_char/2  
108 peek_code/1  
109 peek_code/2  
110 put_byte/1  
111 put_byte/2  
112 put_char/1 
113 put_char/2 
114 put_code/1
115 put_code/2
116 read/1
117 read/2
118 read_term/2  
119 read_term/3  
120 rem/2
121 repeat/0
122 retract/1
123 round/1
124 set_input/1  
125 setof/3
126 set_output/1  
127 set_prolog_flag/2
128 set_stream_position/2  
129 sign/1
130 sin/1
131 sqrt/1
132 stream_property/2  
133 sub_atom/5
134 throw/1
135 true/0
136 unify_with_occurs_check/2
137 var/1
138 write/1
139 write/2
140 write_canonical/1
141 write_canonical/2
142 writeq/1
143 writeq/2
144 write_term/2  
145 write_term/3  

   *1 詳細は!/0リファレンス参照

«ご注意»
(1)本サイトの内容の一部を転載する場合は「AZ-Prologのマニュアルサイトからの転載」とご明示ください。
(2)本サイトの内容について予告なしに変更することがあります。
(3)本サイトの内容につきましては、万全を期して作成致しておりますが、万一誤り、お気付きの点がございましたら、ご連絡下さいますようお願い致します。
(4)運用した結果の影響につきましては、(3)にかかわらず責任を負いかねますのでご了承下さい。