表达简化

时间:2009-05-20 02:28:01

标签: 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)))
       ((*) (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显示2x

代替x * x显示x^2

4 个答案:

答案 0 :(得分:3)

简化algegraic表达式非常困难,特别是与派生计算相比。简化应该以递归方式完成。您首先简化最内层表达式。不要一次尝试太多。我从最简单的简化开始,例如:

 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)
 x * 2 -> 2 * x
 2 * (x * 3) -> 2 * (3 * x)

简化指数

  (x ^ y) ^ z -> x^(y * z)

简化数字部分。

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

完成此操作后,您可以考虑收集常用表达式。

答案 1 :(得分:0)

来自this codePAIP可能会有用。它是Common Lisp,与Scheme非常相似。入口点是simp函数。

请注意,它也使用this file

历史记录:相关的PAIP章节是指Macsyma,即20世纪60年代在麻省理工学院开发的计算机代数系统,是Mathematica,Maple(现在的Matlab)和其他工具的基础。

答案 2 :(得分:0)

这是一个开始:

将衍生函数从(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给出的链接值得一看。

答案 3 :(得分:0)

一般问题很难,但是您可以通过产品总和的正常形式获得很长的路,表示为从键(变量名称)到系数的有限映射。这种形式非常适用于线性方程和线性求解,它可以扩展到乘法和幂而不会有太多麻烦。如果你在这个表格上定义“智能构造函数”进行算术运算,你可以得到一些合理的符号区分和方程求解。

这是一个快速的黑客,但我在一些应用程序中使用它。它工作的几个;有几次它还不够好。对于更严肃的事情,你说的是多年的工作。

如果您需要代码示例,可以阅读one of my equation solvers