3

次のプロローグベースを使用しましょう:

father(anakinSkywalker, princessLeia).
father(anakinSkywalker, lukeSkywalker).
saysOhNo(lukeSkywalker).

sdescienceloverは、シェル呼び出しから swi-prologでパターン マッチング ゴールの結果を表示する方法を尋ね、クエリを手動で変換して書き込みを発行するという回答を得ました。

swipl -q -s kb.pl -t "father(anakinSkywalker,X), writeln(X), false"

結果:

princessLeia
lukeSkywalker

これは、単一の自由変数を使用したクエリがいくつかある場合には問題なく機能しますが、それぞれを手動で変換するのは面倒です。また、各変数の名前とその結果を適切に出力したい場合は、すぐに非常に煩わしくなります。たとえば、クエリを実行するには、次のfather(AVariable, Another)ように記述する必要があります。

swipl -q -s kb.pl -t "father(AVariable,Another), write('AVariable='), write(AVariable), write(', Another='), writeln(Another), false"

結果:

AVariable=anakinSkywalker, Another=princessLeia
AVariable=anakinSkywalker, Another=lukeSkywalker

パイプからコマンドを供給しようとしましたが、うまくいきません(結果の書き込みがいつ終了したかを検出できないため、後でハングし、改行で回答が区切られません):

(echo "father(X,Y)."; while true; do echo ";"; done) | swipl -q -s kb.pl

結果 :

X = anakinSkywalker,
Y = princessLeia X = anakinSkywalker,
Y = lukeSkywalker.

swipl hangs here, and needs to be stopped with Control-C.

sedスクリプトを使用してクエリを前処理し、変数を大文字で出力するために必要なコードを追加できることはわかっていますが、たとえば 2 つの述語を満たす必要がある場合など、複雑なクエリを処理するにはかなりの作業が必要になります。

father(X,Y), saysOhNo(Y).

常に正しい結果を得るには、prolog 用のパーサーを作成する必要がありますが、prolog は対話的にこれを行う方法を既に知っているため、これは役に立たない作業です。

だからここに私の質問があります:GNUプロローグまたはSWIプロローグ(またはLinuxに簡単にインストールできる他の無料バージョン)に、インタラクティブに行うのと同じように、いくつかのクエリを実行して結果を出力するように指示する方法はありますか?各クエリを手動で入力 (またはコピーして貼り付け) するには?

編集 :一連のクエリをファイル (kb.plファイルまたは補助ファイル) に保存し、それらすべてを実行して、結果を表示する方法はさらに優れています。

4

4 に答える 4

3

これまでのところ、私が見つけた方法は次のとおりです。

gprolog

false's answerを使用して、kb.plファイルの先頭に次の行を追加する必要があることがわかりました。

a(_) :- fail.

を使用します./query.sh kb.pl "father(X,Y), saysOhNo(Y)"query.shは次のとおりです。

#!/bin/sh
echo "a(fail)." | gprolog --query-goal "consult('$1'), $2"

クエリがすぐに返されると (つまり、結果がないか、単一の結果であり、gprologそれが最後のものであることが検出された場合)、クエリが実行され、クエリが実行consult('kb.pl'), actual_query.され、コンソールにa(fail).余分なものが出力されます。noファイルの先頭に追加した false 述語。

gprologが何をすべきかを尋ねた場合(つまり、複数の結果、または単一の結果でgprolog最後の結果であることが検出できなかった場合)、これはクエリを実行し、すべての結果を出力するように要求する をconsult('kb.pl'), actual_query.読み取り、次にクエリを実行します。これらは単なるグループ化括弧であるため、コンソールに余分なものを出力するだけなので、クエリは と同等です。agprolog(fail).nofail.

xsb

を使用できます./query.sh kb.pl "father(X,Y), saysOhNo(Y)"query.sh

#!/bin/sh
(echo "consult('$1'), ${2%.}."; yes halt.) | xsb --noprompt --quietload --nobanner

xsbが次に何をするかを尋ねたときに、ユーザーが空でない文字列に続けてenterを入力すると、次の結果が表示されます。それ以外の場合は、現在のクエリに対するソリューションの検索が中止されます。したがって、yes halt.コマンドを使用して、空でない行の無限ストリームを入力します。xsbすべての結果をクエリに出力し ( を読み取るたびにhalt.、空でない文字列であるため、次の結果に進みます)、プロンプトに戻ります。それから、halt.それが受け取る以下は、終了するように伝えます。

swi-prolog

私はまだ解決策を見つけていません。

[暴言]プロローグの実装を構築する人々が、他のほとんどの言語で可能であるのと同じように、非対話的に使用することを実際に考えていれば、これはすべて非常に簡単になります.[/暴言]

于 2012-08-08T09:47:34.470 に答える
2

--query-goalGNUではコマンドライン オプションを使用できます。そのようです:

$エコーa | gprolog --query-goal 'X = 1 ; X = 2'
GNU プロローグ 1.4.1
ダニエル・ディアス
Copyright (C) 1999-2012 ダニエル・ディアス
| | ?- X = 1 ; X = 2。

X = 1 ? a

X = 2

はい
于 2012-08-01T13:48:42.383 に答える
1

あなたはあなたの問題の解決策を見つけたかもしれませんが、とにかく、ここに私のアプローチがあります。組み込み述語のbagofにいつでも再帰できます。あなたはそれがドキュメントで何をするかを読むかもしれません、このようにしてあなたはそれについてもっと学ぶでしょう。

swipl -q -s starwars.pl -t "bagof(X, Y^father(X,Y), BagOfFathers), bagof(Y, X^father(X,Y), BagOfChildren), writeln(BagOfFathers), writeln(BagOfChildren)."
[anakinSkywalker,anakinSkywalker]
[princessLeia,lukeSkywalker]

後でマッピングまたは必要なものとして処理することもできます。関係は1:1です(正しい表現方法かどうかはわかりませんが、取得していただければ幸いです)

于 2013-03-07T13:49:31.750 に答える
0

次の bash スクリプトを swi-prolog に使用できます。

#!/bin/sh

exec swipl -q  -f none -g "load_files([interface],[silent(true)])" \
         -t interface:get_args -- $*

これにより、ファイルがロードされinterface.pl、述語get_args/0
が呼び出されて、呼び出すことができるコマンド ライン引数が取得されます。

current_prolog_flag(argv, Arguments)

もちろん、ロードされた述語/ファイルの名前を変更できます。
引数はsilent(true)、イントロ テキストなどの情報メッセージを抑制します。

編集: 表示されるエラー メッセージは、おそらくinterface.plファイルがないためです (get_args/0 述語もありません)。(またはファイルに名前を付けます)とinterface置き換えるか、プロローグファイル内で補助述語を使用する必要があります(これはちょっときれいかもしれません)kbinterface:get_argskb:father(X,Y), saysOhNo(Y) run(X,Y):- father(X,Y), saysOhNo(Y)

于 2012-08-01T14:41:01.177 に答える