标签: swi-prolog

Prolog - 带有文件输入的DCG解析器

作为项目的一部分,我需要编写一个解析器,它可以读取文件并解析我可以在程序中使用的事实.

文件结构如下所示:

property = { el1 , el2 , ... }.  
Run Code Online (Sandbox Code Playgroud)

我最终想要的是:

property(el1).
property(el2).
...
Run Code Online (Sandbox Code Playgroud)

我这样读了我的文件:

main :-
       open('myFile.txt', read, Str),
       read_file(Str,Lines),
       close(Str),
       write(Lines), nl.

read_file(Stream,[]) :-
                       at_end_of_stream(Stream).

read_file(Stream,[X|L]) :-
                          \+ at_end_of_stream(Stream),
                          read(Stream,X),
                          parse(X),            % Here I call upon my parser.
                          read_file(Stream,L).
Run Code Online (Sandbox Code Playgroud)

现在我已经阅读了几本书和网上关于DCG的内容,但他们都解释了相同的简单例子,你可以生成句子,如"猫吃蝙蝠"等......当我想用它来做上面的例子时我惨遭失败.

我所做的是"解析"下面的行:

property = el1.
Run Code Online (Sandbox Code Playgroud)

property(el1).
Run Code Online (Sandbox Code Playgroud)

有了这个:

parse(X) :-
           X =.. List,    % Reason I do this is because X is one atom and not a list.
           phrase(sentence(Statement), List),
           asserta(Statement).

sentence(Statement) --> ['=', Gender, Person] , { …
Run Code Online (Sandbox Code Playgroud)

parsing prolog swi-prolog dcg

8
推荐指数
1
解决办法
4535
查看次数

SWI-Prolog中的catch/3和call_with_time_limit/2谓词

我想用

catch(:Goal, +Catcher, :Recover)
Run Code Online (Sandbox Code Playgroud)

目标在哪里

call_with_time_limit(+Time, :Goal)
Run Code Online (Sandbox Code Playgroud)

它搞砸了,我无法找到正确的方法来了解上述情况之一发生时间:

1)由于超时,目标停止了.

2)目标失败(有时候会失败).

我试过了:

(catch(call_with_time_limit(Time, Goal), Catcher, Recover) ->
(ground(Catcher), Catcher = time_limit_exceeded), **TIMEOUT ACTIONS**)
;
(**SUCCESS ACTIONS**))
;
**FAILURE ACTIONS**
)
Run Code Online (Sandbox Code Playgroud)

*编辑*

图案:

我使用以下模式:

((catch(call_with_time_limit(6,goal),
    Exception,
    true),(var(Exception);Exception=time_limit_exceeded))
->
    (var(Exception) -> writeln(succ) ; writeln(timeout))
;
    writeln(fail)
).
Run Code Online (Sandbox Code Playgroud)

该模式在4秒或更长时间内不起作用 - 它只是忽略了超时请求.

timeout prolog swi-prolog

8
推荐指数
1
解决办法
533
查看次数

在SWI-Prolog中编写宏

我试图在SWI-Prolog中为switch-statements实现一个简单的宏.

这是一系列条件陈述:

(X = a ->
    Output = case1;
X = b ->
    Output = case2;
X = c ->
    Output = case3).
Run Code Online (Sandbox Code Playgroud)

这是一个具有相同效果的等效(但速度要慢得多)的表达式:

switch(X, [
    a : (Output = case1),
    b : (Output = case2),
    c : (Output = case3)
])
Run Code Online (Sandbox Code Playgroud)

我在一个应用程序中使用了很多这样的谓词,但这会大大减慢它的速度.是否可以将此开关谓词实现为宏,以便在编译时将其更改为正常的条件表达式,以提高应用程序的性能?

macros prolog swi-prolog

8
推荐指数
1
解决办法
526
查看次数

如何使用Prolog中几个模块共享相同名称的谓词

我是Prolog的新手,我正在使用SWI-Prolog来解决以下问题.我有几个文件dataBase1.pl,dataBase2.pl...具有相同的结构(基于此线程)

:- module(dataBase1,[]).

:- use_module(library(persistency)).

:- persistent 
       predicate1(A:any, B:any),
       predicate2(A:any, B:any).

:- initialization(init).

init :-
        absolute_file_name('dataBase1.db', File, [access(write)]),
        db_attach(File, []).
Run Code Online (Sandbox Code Playgroud)

predicate1/2, predicate2/2 对所有数据库文件都是通用的.

然后,我在第三个文件中定义了predicates.pl几个使用以前数据库中的子句的子句,例如testPredicate(A,B) :- predicate1(A,B), predicate2(A,B).

我的问题是我希望predicate1/2, predicate2/2从与数据库文件对应的所有模块中使用上面的子句.在当前状态下,我需要精确上下文模块才能使用 predicate1/2, predicate2/2(即dataBase1:predicate1/2, dataBase2:predicate1/2,....)

我无法使用,use_module/1因为我将动态添加/删除数据库文件.

提前感谢任何建议!

编辑:在评论中讨论之后,如何将表单的可查询谓词定义head(X,Y) :- body()为持久动态谓词?

prolog swi-prolog

8
推荐指数
1
解决办法
333
查看次数

全局启用发生检查时,Prolog 是否需要 GC?

据我所知,通过健全的统一,SLD 解析不应该创建循环数据结构(这是正确的吗?)

如果是这样,理论上可以以不需要垃圾收集 (GC) 的方式实现 Prolog。但话又说回来,一个人可能不会。

  • 对于基于 WAM 的 Prolog 实现来说,这是真的吗?

  • SWI-Prolog 是这样吗?(我相信它不是基于 WAM 的)当发生检查全局启用时,在 SWI-Prolog 中禁用 GC 是否安全?

具体来说:

:- set_prolog_flag(occurs_check, true).
:- set_prolog_flag(gc, false). /* is this safe? */
Run Code Online (Sandbox Code Playgroud)

prolog logic-programming swi-prolog warren-abstract-machine occurs-check

8
推荐指数
1
解决办法
195
查看次数

Predsort/3喜欢msort/2

我想知道是否可以使用predsort/3而不会丢失重复值?如果没有,我应该如何排序这个术语列表?

当前排序功能:

compareSecond(Delta, n(_, A, _), n(_, B, _)):-
        compare(Delta, A, B).
Run Code Online (Sandbox Code Playgroud)

结果:

predsort(compareSecond, [n(3, 1, 5), n(0, 0, 0), n(8, 0, 9)], X).
X = [n(0, 0, 0), n(3, 1, 5)].
Run Code Online (Sandbox Code Playgroud)

你看,这个词n(8,0,9)已经消失了,这不是我需要的.

prolog swi-prolog

7
推荐指数
1
解决办法
1526
查看次数

Prolog延迟评估:LIFO还是FIFO唤醒?

许多Prolog系统都有一个freeze/2谓词,一个应该有名字的谓词,geler/2因为它甚至是在Prolog-II之前发明的.

假设我对同一个变量有条件,但有两个不同的目标,即:

 ?- freeze(X, G1), freeze(X, G2), X=1.
Run Code Online (Sandbox Code Playgroud)

什么是首选的唤醒策略,G1首先执行还是G2首次执行?如果G1和G2确实会产生新的冻结,这也会被唤醒:

 G1 :- freeze(Y, G3), Y=1.
 G2 :- freeze(Z, G4), Z=1. 
Run Code Online (Sandbox Code Playgroud)

G3或G4是否始终在G1和G2之间执行,或者可能是G1和G2之后执行G3或G4,甚至是以后的任何时间?

再见

prolog swi-prolog sicstus-prolog prolog-coroutining

7
推荐指数
1
解决办法
181
查看次数

SWI-prolog - 如何使用键盘快捷键或全局谓词清除终端屏幕?

我想使用键盘快捷键或命令清除 SWI-prolog 控制台内的屏幕(我猜在 Prolog 中你称之为“谓词”)。

是类似的问题,我有点找到我需要的东西 - 有一个适合我的谓词:

write('\33\[2J').
Run Code Online (Sandbox Code Playgroud)

有没有更好(更简单)的方法来清除屏幕?

prolog swi-prolog

7
推荐指数
2
解决办法
2万
查看次数

如何使用 call_with_depth_limit/3

我试图call_with_depth_limit/3在 SWI-Prolog 中使用来实现迭代深化,要么我不明白它是如何工作的,要么它行为不端。我有一个例子,其中发生以下情况:

?- call_with_depth_limit(mygoal, 29, Result).
Result = 29 ;
Result = 25 ;
Result = 27 ;
Result = 27 ;
false.
Run Code Online (Sandbox Code Playgroud)
?- call_with_depth_limit(mygoal, 26, Result).
Result = depth_limit_exceeded ;
false.
Run Code Online (Sandbox Code Playgroud)

根据文档,如果目标可以用限制最大递归或更少来证明,它应该会成功。在限制为 30 的第一次调用中,我们看到结果为 25,因此我希望以 26 的限制调用它会成功。我在模块中使用约束处理规则,以防那里可能有一些交互使其行为不端。

编辑:玩过伊莎贝尔的回答后,我想我明白它的行为方式了:

  • 它像往常一样运行深度优先搜索,但如果达到限制+1 深度,它就好像失败了。
  • 失败的分支计入结果。
  • 每次在成功回答后回溯时,它都会将 Result 重置为堆栈的当前深度。

看这个例子:

loop :- loop.

succeed(0).
succeed(N) :- N > 0, N1 is N - 1, succeed(N1).

fail(N) :- N > 0, N1 is N - 1, fail(N1).
Run Code Online (Sandbox Code Playgroud)
?- call_with_depth_limit(succeed(0), 1000, Result). …
Run Code Online (Sandbox Code Playgroud)

prolog swi-prolog iterative-deepening

7
推荐指数
3
解决办法
247
查看次数

Prolog `shift`/`reset` 与其他语言有何不同?

我在这里找到了 Haskell 中移位重置分隔延续的示例:

resetT $ do
    alfa
    bravo
    x <- shiftT $ \esc -> do
       charlie
       lift $ esc 1
       delta
       lift $ esc 2
       return 0
    zulu x
Run Code Online (Sandbox Code Playgroud)

这会:

  1. 履行alfa

  2. 履行bravo

  3. 履行charlie

  4. 绑定x到1,从而执行zulu 1

  5. 从末尾掉下来resetT,然后跳回到后面esc 1

  6. 履行delta

  7. 绑定x到2,从而执行zulu 2

  8. 从末尾掉下来resetT,然后跳回到后面esc 2

  9. 逃离resetT,导致它产生 0

我不知道如何使用 SWI-Prolog 的shift/1reset/3编写等效代码。

下面的代码是我的尝试。输出是相同的,但看起来很混乱和倒退,我觉得我误用了与Haskell 示例中的和Ball类似的东西。另外,我不知道该怎么办。esc 1esc 2return 0 …

continuations haskell prolog swi-prolog delimited-continuations

7
推荐指数
1
解决办法
291
查看次数