【问题标题】:First-order predicate logic in Prolog: Working with Signatures and Arithmetic TermsProlog 中的一阶谓词逻辑:使用签名和算术项
【发布时间】:2020-10-29 16:48:18
【问题描述】:

我正在使用 Prolog 中的术语和签名(一阶谓词逻辑)。

我已获得签名(∅, Z, {add(2), sub(2), mult(2)})。所以没有变量,常量是整数,函数是“add”、“sub”和“mult”。

目标是编写谓词“calc/2”,它接受一个项(给定上面的签名)并根据整数加减乘乘的通常定义计算它。示例:

?- calc( add(sub(8,2), mult(4,-3)), N).
N = -6

(因为 ((8 − 2) + (4 ∗ −3)) = −6)

问题与 this question 类似且相关,但一大区别是我需要避免使用 =.. 运算符来查找函数的名称。相反,我想利用 Prolog 对规则的参数使用模式匹配这一事实,这是我完全坚持的。另外需要注意的是,“add”、“sub”和“mult”不应该是谓词。

我使用 =.. 运算符的第一个解决方案是(借助上面链接的线程的答案):

op(+, add).
op(-, sub).
op(*, mult).

calc(Term, N) :-
    calc2(Term, Expr),
    N is Expr.

calc2(N,N) :- integer(N).
calc2(Term, Expr) :-
    Term =.. [Op_str, Comp1, Comp2],
    op(Op, Op_str),
    calc2(Comp1, Expr1),
    calc2(Comp2, Expr2),
    Expr =.. [Op, Expr1, Expr2].

但由于这^不是我正在寻找的解决方案类型,它对我的​​问题并没有太大帮助。

我可以很容易地执行单个计算(例如 calc(add(1,2), N)),但我遇到比这更复杂的事情。

【问题讨论】:

    标签: prolog signature predicate first-order-logic


    【解决方案1】:

    要使用模式匹配并避免使用 univ 运算符 =..,您可以像这样重写 calc2/2:

    calc2(add(Op1, Op2), Expr1 + Expr2) :- 
        calc2(Op1, Expr1),
        calc2(Op2, Expr2).
    calc2(sub(Op1, Op2), Expr1 - Expr2) :-
        calc2(Op1, Expr1),
        calc2(Op2, Expr2).
    calc2(mult(Op1, Op2), Expr1 * Expr2) :-
        calc2(Op1, Expr1),
        calc2(Op2, Expr2).
    

    这使代码更加直观,其中额外的情况(例如电源)可以由单独的子句处理。此外,现代编译器可以优化生成的代码。

    【讨论】:

    • 谢谢你,这么好的答案,正是我想要的
    • 我无法将您的答案标记为有用(赞成),因为这是我第一次使用 stackoverflow,但是一旦我达到 15 名声望,我就会回来这样做。
    猜你喜欢
    • 1970-01-01
    • 2011-09-14
    • 2012-09-20
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多