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
show2x
及
而不是x*x
showx^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