O-Prologの仕様、覚書

  • 1
    いいね
  • 0
    コメント

はじめに

自作Prolog処理系のO-Prologについてその仕様などを文書化することにしました。O-PrologはISO-Prologを参考にしつつAZ-Prologのサブセットを目指して制作しているものです。この記述は甚だ中途半端なものですが、五月雨式に追加、詳細な記述を目指しております。

起動オプション

Windowsであればコマンドプロンプトよりoplと入力することにより起動します。Linuxであれば./oplで起動します。スタートアップファイルを読み込ませて起動する場合には -c でファイル名を与えます。



./ opl -c init.pl

linuxバージョン、ラズパイバージョンのREPLはデフォルトで編集可能になっています。Emacsなどで使うために編集機能が不要の場合には -r オプションで起動してください。

./opl -r

対話的動作

起動すると|(縦棒)記号が表示されます。これがO-Prologのプロンプトです。この状態で受け取ったものは述語定義であると解釈してメモリに記憶されます。|に続いて?-と入力してから入力したものは処理系に対しての質問となります。いずれの場合には最後に .(ピリオド)記号が必要となります。質問の場合にはyesかnoかの結果が返されます。


| human(taro).

| ?- human(taro)).
yes

入力したものを再度入力したい場合にはCTRL+yで履歴を呼び出すことができます。これは編集可能です。履歴を遡りすぎて戻したいときにはCTRL+vです。

Prologコードをあらかじめエディタを使ってファイルにしておき、それを読み込む場合には次のようにします。

| ?- consult('init.pl').
yes
|

既に読み込み済みのコードを上書きをする場合にはreconsultを使います。
| ?- reconsult('init.pl').
yes

reconsultと入力するのは煩わしいのでリストで入力することも可能です。
| ?- ['init.pl'].
yes
|

これらにより読み込んだコードはlisting述語により表示することができます。
| ?-listing.
yes_or_no(X) :- repeat,write(yes or no >),read(X),X==yes;X==no,!.
yes
|

linux版には組み込みのCUIエディタがあります。CPUパワーの小さいラズパイでの編集を目的としています。詳細は下記を参照してください。
http://qiita.com/sym_num/items/4af619de02191c95e3b9

事実

太郎は人間であるという事実は述語として表現されます。

human(taro).

推論規則

人間は誤りを犯すものである、ということは推論規則として表現されます。次のような節となります。

節   ↓通称メダカ記号
error(X) :- human(X).
↑      ↑
頭部     本体部

大文字のアルファベットで始まる記号は変数として扱われます。

アトム

humanやtaroという記号はアトムと呼ばれます。アトムとして利用可能な文字はISO標準のものに加え、UnicodeまたはシフトJISが可能となっています。

アルファベット abcdefghijklmnopqrstuvwz ABCDEFGHIJKLMNOPQRSTUVWXYZ
特殊記号 #$&*+-/:.<=>?@^~\
数文字 1234567890

先頭はアルファベットである必要があります。
特殊記号を含むアトムである場合にはシングルクオートでくくる必要があります。

アトムにシングルクオートを含む場合には次のように記述します。
例 'I don''t know'

| ?- X = 'I don''t know'.
X = I don't know
yes
| 

独自拡張 Unicode(UTF8) またはシフトJIS 例 人間 太郎
Winodws版は初期設定はシフトJISです。Linux版はUnicodeです。
組込み述語 char_set/1により切り替えることができまs。
char_set(unicode). 以後Unicodeでの動作となります。
char_set(sjis).  以後シフトJISでの動作となります。

変数

先頭が大文字のアルファベットで始まるアトムは変数となります。

例 X Y A1 Bcd

先頭がアンダーバーで始まるアトムも変数となります。

例 _var _あれ

整数と浮動小数点数が扱えます。整数は無限多倍長整数(BIGNUM)が扱えます。

| ?- X is sin(3.14).
X = 0.001592652916486828
yes
| ?- Y is 3**100.
Y = 515377520732011331036461129765621272702107522001
yes
|

浮動小数点数には指数表示が可能です。
例 1.002E3

| ?- X is 1.002E3.
X = 1002.0
yes
| 

浮動小数点数は小数部を省略することはできません。
例 1. × 1.0 ○

| ?- X is 1.
X = 1
yes
| ?- X is 1.0.
X = 1.0
yes
| 

整数につき2進、8進、16進表記が使えます。


0o1234 (8)
0b0101 (2)
0xFACE (16)

O-Prolog Ver0.58
| ?- X is 0o1234.
X = 668
yes
| ?- X is 0b0101.
X = 5
yes
| ?- X is 0xFACE.
X = 64206
yes
| 

リスト

Lispと同様にリストが使えます。ドット記法は|(縦棒)で表現します。以下、Lispとの対比表です。

Prolog       Lisp
[1,2,3]     (1 2 3)
[1,2|3]     (1 2 . 3)
[1,2,[3,4]]  (1 2 (3 4))
[a|b]       (a . b)

演算子記号

次の記号が演算子として使用されています。

":-" "-->" "," "?-" "->" "/\" "=.." "==" "\==" "@<" "@=<" "@>" "@>="
"=:=" "=/=" "=\=" "<" "=<" ">"
">=" "<<" ">>" "**" "\\=" "^"
"=" "+" "-" "*" "//" "/" "."

演算子

:- 節を定義します。左側に頭部、右側に本体部の述語が入ります。
human(X) :- error(X).

?- 質問をします。続けて質問したい述語を記述します。
-? human(taro).

算術式

is述語を使った場合、右辺は評価計算され左辺にユニフィケーションします。この場合の算術式については下記の通りです。

定数

pi 円周率の近似値です。3.14159265358979

関数 数演算子

+ 加算
- 減算
* 乗算
/ 除算
// 整数除算
** 累乗
^ 累乗
abs(X) 絶対値
sin(X) 正弦
cos(X) 余弦
tan(X) 正接
asin(X) 正弦の逆関数
acos(X) 余弦の逆関数
atan(X) 正接の逆関数
exp(X) 指数関数
log(X) 対数関数(底はe)
floor(X) Xに最も近い整数
ceiling(X) 小数部の切り上げ
truncate(X) ゼロから近づいた時の最大の整数
float(X) 整数の浮動小数点数への変換
sign(X) 正負符号 プラスなら1、マイナスなら-1、ゼロなら0
sqrt(X) 平方根
round(X) まるめ
gcd(X,Y) 最大公約数
lcm(X,Y) 最小公倍数
mod(X,Y) 剰余
rem(X,y) 剰余
X /\ Y 論理積
X \/ Y 論理和
X xor Y 排他的論理和
X iand Y 包含的論理積

組込み述語

op
!

assert/1
述語、節をデータベースの最後に追加登録します。

| ?-assert(human(taro)).
yes
| ?-listing.
human(taro).
yes
| 

asserta/1
述語、節をデータベースの先頭に追加登録します。

assertz/1
assertと同じです。最後に追加登録します。

retractall/1
引数に与えられた述語をすべて削除します。

abolish/1
引数に与えられた述語、節を削除します。述語名とその引数の数をスラッシュ記号とともに渡します。

| foo(1).
| foo(2).
| ?-listing.
foo(1).
foo(2).
yes
| ?-abolish(foo/1).
yes
| ?-listing.
yes
| 

read/1
入力データを引数にユニファイします。入力の最後にはピリオドが必要です。

write/1
引数を画面表示します。

put/1
引数で与えられた整数を文字コードとみた場合tの文字を表示します。

| ?-put(80).
Pyes
|

get/1
1文字入力し、その文字コードと引数をunifyします。空白文字は無視します。
| ?-get(X).
a
X = 97
yes
|

get0/1
1文字入力し、その文字コードと引数をunifyします。空白文字も1文字として入力します。
| ?-get0(X).
      (スペースを入力しています。)
X = 32
yes
|

get_char/1
1文字を標準入力から得て、1文字のアトムを生成して引数とunifyします。
Windows版はSJISに、Linux版はunicodeに対応しています。

get_char/2
第一引数にストリーム、第二引数がunifyする変数が入ります。他はget_char/1と同じです。

get_code/1
1文字を標準入力から得て、その文字コードを生成して引数とunifyします。
Windows版はSJISに、Linux版はunicodeに対応しています。

get_code/2
第一引数にストリーム、第二引数がunifyする変数が入ります。他はget_code/1と同じです。

put_char/1
1文字のアトムを標準出力に表示します。

put_char/2
1文字のアトムをストリームへ出力します。第一引数にストリーム、第二引数にunifyする変数が入ります。

current_input(Stream)
現在使用中の入力ストリームを引数にunifyします。

current_output(Stream)
現在使用中の出力ストリームを引数にunifyします。

set_input(Stream)
入力ストリームを引数で与えられたものにセットします。

set_output(Stream)
出力ストリームを引数で与えられたものにセットします。

flush_output(Stream)
引数で与えられたストリームにつきバッファを書き出します。

flush_ouput
現在使用中の出力ストリームにバッファを書き出します。

nl/0
画面表示で改行をします。

tab/1
引数に与えられた数だけスペースを表示します。

fail/0
常に失敗します。

once/1
引数の述語を1度だけ実行します。バックトラックはしません。

not/1
引数の否定を返します。
| ?-not(true).
no
| ?-not(fail).
yes
|

true/0
常に成功します。

halt/0
処理系を終了します。

abort/0
実行を中断してプロンプトに戻ります。

errorset

errormode

listing/0
listing/1
引数無しに実行された場合には、assertされた節をすべて表示します。
引数として非数値アトムが与えられた場合には、そのアトムを述語名とする節を表示します。

functor/3
第1引数の述語の述語名と項に分解します。逆も可
| ?-functor(foo(1,2,3),X,Y).
X = foo
Y = 3
yes
|
| ?-functor(X,foo,3).
X = foo(v_1,v_2,v_3)
yes
|

arg/3
第2引数の第1引数番目が第3引数であれば真となります。
| ?-arg(2,f(X,t(a),t(b)),Y).
Y = t(a)
yes
|

debug

atom_length/2
アトムの長さを求めます。

| ?-atom_length('abc',X).
X = 3
yes

atom_concat
アトムを結合します。
| ?-atom_concat('abc','def',X).
X = abcdef
yes
|

findall/3
第2引数が真となる第1引数の値を第3引数に追加します。

| a(1).
| a(2).
| a(3).
| ?-findall(X,a(X),L).
L = [1,2,3]
yes
|

consult/1
引数の非数値アトムで指定されたファイルを読み込みます。

reconsult/1
ファイルを読み込みます。consultと違うのは定義を上書きするところです。

see/1
引数のアトムをファイル名とするファイルを入力ようにオープンする。

seen/1
入力ファイルをクローズする。

tell/1
引数のアトムをファイル名とするファイルを出力用にオープンする。

told/1
出力ファイルをクローズする。

trace/0
実行時のデバッグ情報を表示します。

プロンプトを表示しつつステップ実行をします。利用できるコマンドは下記の通りです。

return key: creep
a: abort to REPL
c: creep
d: display goal
e: end of intepreter
h: help
n: notrace
s: skip to next spy point
?>

notrace/0
traceを解除します。

spy/1
引数に与えられた非数値アトムを述語名とする述語が実行された場合に、その述語につきデバッグ情報を表示します。項数とともに次のように指定します。

 spy(foo/3).

spy/0
spy/1で指定されたスパイポイントを表示します。

nospy/1
spyによるスパイポイントを解除します。

例 
 nospy(foo/3)

nospy/0
spyにより設定されたスパイポイントをすべて解除します。

atom
integer/1
引数が整数のときに真、そうでなければ偽を返します。

float/1
引数が浮動小数点数であるときに真、そうでなければ偽を返します。

number/1
引数が数であるときに真、そうでなkれば偽を返します。

compound/1
引数が複合項であるときに真、そうでなければ偽を返します。

| ?-compound(human(taro)).
yes
| ?-compound([1,2,3]).
yes
| 

var/1
引数が未束縛の変数のときに真、そうでなければ偽を返します。

| ?- var(X).
yes
| ?- X is 3,var(X).
no
| 

nonvar/1
引数が未束縛の変数のときに偽、そうでなければ真を返します。

| ?-nonvar(X).
no
| ?- X is 3,nonvar(X).
X = 3.
yes
| 

atomic/1
引数が変数以外のアトムである場合に真、そうでなければ偽を返します。

list/1
引数がリストである場合には真、そうでなければ偽を返します。

| ?-list([1,2,3]).
yes
| 

length/2
第一引数のリストの長さを第二引数にユニファイします。

| ?-length([1,2,3],X).
X = 3
yes
| 

gbc/0 gbc/1
ガーベジコレクションを制御します。引数無しで呼ばれた場合にはガーベジコレクションを起動します。引数にnoを与えた場合にはガーベジコレクション起動時にメッセージを表示しなくなります。引数にyesを与えた場合にはガーベジコレクション起動時にメッセージを表示します。初期設定は表示するです。

| ?-gbc.
enter GBC free=9999739
exit  GBC free=9999751
yes
| ?-gbc(yes).
yes
| ?-gbc(no).
yes
| ?-gbc.
yes
| 

time/1
実行時間計測用の述語です。計測した述語を引数として与えます。

| ?-time(queens9).
[1,3,6,4,8,2,7,5,9]
...
[9,7,4,6,2,8,3,5,1]
Elapsed Time=0.135000 (second)
no
| 

char_set
char_code

atom_chars/2
第1引数のアトムをリストに分解したものを第2引数にunifyします。

atom_codes/2
第1引数のアトムを分解し、その文字コードをリストにしたものを第2引数にunifyします。
| ?-atom_codes(abc,X).
X = [97,98,99]
yes
|

name/2
アトムとリストとを相互に変換します。

| ?-name(abc,X).
X = [97,98,99]
yes
| ?-name(X,[97,98,99]).
X = abc
yes
| 

number_chars/2
第1引数の数を分解してリストにしたものを第2引数にunifyします。
| ?- number_chars(123,X).
X = ['1','2','3']
yes
|

number_cords
第一引数の数を分解して、その文字コードをリストにしたものを第2引数にunifyします。
| ?-number_codes(123,X).
X = [49,50,51]
yes

sexp/1
処理系のデバッグ用です。引数にyesを与えると述語や節をS式で表示します。noを与えると元に戻ります。

read_csv
append
member
retract
clause
between