如何在 ECLiPSe 中读取大型 Prolog 文件?

How to read large Prolog files in ECLiPSe?

我通过 eclipse 生成了一个大的路径文件。每行包含一个子句,用于 27 个点的列表。

$ wc -l snake_points.pl
240917 snake_points.pl

$ ls -lh snake_points.pl
-rw-rw-r-- 1 carl carl 72M Sep  6 02:39 snake_points.pl

$ head -n 1 snake_points.pl 
snake_points([(2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 2), (2, 1, 1), (2, 1, 0), (2, 2, 0), (2, 2, 1), (2, 2, 2), (1, 2, 2), (0, 2, 2), (0, 1, 2), (0, 0, 2), (0, 0, 1), (0, 1, 1), (0, 1, 0), (0, 2, 0), (0, 2, 1), (1, 2, 1), (1, 2, 0), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 0, 2), (1, 0, 1), (1, 0, 0), (0, 0, 0)]).

但是,我无法将文件加载到内存中(即使有 8G 堆):

$ time eclipse -f snake_points.ecl -e 'halt.'
*** Overflow of the global/trail stack in spite of garbage collection!
You can use the "-g kBytes" (GLOBALSIZE) option to have a larger stack.
Peak sizes were: global stack 8388576 kbytes, trail stack 59904 kbytes

________________________________________________________
Executed in  128.05 secs   fish           external 
   usr time  122.92 secs  297.00 micros  122.92 secs 
   sys time    5.01 secs   37.00 micros    5.01 secs 

将此与 swipl 进行比较:

$ time swipl -f snake_points.pl -g 'halt.'

________________________________________________________
Executed in   53.56 secs   fish           external 
   usr time   53.27 secs  272.00 micros   53.27 secs 
   sys time    0.28 secs   41.00 micros    0.28 secs 

两者都不令人印象深刻,但我希望 ECLiPSe 能够在合理的内存量下完成。

这是预期的行为吗?可以做什么?

我知道解决方案可能是“使用数据库”或 EXDR,但这难道不能高效地完成吗?

您是否尝试过更改点表示法?使用 ','/2 来表示每个元组具有两个以上元素的元组是一个坏主意。注意:

[eclipse 30]: write_canonical((1,2,3)).
','(1, ','(2, 3))
Yes (0.00s cpu)

试试看,例如p(1,2,3)。这应该会稍微降低内存要求并可能有所作为。

问题是您不仅在读取数据,您还试图将其编译为具有 240917 个子句的单个谓词,而编译器确实不是为这种用法而构建的。

您可以从数据文件中逐一读取和断言子句,如下所示:

assert_from_file(File) :-
        open(File, read, S),
        repeat,
            read(S, Term),
            ( Term == end_of_file ->
                true
            ;
                assert(Term),
                fail
            ),
        !, close(S).

这会在有限的时间内加载您的数据

?- assert_from_file("snake_points.pl").
Yes (19.38s cpu)

然后您可以按预期调用结果谓词

?- snake_points(X).
X = [(2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 2), (2, 1, 1), (2, 1, 0), (2, 2, 0), (2, 2, 1), (2, 2, 2), (1, 2, 2), (0, 2, 2), (0, 1, 2), (0, 0, 2), (0, 0, 1), (0, 1, 1), (0, 1, 0), (0, 2, 0), (0, ..., ...), (..., ...), ...]
Yes (0.04s cpu, solution 1, maybe more) ? ;

但是无论您想解决什么问题,这看起来都不是最有希望的方法...