prolog catch all 仅在没有其他子句时才有效的子句
prolog catch all clause that's only active if no other clause is
我有一个谓词将模态逻辑公式与其负范式联系起来。除了模态运算符、合取和析取之外的所有连接词都被删除,否定被尽可能地推到表达式的叶子中。
rewrite/2
✱ 谓词有一个包罗万象的子句 rewrite(A, A).
,文本最后。有了这个包罗万象的子句,就可以提取否定范式的公式。在这个例子中,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>)
总是成功,我希望它不要成功。包罗万象的条款确实应该是包罗万象的,而不是如果另一个条款适用可能会触发的东西。
?- rewrite(e(4, 7), e(4, 7)).
true.
我尝试用受保护的版本替换 rewrite(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/constructor 为首。但是,在进行该更改后,如果递归调用 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).
如果您使用 干净 数据表示,这些问题都会消失。
在这种情况下,这意味着您应该完全类似于您如何通过不同的 函子 系统地表示所有其他实体,也使用专用函子来表示(模态) 变量.
例如,让我们使用函子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
包装器,并在答案中获取包装器。与不存在包装器相比,这稍微难于读写。但是,它使推理这些公式变得容易得多,因此我强烈建议使用它。
在这些公式和您当前使用的 默认 表示法之间进行转换是一种直接的练习。它被称为 "defaulty" 正是因为它需要一个 default ("catch all") 的情况,也因为这被认为是 faulty .最好尽快摆脱此类表示,然后围绕干净的表示编写主要逻辑。
干净的表示有利于通用性和效率:您的 Prolog 系统的 参数索引 现在可以通过第一个参数的主函子轻松区分所有子句,并且这提高了在该参数被完全实例化的重要用例中的性能(例如,在您发布的示例中)。
我有一个谓词将模态逻辑公式与其负范式联系起来。除了模态运算符、合取和析取之外的所有连接词都被删除,否定被尽可能地推到表达式的叶子中。
rewrite/2
✱ 谓词有一个包罗万象的子句 rewrite(A, A).
,文本最后。有了这个包罗万象的子句,就可以提取否定范式的公式。在这个例子中,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>)
总是成功,我希望它不要成功。包罗万象的条款确实应该是包罗万象的,而不是如果另一个条款适用可能会触发的东西。
?- rewrite(e(4, 7), e(4, 7)).
true.
我尝试用受保护的版本替换 rewrite(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/constructor 为首。但是,在进行该更改后,如果递归调用 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).
如果您使用 干净 数据表示,这些问题都会消失。
在这种情况下,这意味着您应该完全类似于您如何通过不同的 函子 系统地表示所有其他实体,也使用专用函子来表示(模态) 变量.
例如,让我们使用函子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
包装器,并在答案中获取包装器。与不存在包装器相比,这稍微难于读写。但是,它使推理这些公式变得容易得多,因此我强烈建议使用它。
在这些公式和您当前使用的 默认 表示法之间进行转换是一种直接的练习。它被称为 "defaulty" 正是因为它需要一个 default ("catch all") 的情况,也因为这被认为是 faulty .最好尽快摆脱此类表示,然后围绕干净的表示编写主要逻辑。
干净的表示有利于通用性和效率:您的 Prolog 系统的 参数索引 现在可以通过第一个参数的主函子轻松区分所有子句,并且这提高了在该参数被完全实例化的重要用例中的性能(例如,在您发布的示例中)。