【问题标题】:Dynamic rule assertion in SWI-prologSWI-prolog 中的动态规则断言
【发布时间】:2010-10-31 22:07:16
【问题描述】:

我正在尝试使用 SWI-prolog 将规则动态添加到知识库,其中规则主体事先未知。

所需的规则如下所示:

rule(a) :- fact(1), fact(2).

通常你会简单地陈述

assert((rule(a):-fact(1),fact(2))).

但问题是事实是在运行时决定的(事实的数量在断言之前也是未知的)。

这就是为什么我想知道是否有可能断言主体由事实列表组成的规则,例如[fact(1), fact(2)]

【问题讨论】:

    标签: prolog metaprogramming


    【解决方案1】:

    我们将创建一个规则newrule(X) :- w,x,y,z(X)
    规则的主体是一个元组,是一个 (w,x,y...) 形式的构造。

    对于不同的身体长度,从无身体开始:

    assert(goal).  
    assert(goal:-cond).  
    assert(goal:-(cond1,cond2)).
    

    元组运算符是逗号(`,'),如','(a,b) == (a,b)

    %%%%
    %%%% Name: runtime.pl -- Runtime rule insertion.
    %%%%
    create_a_rule :- 
        Cond=[w,x,y,z(X)],
        Head=newrule(X),
        list_to_tuple(Cond,Body),
        dynamic(Head),
        assert(Head :- Body),
        listing(Head).
    
    /*
    This is a [l,i,s,t], and this is a (t,u,p,l,e).  
    Convertng list to tuple:  
    []    -> undefined  
    [x]   -> (x) == x  
    [x,y] -> (x,y).  
    [x,y,z..whatever] = (x,y,z..whatever)  
    */
    
    list_to_tuple([],_) :- 
        ValidDomain='[x|xs]',
        Culprit='[]',
        Formal=domain_error(ValidDomain, Culprit),
        Context=context('list_to_tuple','Cannot create empty tuple!'),
        throw(error(Formal,Context)).
    
    list_to_tuple([X],X).
    
    list_to_tuple([H|T],(H,Rest_Tuple)) :-
        list_to_tuple(T,Rest_Tuple).
    
    :- create_a_rule.
    :- listing(newrule).
    

    --

    有两个列表。第一个列表来自listing()create_a_rule() 中被调用。第二个清单来自最后一个源代码行的listing() 命令。

    ?- [runtime].
    :- dynamic newrule/1.
    
    newrule(A) :-
        w,
        x,
        y,
        z(A).
    
    :- dynamic newrule/1.
    
    newrule(A) :-
        w,
        x,
        y,
        z(A).
    
    % runtime compiled 0.01 sec, 1,448 bytes
    true.
    

    【讨论】:

    • 非常感谢您提供完美且非常详尽的解决方案!
    • @Tom:如果答案是“完美”,你为什么不接受呢?
    • 此答案中的 assert 谓词在 SWI-Prolog 中已弃用。
    【解决方案2】:

    对 frayser 列表的建议更改:

    list_to_tuple([X],X).
    
    list_to_tuple([A,B],(A,B)).
    
    list_to_tuple([A,B|T],(A,B,Rest_Tuple)) :-
        list_to_tuple(T,Rest_Tuple).
    

    如果第一个变量是一个空列表,这些子句就不需要异常:它只会失败。这也意味着您在回溯时永远不会遇到断言。

    但是,您可能仍然希望使用异常子句,因此您仍然可以将其放入以捕获尝试与 [] 进行统一的情况。 (不过,回溯时它不会击中它。)

    【讨论】:

      猜你喜欢
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多