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

如何将文件中的数据读入Prolog,prolog,wumpus-world,dcg,Prolog,Wumpus World,Dcg,我正在使用SWI Prolog创建Wumpus World项目。我应该从一个.txt文件中读取黄金、矿坑和Wumpus的位置,该文件如下所示: GOLD 3 2 WUMPUS 3 3 PIT 2 1 PIT 3 4 其中单词表示对象,第一个数字表示对象的x位置,第二个数字表示对象的y位置。我知道如何打开文件并从中读取,我只是不知道如何告诉我的程序GOLD 3 2意味着GOLD需要位于(3,2)。您需要打开文件,读取其中的行,然后将每行拆分为您想要使用的术语。然后,您可以

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

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

其中单词表示对象,第一个数字表示对象的x位置,第二个数字表示对象的y位置。我知道如何打开文件并从中读取,我只是不知道如何告诉我的程序GOLD 3 2意味着GOLD需要位于(3,2)。

您需要打开文件,读取其中的行,然后将每行拆分为您想要使用的术语。然后,您可以将这些术语放在某个变量中或
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)
考虑使用,免费读取和解析文件。我将您的示例放入一个文件
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
,它的类型作为第一个参数,坐标作为第二个和第三个参数

我想,你将如何使用这是另一个问题。现在你可以问,“我在哪里有金子”:

或者“我在哪里有坑”

基于DCG的解决方案 我想在现有解决方案的基础上添加一个基于DCG的解决方案

DCGs的优势 使用DCGs执行此任务有几个主要优点:

  • 您可以轻松地以交互方式测试解析器,而无需修改单独的文件
  • 一个足够通用的DCG可以用来解析和生成测试数据
  • 了解此方法可能有助于更复杂的解析任务,这些任务不适合ECSV等预定格式
预备赛 以下代码采用以下设置:

示例查询 以下是几个例子:

?- phrase(token(T), "GOLD"). T = 'GOLD'. ?- phrase(token(T), "2"). T = '2'. ?- phrase(token(T), "GOLD 2"). false. 使用
phrase\u from\u file/2
将DCG应用于该文件,我们得到:

?- phrase_from_file(tokens(Ts), 'wumpus.data'). Ts = ['GOLD', '3', '2', 'WUMPUS', '3', '3', 'PIT', '2', '1', 'PIT', '3', '4'] . ?-来自_文件的短语_(令牌(Ts),'wumpus.data')。 Ts=['GOLD','3','2','WUMPUS','3','3','PIT','2','1','PIT','3','4']。 从这样的令牌列表中,很容易导出必要的数据,例如再次使用aDCG:

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) }. 数据([])-->[]。 数据([D|Ds])-->数据(D),数据(Ds)。 数据(黄金(X,Y))-->['gold'],坐标(X,Y)。 数据(wumpus(X,Y))-->['wumpus',],坐标(X,Y)。 数据(pit(X,Y))-->['pit'],坐标(X,Y)。 坐标(X,Y)-->原子数(X),原子数(Y)。 原子数(N)->[A],{atom_数(A,N)}。 我们可以将这些DCG一起用于:

  • 标记化文件或给定的字符列表
  • 解析标记以创建结构化数据
  • 示例查询:

    ?- 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)] . ?-来自_文件的_短语(令牌(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附带的过时的
    库(pio)
    版本不适用于设置为
    字符的
    双引号。如果您想在SWI Prolog中尝试此功能,请直接使用Ulrich提供的版本。

    回答正确(+1)。在SWI Prolog中有
    库(csv)
    ,这使得读取表格数据非常容易。请参阅我的答案。如果
    load\u loop/1
    中出现问题,这很容易导致文件句柄泄漏。例如,创建不符合预期格式的
    wumpus.data
    ,并尝试以下查询作为测试用例:
    ?-重复,加载('wumpus.data'),false。
    。这很快就会抛出:
    错误:资源不足:max\u文件
    。使用
    setup\u call\u cleanup/3
    在所有情况下安全关闭文件! ?- 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). $ cat wumpus.data GOLD 3 2 WUMPUS 3 3 PIT 2 1 PIT 3 4 ?- phrase_from_file(tokens(Ts), 'wumpus.data'). Ts = ['GOLD', '3', '2', 'WUMPUS', '3', '3', 'PIT', '2', '1', 'PIT', '3', '4'] . 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) }. ?- 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)] .