【问题标题】:Prolog - subsitution and evaluationProlog - 替换和评估
【发布时间】:2017-09-22 13:52:56
【问题描述】:

编程界的好人你好。

与命令式编程相比,逻辑编程总是令人着迷。 由于追求逻辑编程的未知性,在遇到算术表达式时存在一些问题。

这是我到目前为止所做的代码。

number_atom(N) :-
(number(N) -> functor(N, _, _); functor(N, _, _), atom(N)).
arithmeticAdd_expression(V,V,Val,Val).
arithmeticAdd_expression(N, _Var, _Val, N) :-
   number_atom(N).

arithmeticAdd_expression(X+Y, Var, Val, R) :-
   arithmeticAdd_expression(X, Var, Val, RX),
   arithmeticAdd_expression(Y, Var, Val, RY),
   (number(RX), number(RY) -> R is RX + RY; R = RX + RY).

以添加操作为例:

arithmeticAdd_expression(Expression, Variable, Value, Result)

?- arithmeticAdd_expression(a+10, a, 1, Result).
?- Result = 11;
?- Result = a + 10.

?- arithmeticAdd_expression(a+10, b, 1, Result).
?- Result = a + 10.

我想要实现的是 如果表达式中的原子只能由给定的变量和值替换,则结果只是上面显示的示例(结果 = 11)的数字。否则,结果只是表达式本身。我的代码问题出在某个地方,我可以弄清楚。那么,请有人可以帮助我吗?谢谢。

【问题讨论】:

  • 你可以在这里删减:(number(RX), number(RY) -> !, R is RX + RY; R = RX + RY)。另外,我认为number_atom/1可以简化为number_atom(N) :- number(N) ; atom(N).
  • 感谢您提供快速响应的解决方案,干杯..:P

标签: prolog prolog-defaulty


【解决方案1】:

逻辑编程相对于函数式编程的一个重要吸引力在于,您可以经常在多个方向使用相同的代码。

这意味着,如果输入是给定的,您不仅可以询问特定结果,还可以询问解决方案的外观一般

但是,要使其发挥作用,您必须对表示数据的方式进行一些思考。例如,在您的情况下,您的表达式中仍然是逻辑变量的任何术语都可能表示 要么 给定数字 应该与普通数字不同解释的原子另外两个术语的添加。这被称为 defaulty 表示,因为您必须决定一个变量应该表示什么默认,并且没有办法将其含义限制为仅一种可能的情况。

因此,我建议首先更改表示,以便您可以象征性地区分这两种情况。例如,要在您的情况下表示表达式,让我们采用以下约定:

  • 原子由包装器a/1表示
  • 数字由包装器n/1表示。
  • 和已经存在的情况一样,(+)/2 应表示两个表达式的加法

所以,像b+10 这样的默认术语现在应该写成:a(b)+n(10)。请注意使用包装器 a/1n/1 来明确我们正在处理哪种情况。这种表示称为clean。包装器是任意选择的(尽管是记忆法),我们可以使用完全不同的包装器,例如atom/1number/1,或atm/1nmb/1。关键特性只是我们现在可以通过它们最外层的函子和数量来象征性地区分不同的情况。

现在的关键优势:使用这样的约定,我们可以编写例如:a(X)+n(Y)。这是早期术语的概括。然而,它携带的信息远不止X+Y,因为在后一种情况下,我们已经忘记了这些变量代表什么,而在前一种情况下,这种区别仍然存在。

现在,假设这个约定用在表达式中,描述不同的情况就变得直截了当:

表达式_结果(n(N),_,_,n(N))。 表达式_结果(a(A),A,N,n(N))。 表达式_结果(a(A),Var,_,a(A)):- 差异(A,Var)。 expression_result(X+Y, Var, Val, R) :- expression_result(X, Var, Val, RX), expression_result(Y, Var, Val, RY), 加法(RX,RY,R)。 加法(n(X),n(Y),n(Z)):- Z #= X + Y。 加法(a(X),Y,a(X)+Y)。 加法(X,a(Y),X+a(Y))。

请注意,我们现在可以使用模式匹配来区分情况。不再需要 if-then-elses,也不再需要 atom/1number/1 测试。

您的测试用例按预期工作:

?- expression_result(a(a)+n(10), a, 1, Result)。 结果 = n(11) ; 错误的。 ?- expression_result(a(a)+n(10), b, 1, Result)。 结果 = a(a)+n(10) ; 错误的。

现在的关键优势是:有了这样一个纯程序(请参阅 了解更多信息),我们还可以问“结果是什么样的一般?”

?- expression_result(Expr, Var, N, R). 表达式 = R, R = n(_1174) ; Expr = a(Var), R = n(N) ; 表达式 = R, R = a(_1698), 差异(_1698,变量); 表达式 = n(_1852)+n(_1856), R = n(_1896), _1852+_1856#=_1896 ; Expr = n(_2090)+a(Var), R = n(_2134), _2090+N#=_2134。

在这里,我对所有参数使用了逻辑变量,我从这个程序中得到了相当普遍的答案。这就是我使用 约束进行声明式整数运算的原因。

因此,您的直接问题可以通过使用干净的表示和使用上面的代码轻松解决。

只剩下一个很小的挑战:也许您实际上想要使用默认表示,例如c+10(而不是a(c)+n(10))。然后您面临的任务是将默认表示convert 转换为干净的表示,例如通过谓词defaulty_clean/2。我把它作为一个简单的练习。一旦你有了一个干净的表示,你就可以使用上面的代码而不用做任何更改。

【讨论】:

  • 非常感谢您对我的代码问题的理解,我一定会调查的。
猜你喜欢
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-14
  • 1970-01-01
  • 2012-05-10
  • 2013-02-01
相关资源
最近更新 更多