Scheme 表达式简化

Scheme 表达式简化,scheme,Scheme,我有这个代码来计算导数: (define (diff x expr) (if (not (list? expr)) (if (equal? x expr) 1 0) (let ((u (cadr expr)) (v (caddr expr))) (case (car expr) ((+) (list '+ (diff x u) (diff x v))) ((-) (list '- (diff x u) (diff x v)))

我有这个代码来计算导数:

(define (diff x expr)
  (if  (not (list? expr))
    (if  (equal? x expr) 1 0)
    (let ((u (cadr expr)) (v (caddr expr)))
     (case (car expr)
       ((+) (list '+ (diff x u) (diff x v)))
       ((-) (list '- (diff x u) (diff x v)))
       ((*) (list '+
                   (list  '* u (diff x v))
                   (list  '* v (diff x u))))
        ((/) (list ‘div (list '-
                  (list  '* v (diff x u))
                  (list  '* u (diff x v)))
                  (list  '* u v)))
))))
如何简化代数表达式

而不是
x+x
show
2x

而不是
x*x
show
x^2

也许from会有用。它是公共Lisp,与Scheme非常相似。入口点是
simp
函数

请注意,它还使用

历史注释:PAIP的相关章节提到了20世纪60年代在麻省理工学院开发的计算机代数系统,它是Mathematica、Maple(现在在Matlab中)和其他工具的基础。

以下是一个开始:

将导数函数从
(define(diff x expr)
更改为类似
(define(simp expr)…)

对于
x+x
情况,执行以下操作

(case (car expr)
  ((+) (if (equal u v)    ; check for identical subexpressions
         `(* ,(simp u) 2) ; if u==v, simplify 2u
         `(+ ,(simp u) ,(simp v))))
  ...)
x*x
的情况应该类似。最后,如果需要进行许多不同的简化,您可能需要将
if
转换为
cond


这是一个很难完全解决的问题,eliben给出的链接值得一看。

代数表达式的简化相当困难,尤其是与导数的计算相比。简化应该递归地进行。首先要简化最里面的表达式。一次不要尝试太多。我只从最基本的简化开始,例如:

 0 + x -> x
 0 * x -> 0
 1 * x -> x
 x ^ 0 -> 1
 x ^ 1 -> x
用加法代替减法,用乘法代替除法

 x - y -> x + (-1)*x
 x / y -> x ^ (-1)
这看起来可能不是一种简化,但它将简化您的代码。在结束时,您始终可以反转此步骤

然后使用结合性和交换性对术语进行排序。将数值移到左侧,按预定义的顺序对变量排序(不必按字母顺序,但应始终相同)

简化指数

  (x ^ y) ^ z -> x^(y * z)
简化数值部分

 2 * (3 * x) -> 6 * x
 2 + (3 + x) -> 5 + x

完成这项工作后,您可以考虑收集常用表达式。

一般的问题很难解决,但使用乘积和标准形式(表示为从键(变量名)到系数的有限映射)可以有很长的路要走。这种形式适用于线性方程组和线性求解,并且可以扩展到乘法和幂,而不需要太多麻烦。如果你在这种形式上为算术定义“智能构造函数”,你可以得到一些合理的符号微分和方程求解

这是一个快速的破解,但我已经在一些应用程序中使用过它。它在几家公司工作;有几次还不够好。更严重的是,你说的是多年的工作


如果您需要代码示例,可以阅读。

听起来很有趣。你的论文是pdf格式的吗?要获得一个很好的总结,包括许多具体的、易于实现的规则,请参阅论文:“微积分的历史和计算机代数系统的发展”。有关章节如下:
 2 * (3 * x) -> 6 * x
 2 + (3 + x) -> 5 + x