Mathematica 中的有针对性简化

7

我会生成非常长且复杂的分析表达式,一般形式如下:

(...something not so complex...)(...ditto...)(...ditto...)...lots...

当我尝试使用Simplify时,Mathematica会变得非常缓慢,我认为这是因为它试图展开括号或简化不同括号之间的表达式。这些括号虽然包含了长表达式,但单独使用Mathematica很容易进行简化。有没有办法将Simplify的范围限制在一个括号内? 编辑:一些额外的信息和进展。
所以根据你们的建议,我现在开始使用类似以下的东西:
In[1]:= trouble = Log[(x + I y) (x - I y) + Sqrt[(a + I b) (a - I b)]];

In[2]:= Replace[trouble, form_ /; (Head[form] == Times) :> Simplify[form],{3}]

Out[2]= Log[Sqrt[a^2 + b^2] + (x - I y) (x + I y)]

Times 改为适当的标题,如 PlusPower,可以更精确地定位简化。然而,仍然存在以下问题/疑问:Simplify 将比指定给 Replace 的级别更深入。
In[3]:= Replace[trouble, form_ /; (Head[form] == Plus) :> Simplify[form], {1}]

Out[3]= Log[Sqrt[a^2 + b^2] + x^2 + y^2]

它也可以简化平方根。

我的计划是从下往上逐级使用Replace,但这显然会导致Simplify大量重复的工作,最终导致Mathematica出现与我一开始遇到的完全相同的卡顿。有没有办法限制Simplify到某个特定的级别?

我意识到这种限制可能不会产生最佳结果,但这里的想法是得到一个“足够好”的东西。

3个回答

5

有多种方法可以实现这一点,但这可能有点棘手,取决于您实际表达式的结构。然而,通常在括号中的多个项的乘积将具有头部Times,您可以使用FullForm来验证:

In[1]:= FullForm[(a+b)(c+d)]
Out[1]= Times[Plus[a, b], Plus[c, d]]

您可以像处理头部为List的表达式一样处理头部为Times的表达式,使用高阶函数Map,这样可以逐项简化表达式,例如:

Map[Simplify, yourGinormousExpression]

如果您需要随后展开括号,可以在结果上使用Expand
编辑添加:如果您想指定要简化的表达式形式,可以使用ReplaceReplaceAll代替Map的某个相关函数。 Replace特别有用,因为它可以接受级别规范,这样您就只能影响最顶层乘积中的因子。作为一个简单的例子,请考虑以下内容:
In[1]:= expr = Sqrt[(a + 1)/a] Sqrt[(b + 1)/b];

In[2]:= Simplify[expr]
Out[2]= Sqrt[1 + 1/a] Sqrt[1 + 1/b]

如果您不想简化依赖于a的因素,可以尝试以下方法:

In[3]:= Replace[expr, form_ /; FreeQ[form, a] :> Simplify[form], {1}]
Out[3]= Sqrt[(1 + a)/a] Sqrt[1 + 1/b]

仅第二项与b有关。但需要注意的是,有些转换会自动由TimesPlus完成;例如,即使没有使用Simplifya + a也会变成2 a


谢谢,这个(以及其他答案)帮了很大的忙。 - Timo
刚刚尝试了这个有用的技巧,将变量列表{y1,y2,..}代替“a”,它非常好用。 - Massimo

2
我不同意我的同事们的看法,使用MapSimplify应用于每个子表达式可能不会节省任何时间,因为它仍然会被应用于每个子表达式。相反,请尝试使用MapAt,如下所示:
In[1]:= MapAt[f, SomeHead[a,b,c,d], {4}]
Out[1]:= SomeHead[a, b, c, f[d]]

关键在于确定位置说明。虽然,如果你想简化的表达式在第一层级别,那么它不应该比我上面写的更难。
现在,如果您仍然希望简化所有内容,但希望保留一些结构,请尝试使用选项{{link1:ExcludedForms}}。过去,我曾使用它来防止这种简化:
In[2]:= Simplify[d Exp[I (a + b)] Cos[c/2]]
Out[2]:= Exp[I(a + b + c)](d + d Exp[c])

数学软件Mathematica似乎喜欢这个,所以我也喜欢。
In[3]:= Simplify[d Exp[I (a + b)] Cos[c/2], ExcludedForms -> {_Cos,_Sin}]
Out[3]:= d Exp[I (a + b)] Cos[c/2]

另外,不要忘记 Simplify 的第二个参数是用于假设条件的,可以极大地帮助你将表达式转化成有用的形式。

1
“ExcludeForms”这个提示很不错,谢谢!我只希望Mathematica有一种可以专门包含形式以简化其他形式的方法,而不是TransformationFunctions,因为它不能为括号设置... - Timo

1
你应该尝试使用 Map
通常情况下,对于任何头部 G 和任何表达式 fooMap[foo, G[a, b, c, ...]] 会给出 G[foo[a], foo[b], foo[c], ...]
  Map[Simplify, a b c d e]

它给予

  Simplify[a] Simplify[b] Simplify[c] Simplify[d] Simplify[e]

请注意,如果您觉得更方便,可以将Map[foo, expr]表示为foo /@ expr。这与原始写法等效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接