具有递增组件的动态Prolog谓词

具有递增组件的动态Prolog谓词,prolog,global-variables,swi-prolog,prolog-assert,Prolog,Global Variables,Swi Prolog,Prolog Assert,我有一个由一组规则组成的知识库,当某些情况发生时,每个规则的头部执行复杂术语的断言或收回 如何确保Id随时间递增 assert(术语(Id,A,B,C))?假设您不关心Id中的孔(在收回Id\u person/2子句时发生),您可以执行以下操作: :- dynamic nextID/1. :- dynamic id_person/2. nextID(0). assertz_person(P) :- nextID(I), retract(nextID(I)), I1 is I+

我有一个由一组规则组成的知识库,当某些情况发生时,每个规则的头部执行复杂术语的断言或收回

如何确保
Id
随时间递增
assert(术语(Id,A,B,C))

假设您不关心
Id
中的孔(在收回
Id\u person/2
子句时发生),您可以执行以下操作:

:- dynamic nextID/1. :- dynamic id_person/2. nextID(0). assertz_person(P) :- nextID(I), retract(nextID(I)), I1 is I+1, assertz(nextID(I1)), assertz(id_person(I,P)). :-动态nextID/1。 :-动态id_person/2。 nextID(0)。 资产管理人(P):- nextID(I), 收回(下一个(I)), I1是I+1, assertz(nextID(I1)), 资产(个人(I,P))。 示例使用(与SWI Prolog 8.0.0和SICStus Prolog 4.5.0配合使用):

?身份证持有人(I,P)。 错。 -资产人(joan),身份人(I,P)。 I=0,P=joan。 -资产人(al)、资产人(ian)、身份人(I、P)。 I=0,P=joan ; I=1,P=al ; I=2,P=ian。
当您为
term/3
谓词断言子句时,其中第一个参数是唯一(整数)标识符,因此不需要辅助动态谓词来表示当前计数器。您只需执行以下操作:

:- dynamic(term/3).

assert_term(A, B, C) :-
    (   term(Id, _, _, _) ->
        NextId is Id + 1
    ;   NextId is 1
    ),
    asserta(term(NextId, A, B, C)).

调用
asserta/1
将使
term/3
的最新断言子句在调用时成为第一个被检索的子句,如上所述,所有参数都未绑定,从而提供对最后一次计数的访问。但是,此解决方案假设这些子句没有被任意收回。

是的,我会依次收回。
收回
呢?由此产生的“漏洞”应该如何处理?有趣的是:SWI Prolog@GuyCoder。(1) 我不认为“身份”标签有帮助。(2) “顺序”是多余的。“递增”指“+1”;不是“+2”;不是“+1.5”。@GuyCoder。不过,我确实认为你加上“顺序”有些好处。这是一个措辞上的问题。。。多个增量是按顺序进行的,但我认为不太可能出现误解。
assert/1
是遗留的
assertz/1
(或
asserta/1
)是标准配置。另外,通过使用
initialization/1
指令初始化
当前\u id/1
谓词,可以避免if-then-else构造。@PauloMoura。正确的!旧习惯:)初始化指令(在本例中)比一个简单的事实好吗?(这是一个额外的概念。)我认为你不需要同时使用
nextID(I)和retract(nextID(I))
,我认为
retract(nextID(I))
就足够了。@DanielLyons。好主意。但是SICStus手册()让我有点不安,我明天会检查一下。谢谢如果
nextID/1
是不确定的,这将是有问题的,但是如果没有线程,它应该只有一个解决方案。如果您有线程,那么无论如何您都会遇到其他问题(您需要一个关键部分或一个锁)。
:- dynamic(term/3).

assert_term(A, B, C) :-
    (   term(Id, _, _, _) ->
        NextId is Id + 1
    ;   NextId is 1
    ),
    asserta(term(NextId, A, B, C)).