Prolog 中的一阶谓词逻辑:使用签名和算术项
First-order predicate logic in Prolog: Working with Signatures and Arithmetic Terms
我正在使用 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)
问题与 相似且相关,但一个很大的区别是我需要避免使用 =.. 运算符来查找职能。相反,我想利用 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)
),但我很难处理比这更复杂的事情。
要使用模式匹配并避免使用 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).
这使代码更加直观,其中额外的情况(例如电源)可以由单独的子句处理。此外,现代编译器可以优化生成的代码。
我正在使用 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)
问题与
我使用 =.. 运算符的第一个解决方案是(借助上面链接的线程的答案):
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)
),但我很难处理比这更复杂的事情。
要使用模式匹配并避免使用 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).
这使代码更加直观,其中额外的情况(例如电源)可以由单独的子句处理。此外,现代编译器可以优化生成的代码。