4

SWI-Prolog を使用して Wumpus World プロジェクトを作成しています。次のような .txt ファイルから金、ピット、ウンパスの場所を読み取ることになっています。

   GOLD 3 2
   WUMPUS 3 3
   PIT 2 1
   PIT 3 4

単語がオブジェクトを識別する場合、最初の数字はオブジェクトの x 位置を識別し、2 番目の数字はオブジェクトの y 位置を識別します。ファイルを開いてそこから読み取る方法は知っていますが、GOLD 3 2 が金を (3, 2) に配置する必要があることをプログラムに伝える方法がわかりません。

4

3 に答える 3

6

DCG ベースのソリューション

既存のソリューションにDCG ベースのソリューションを追加したいと考えています。

DCG の利点

このタスクに DCG を使用することには、いくつかの大きな利点があります。

  • 別のファイルを変更することなく、パーサーをインタラクティブに簡単にテストできます。
  • 十分に一般的な DCG を使用して、テスト データの解析と生成を行うことができます。
  • このメソッドを知っていると、CSV のような所定の形式に適合しない、より複雑な解析タスクに役立つ場合があります。

予選

次のコードは、次の設定を前提としています。

:- set_prolog_flag(double_quotes, chars)。

DCG の操作が読みやすくなるため、この設定をお勧めします。

建築用ブロック:token//1

まず、トークンの意味を簡単に定義します。

トークン(T) -->
        アルナム(L)、
        token_(Ls)、
        !, % 単一解: 最長一致
        { atom_chars(T, [L|Ls]) }.

alnum(A) --> [A], { char_type(A, alnum) }.

token_([L|Ls]) --> alnum(L), token_(Ls).
token_([]) --> [].

サンプルクエリ

以下にいくつかの例を示します。

?- フレーズ(トークン(T), "GOLD" ).
T = 'ゴールド' .

?- フレーズ(トークン(T), "2" ).
T = '2' .

?- フレーズ(トークン(T), "GOLD 2" ).

最後の例は、空白をトークンの一部にできないことを明確にしています。

空白

次のシーケンスを空白と見なします。

スペース --> []。
スペース --> スペース、スペース。

スペース --> [S], { char_type(S, スペース) }.

解決

したがって、空白で区切られた一連のトークンは次のようになります。

トークン ([]) --> []。
tokens([T|Ts]) --> token(T)、スペース、tokens(Ts)。

以上です!

Ulrich Neumerkel の先見の明を使用して、この DCG を filesに透過的に適用できるようになりlibrary(pio)ました。

ここにあるwumpus.data

$ 猫 wumpus.data
ゴールド 3 2
ウンパス 3 3
ピット 2 1
ピット 3 4

を使用phrase_from_file/2して DCG をファイルに適用すると、次のようになります。

?-phrase_from_file(トークン(Ts)、「wumpus.data」)。
Ts = ['GOLD', '3', '2', 'WUMPUS', '3', '3', 'PIT', '2', '1', 'PIT', '3', '4' ] .

このようなトークンのリストから、たとえば再びDCGを使用して、必要なデータを簡単に取得できます。

データ([]) --> [].
data([D|Ds]) --> data_(D), data(Ds).

data_(gold(X,Y)) --> ['GOLD'], coords(X, Y).
data_(wumpus(X,Y)) --> ['WUMPUS'], coords(X, Y).
data_(pit(X,Y)) --> ['PIT'], coords(X, Y).

coords(X, Y) --> atom_number(X), atom_number(Y)。

atom_number(N) --> [A], { atom_number(A, N) }.

これらの DCG を一緒に使用して、次のことを行うことができます。

  1. ファイルまたは指定された文字リストをトークン化する
  2. トークンを解析して構造化データを作成します。

サンプルクエリ:

?-phrase_from_file(tokens(Ts), 'wumpus.data'),
   フレーズ(データ(Ds)、Ts)。
Ts = ['GOLD', '3', '2', 'WUMPUS', '3', '3', 'PIT', '2', '1'|...],
Ds = [ゴールド(3, 2), ウンパス(3, 3), ピット(2, 1), ピット(3, 4)] .

この多彩なメカニズムの詳細については、を参照してください。


1 SWI-Prolog には の古いバージョンが同梱されており、 を に設定する library(pio)と動作しません。SWI-Prolog でこれを試したい場合は、Ulrich が提供するバージョンを直接使用してください。double_quoteschars

于 2016-10-22T08:29:08.117 に答える
1

無料でファイルの読み取りと解析を行うために、library(csv)の使用を検討してください。私はあなたの例をファイルに入れましたwumpus.txt:

$ cat wumpus.txt 
GOLD 3 2
WUMPUS 3 3
PIT 2 1
PIT 3 4

ライブラリのドキュメントにはいくつかのコード例があります。これは最小限の例であり、トップレベルからそのままです。

?- use_module(library(csv)).
true.

?- csv_read_file("wumpus.txt", World, [separator(0' ), functor(location)]),
   forall(member(L, World), assertz(L)).
World = [location('GOLD', 3, 2), location('WUMPUS', 3, 3), location('PIT', 2, 1), location('PIT', 3, 4)].

重要: 区切り文字がスペース文字であることを示す方法は、オプションを追加することlocation(0' )です。0'閉じ括弧の前後のスペースは重要です!

これで、データベースにテーブルができました。このテーブルにはlocation/3、最初の引数として Type があり、2 番目と 3 番目の引数として座標があります。

これをどのように使用するかは別の問題だと思います。今、あなたは「どこに金を持っていますか?」と尋ねることができます:

?- location('GOLD', X, Y).
X = 3,
Y = 2.

または、「どこに穴がありますか」?

?- location('PIT', X, Y).
X = 2,
Y = 1 ;
X = 3,
Y = 4.
于 2016-10-21T08:13:51.283 に答える
0

ファイルを開いてその行を読み、それぞれの行を使用したい用語に分割する必要があります。次に、用語を変数に配置するかassert/1、動的データベースに配置できます。以下の例では、動的述語を使用してそれらをデータベースにアサートしますlocation/3

:- dynamic location/3.

load(File) :-
    setup_call_cleanup(
         open(File, read, Stream),
         load_loop(Stream),
         close(Stream)
         ).


load_loop(Stream) :-
    read_line_to_string(Stream, String),
    (String == end_of_file ->
         true
     ;
     split_string(String, " ", " ", [ItemS, XS, YS]),
     atom_string(Item, ItemS),
     term_string(X, XS),
     term_string(Y, YS),
     assertz(location(Item, X, Y)),
     load_loop(Stream)
    ).

show_locations :-
    forall(location(Item, X, Y),
           format('~p is at (~d, ~d)~n', [Item, X, Y])).

入力が wumpus.txt にあると仮定すると、次のようになります。

bash-3.2$ swipl -l wumpus.pl
'GOLD' is at (3, 2)
'WUMPUS' is at (3, 3)
'PIT' is at (2, 1)
'PIT' is at (3, 4)
于 2016-10-21T02:45:12.303 に答える