如何将文件中的数据读入Prolog

cal*_*leb 4 prolog wumpus-world

我正在使用SWI-Prolog创建一个Wumpus World项目.我应该从.txt文件中读取金币,凹坑和Wumpus的位置,如下所示:

   GOLD 3 2
   WUMPUS 3 3
   PIT 2 1
   PIT 3 4
Run Code Online (Sandbox Code Playgroud)

在单词标识对象的情况下,第一个数字标识对象的x位置,第二个数字标识对象的y位置.我知道如何打开文件并从中读取,我只是不知道如何告诉我的程序GOLD 3 2意味着黄金需要位于(3,2).

mat*_*mat 6

基于DCG的解决方案

我想为现有的解决方案添加基于DCG的解决方案.

DCG的优点

使用DCG执行此任务有几个主要优点:

  • 您可以轻松地以交互方式测试解析器,而无需修改单独的文件.
  • 足够通用的DCG可用于解析以及生成测试数据.
  • 知道这种方法对于更复杂的解析任务可能会派上用场,这些任务不适合像CSV这样的预定格式.

预赛

以下代码假定设置:

:- set_prolog_flag(double_quotes, chars).

我建议使用此设置,因为它使DCG更易读.

积木: token//1

我们首先简单定义一个令牌的含义:

token(T) -->
        alnum(L),
        token_(Ls),
        !, % single solution: longest match
        { atom_chars(T, [L|Ls]) }.

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

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

示例查询

这里有一些例子:

?- phrase(token(T), "GOLD").
T = 'GOLD'.

?- phrase(token(T), "2").
T = '2'.

?- phrase(token(T), "GOLD 2").
false.

最后一个示例清楚地表明,空格不能是令牌的一部分.

空白

我们将以下序列视为空白:

spaces --> [].
spaces --> space, spaces.

space --> [S], { char_type(S, space) }.

因此,由空格分隔的一系列令牌是:

tokens([])     --> [].
tokens([T|Ts]) --> token(T), spaces, tokens(Ts).

就是这样!

我们现在可以透明地将这个DCG应用于文件,使用Ulrich Neumerkel的远见卓识library(pio):

这是wumpus.data:

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

使用phrase_from_file/2将DCG应用于文件,我们得到:

?- phrase_from_file(tokens(Ts), 'wumpus.data').
Ts = ['GOLD', '3', '2', 'WUMPUS', '3', '3', 'PIT', '2', '1', 'PIT', '3', '4'] .

从这样的令牌列表中,很容易得到必要的数据,例如再次使用DCG:

data([])     --> [].
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'),
   phrase(data(Ds), Ts).
Ts = ['GOLD', '3', '2', 'WUMPUS', '3', '3', 'PIT', '2', '1'|...],
Ds = [gold(3, 2), wumpus(3, 3), pit(2, 1), pit(3, 4)] .

有关此通用机制的更多信息,请参阅.


1请注意,SWI-Prolog附带过时版本library(pio),但不适用于double_quotes设置为  chars.如果您想使用SWI-Prolog试用,请直接使用Ulrich提供的版本.