【问题标题】:first order logic creating terms for arithmetic expressions using prolog使用 prolog 为算术表达式创建术语的一阶逻辑
【发布时间】:2020-10-12 22:08:09
【问题描述】:

给定签名(0,Z,{plus(2),minus(2),times(2)},常量是整数,函数是加号、减号和时间,每个都有arity 2。我想编写两个谓词arth/2printarth/1,它们采用上述签名中的项并进行必要的算术计算加法、减法和乘法。arth/2 将打印结果,printarth/1 将得出评估表达式如下图。

我想实现两件事

第一:

?- arth( plus(minus(8,2), times(4,-3)), N).
N = -6

N is evaluated as ((8−2) + (4∗−3)) = (6 +−12) =−6

秒:

?- printarth(plus(minus(8,2), times(4,-3)), N).
((8 - 2) + (4 * -3))
true.

我了解Terms, Ops and complex terms 的使用用于此目的,我的代码如下所示

arithmetic_operator('+').
arithmetic_operator('-').
arithmetic_operator('*').

arithmetic_expression(N) :- integer(N).

arithmetic_expression(Term) :-
    Term =..[Functor,Component1,Component2],
    arithmetic_operator(Functor),
    arithmetic_expression(Component1),
    arithmetic_expression(Component2).

从这里我发现如何创建arth/2printarth/1 很困难,因为我无法调用arithmetic_expression(Term) 并在调用它时抛出错误。

?- arithmetic_expression(..[+,5,7]).
ERROR: Syntax error: Operator expected
ERROR: arithmetic_expression(.
ERROR: ** here **
ERROR: .[+,5,7]) .

有关此任务的任何资源都非常有用。

【问题讨论】:

  • 明显的误解:有一个谓词叫univ,定义为运算符,看起来像这样:=..。您已经在代码中使用它。 = 本身也是一个运算符(统一)。但是.. 本身什么都不是。

标签: prolog signature predicate first-order-logic


【解决方案1】:

如果你想取一个看起来像这样的术语:

minus(2, 3)

把它变成一个算术表达式-(2, 3),它等价于2 - 3(默认定义-作为运算符),然后求值,你可以这样做:

term_arithmetic_expression(T, E) :-
    T =.. [Name, X, Y],
    binary_op(Name, Op),
    E =.. [Op, X, Y].

eval_arithmetic_expression(T, R) :-
    term_arithmetic_expression(T, E),
    R is E.

binary_op(minus, -).
% add more binary operations

现在这至少有效:

?- eval_arithmetic_expression(minus(2, 3), R).
R = -1.

如您所见,term_arithmetic_expression/2eval_arithmetic_expression/2 都有两个参数。这就是您需要将minus(2, 4) 映射到2 - 4 的内容。

您的arithmetic_expression/1 正在正确遍历,但没有从一种表示映射到另一种表示。你的arithmetic_operator 也有同样的问题。改动很小:

arithmetic_operator(plus, +).
arithmetic_operator(minus, -).
arithmetic_operator(times, *).

arithmetic_expression(N, N) :- integer(N).

arithmetic_expression(Term, Expr) :-
    Term =.. [Functor,Component1,Component2],
    arithmetic_operator(Functor, Operator),
    arithmetic_expression(Component1, Expr1),
    arithmetic_expression(Component2, Expr2),
    Expr =.. [Operator, Expr1, Expr2].

然后:

?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr).
Expr = 8-2+4* -3 ;
false.

?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
   Result is Expr.
Expr = 8-2+4* -3,
Result = -6 ;
false.

?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
   Result is Expr,
   display(Expr).
+(-(8,2),*(4,-3))
Expr = 8-2+4* -3,
Result = -6 ;
false.

display 是在最后一个查询中输出+(-(8,2),*(4,-3))

【讨论】:

  • 是的。我打算写一个像你的逻辑一样的算术术语。它适用于单个 binary_op,但如果我可以超过 1 个 binary_op 并出现错误“plus/2 不是函数”,它就会失败。为什么会这样?
  • @mkpisk 您需要递归地将每个术语(如minus(2, 4))转换为适当的算术表达式,如2 - 4;然后使用is/2 进行评估。您可以在遍历树时进行评​​估,也可以制作整个表达式然后对其进行评估。
  • @mkpisk 您的问题主要完成了遍历。只需按照我的答案所示修复重写即可。您必须使用is/2 评估arth/2 中的结果;只是不要在你的 arthprint/2 中评估它来获取表达式。
  • 谢谢@TA_intern 我现在就试试
  • @mkpisk 至少您必须向您的arithmetic_expression 添加另一个参数。第一个参数可以是 minus(times(...), ...) 术语,第二个参数是生成的 x * y - ...
猜你喜欢
  • 1970-01-01
  • 2015-12-20
  • 1970-01-01
  • 2014-05-23
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
相关资源
最近更新 更多