【发布时间】:2014-12-25 22:52:21
【问题描述】:
我有以下联合作为符号数学表达式的 AST:
type Expr =
| Const of float
| X of float * float
| Sum of Expr * Expr
| Mul of Expr * Expr
| Pow of Expr * Expr
| Sin of Expr
| Cos of Expr
static member (+) (e1,e2) = Sum(e1,e2)
static member (*) (e1,e2) = Mul(e1,e2)
static member (/) (e1,e2) = Mul(e1, Pow(e2,Const -1.0))
let (!) e = Mul(Const -1.0,e)
let (^) e n = Pow(e ,n)
问题:
我正在尝试简化 Mul(Mul(expr1,expr2),expr3) 或 Mul(e,Mul(e1,e2)) 之类的表达式,或者通常在表达式中有 n 嵌套乘法时。
我写了这个simp 函数,它接受Expr 并递归地简化事情。 (只是一些代数),当从fullSimp 调用函数simp 时,这个函数的两个规则(阅读代码中的cmets)导致无限递归
let rec simp expr =
match expr with
| Mul(Sum(e1,e2),e) -> simp (e1*e) + simp (e2*e)
| Mul(e,Sum(e1,e2)) -> simp (e1*e) + simp (e2*e)
| Mul(e1,e2) when e1 = e2 -> simp e1 ^ Const 2.0
| Mul(Mul(e1,e2),e) -> Mul(simp (e1*e),simp e2) // adding this rule makes the function 'fullSimp' recurse infinitely
| Mul(e,Mul(e1,e2)) -> Mul(simp (e2*e), simp e1) // same as above
| Mul(e1,e2) -> simp e1 * simp e2
| Cos e -> Cos(simp e)
| Sin e -> Sin(simp e)
| _ -> expr
然后是函数fullSimp 调用simp 直到simp 返回表达式的简化版本没有变化
let rec fullSimp e =
let simplified = simp e
if simplified <> e then fullSimp simplified
else simplified
尝试计算以下表达式会产生无限递归!!!
fullSimp (Mul (Mul (Const 2.0,Cos (X (1.0,1.0))),Sin (X (1.0,1.0))))
// notice the nested multiplications here
// also notice that this does not simplify any furthur so the function
// should return the same input.
从simp 中删除这两个规则解决了无限递归,但不是简化嵌套乘法的问题。
编辑:为了以不同的方式思考问题,我试图收集(相乘)嵌套乘法节点中的常量和变量。例如,我试图采用像
这样的表达式Mul(Const 5.0,Mul(Mul (Const 2.0,Sin (X (4.0,2.0))),Mul (Cos (X (4.0,2.0)),X (8.0,1.0))))
然后把它变成Mul (Mul (X (80.0,1.0),Sin (X (4.0,2.0))),Cos (X (4.0,2.0))) 不能再简化了
注意:根据 cmets 中的反馈,我编辑了几次。现在希望很清楚问题是什么。对不一致之处深表歉意。
【问题讨论】:
-
我知道,这将是问题的重现。但是您发布的代码不完整,无法编译。
-
好的,你知道那些静态成员,但我们不知道,因为你没有在代码中指定它们。这就是重点,如果您发布的代码不完整,我们将面临并非真正问题的错误。您发布的内容应该是最小的并且同时是完整的,这意味着如果它是在 fsi 会话中复制粘贴执行的,它应该编译(或者如果这是您的问题,最终会引发编译器错误)。
-
@ZaidAjaj - 请阅读本指南:stackoverflow.com/help/mcve
-
作为一个问题的答案:如果你删除除了有问题的规则之外的每一条规则会发生什么?来自
simp -
这是一个提示 - 一旦你明白为什么会发生这种情况,你就会明白为什么原始版本会崩溃
标签: f# symbolic-math