代码之家  ›  专栏  ›  技术社区  ›  Greg Nisbet

prolog捕获只有在没有其他子句时才有效的所有子句

  •  3
  • Greg Nisbet  · 技术社区  · 6 年前

    我有一个谓词,它把模态逻辑公式和它的负正规形式联系起来。除模态运算符、连词和析取之外的所有连接词都将被消除,并且将否定尽可能地推送到表达式的叶中。

    这个 rewrite/2 _谓词有一个catch all子句 rewrite(A, A). 那就是 最后一个文本 . 有了这个catch all子句,就有可能提取出一个形式为负正规的公式。在这个例子中, e 是“Ukasiewicz”符号中的双条件连接,并且 4 7 是模态逻辑中的变量(因此是prolog常量)。

    Z 与负正规形式的公式统一。

    ?- rewrite(e(4, 7), Z).
    Z = a(k(4, 7), k(n(4), n(7)))
    

    然而, rewrite(<some constant>, <some constant>) 总是成功的,我不想成功。catch all子句实际上应该是catch all,而不是在另一个子句适用时可能激发的内容。

    ?- rewrite(e(4, 7), e(4, 7)).
    true.
    

    我试图替换 重写(a,a)。 带防护版本:

    wff_shallowly(WFF) :-
      WFF = l(_);
      WFF = m(_);
      WFF = c(_, _);
      WFF = f;
      WFF = t;
      WFF = k(_, _);
      WFF = a(_, _);
      WFF = n(_);
      WFF = e(_, _).
    
    rewrite(A, A) :- \+ wff_shallowly(A).
    

    我认为这将阻止“全部捕获”条款的适用。 如果且仅当 a不是由具有特殊含义的Atom/构造函数领导的。然而,在做出这种改变之后, rewrite 如果递归调用,则始终失败。

    ?- rewrite(4, Z).
    Z = 4.
    
    ?- rewrite(c(4, 7), Z).
    false.
    

    设置catch all子句的正确方法是什么?

    _?供参考的程序全文:

    % so the primitive connectives are
    % l <-- necessity
    % m <-- possibility
    % c <-- implication
    % f <-- falsehood
    % t <-- truth
    % k <-- conjunction
    % a <-- alternative
    % n <-- negation
    % e <-- biconditional
    
    wff_shallowly(WFF) :-
      WFF = l(_);
      WFF = m(_);
      WFF = c(_, _);
      WFF = f;
      WFF = t;
      WFF = k(_, _);
      WFF = a(_, _);
      WFF = n(_);
      WFF = e(_, _).
    
    % falsehood is primitive
    rewrite(f, f).
    
    % truth is primitive
    rewrite(t, t).
    
    % positive connectives
    rewrite(a(A, B), a(C, D)) :- rewrite(A, C), rewrite(B, D).
    rewrite(k(A, B), k(C, D)) :- rewrite(A, C), rewrite(B, D).
    rewrite(l(A), l(C)) :- rewrite(A, C).
    rewrite(m(A), m(C)) :- rewrite(A, C).
    
    % implication
    rewrite(c(A, B), a(NC, D)) :-
      rewrite(n(A), NC), rewrite(B, D).
    
    % biconditional
    rewrite(e(A, B), a(k(C, D), k(NC, ND))) :-
      rewrite(A, C),
      rewrite(n(A), NC),
      rewrite(B, D),
      rewrite(n(B), ND).
    
    % negated falsehood is truth
    rewrite(n(f), t).
    
    % negated truth is falsehood
    rewrite(n(t), f).
    
    % double negation elimination
    rewrite(n(n(A)), C) :- rewrite(A, C).
    
    % negated alternation
    rewrite(n(a(A, B)), k(NC, ND)) :-
      rewrite(n(A), NC), rewrite(n(B), ND).
    
    % negated conjunction
    rewrite(n(k(A, B)), a(NC, ND)) :-
      rewrite(n(A), NC), rewrite(n(B), ND).
    
    % negated biconditional
    rewrite(n(e(A, B)), a(k(C, ND), k(NC, D))) :-
      rewrite(A, C),
      rewrite(n(A), NC),
      rewrite(B, D),
      rewrite(n(B), ND).
    
    % negated necessity
    rewrite(n(l(A)), m(NC)) :- rewrite(n(A), NC).
    
    % negated possibility
    rewrite(n(m(A)), l(NC)) :- rewrite(n(A), NC).
    
    % catch all, rewrite to self
    rewrite(A, A) :- \+ wff_shallowly(A).
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   mat    6 年前

    如果你使用 清洁的 数据的表示。

    在这种情况下,这意味着你将完全类比你如何通过不同的 仿函数 ,还使用专用函数表示(模态) 变量 .

    例如,让我们使用函数 v/1 表示变量。这意味着我们使用 v(1) ,请 v(7) 等表示模态变量1、7等。

    我没有添加“catch all”子句,而是添加了以下子句来说明对模态变量的看法:

    % (negated) variable
    
    rewrite(n(v(V)), n(v(V))).
    rewrite(v(V), v(V)).
    

    现在我们得到:

    ?- rewrite(e(v(4), v(7)), Z).
    Z = a(k(v(4), v(7)), k(n(v(4)), n(v(7)))).
    

    请注意,我们当然必须使用 V/1 在查询中包装,并在应答中获取包装。这比包装器不存在时要稍微困难一些。然而,它使 推理 关于这样的公式要容易得多,因此我强烈建议使用它。

    在这些公式和 瑕疵 您当前使用的表示。它被称为“违约”,正是因为它需要 违约 (“全部捕获”)案例,也因为考虑到这一点 有错误的 . 最好尽快摆脱这种表示,然后围绕干净的表示编写主要逻辑。

    一个干净的表示对于一般性和效率都是很好的:Prolog系统的 参数索引 现在可以通过第一个参数的主函数很容易地将所有子句区分开来,这提高了在参数完全实例化的重要用例中(例如,在您发布的示例中)的性能。