Re: Simplify and FullSimplify
- To: mathgroup at smc.vnet.net
- Subject: [mg58553] Re: [mg58547] Simplify and FullSimplify
- From: "David Park" <djmp at earthlink.net>
- Date: Thu, 7 Jul 2005 05:35:42 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
Jerry, The example you give doesn't quite rise to the requirements of the answer I am going to give because there are simple ways to do the manipulation. Nevertheless, I am going to take the question as a generic question on how one can manipulate expressions to the precise form that one may want. The trouble with Simplify and FullSimplify is that although they are very powerful and often give one a useful form, they are still a little beyond the control of the user. One can often control simplifications and manipulations much easier by working on only parts of expressions. So one could use MapAt to work on only a subpart of an expression. But Mathematica has a missing feature here. Sometimes one might want to work on only a subset of level parts, especially level parts of a sum or product. There is no routine to do that. One could write replacement rules for this, but if the expressions are long this can be time consuming. The following routines, MapLevelParts and MapLevelPatterns, are part of the Tensorial tensor calculus package. I have found them very useful in manipulating complex expressions. MapLevelParts::usage = "MapLevelParts[function, {topposition, levelpositions}][expr] will map \ the function onto the selected level positions in an expression. \ Levelpositions is a list of the selected parts. The function is applied to \ them as a group and they are replaced with a single new expression. Other \ parts not specified in levelpositions are left unchanged.\nExample:\na + b + \ c + d + e // MapLevelParts[f, {{2,4,5}}] -> a + c + f[b + d + e]"; MapLevelParts[func_, part : {toppart___Integer?Positive, subp : {_Integer?Positive, eprest__Integer?Positive}}][expr_] := Module[{work, subparts, npos, null, i, nnull = Length[{eprest}]}, work = func@Part[expr, Sequence @@ part]; subparts = Thread[{toppart, subp}]; newparts = {work, Table[null[i], {i, 1, nnull}]} // Flatten; npos = Partition[Range[nnull + 1], 1]; ReplacePart[expr, newparts, subparts, npos] /. null[_] -> Sequence[] ] MapLevelPatterns::usage = "MapLevelPatterns[function, {topposition, {pattern}}][expr] will map the \ function onto the selected level positions at topposition that match the \ pattern in an expression. The function is applied to these positions as a \ group and they are replaced with a single new expression. Other parts not \ specified in the level are left unchanged.\nExample:\nf[1] + f[2] + f[3] + \ f[4] // MapLevelPatterns[g, {{f[_?EvenQ]}}] -> f[1] + f[3] + g[f[2] + f[4]]"; MapLevelPatterns::nomatch = "There were no matches for `` in ``"; MapLevelPatterns[func_, {toppart___Integer?Positive, {pattern_}}][expr_] := Module[{work, levelpos}, work = Part[expr, toppart]; levelpos = Flatten@Position[work, pattern, {1}]; If[Length[levelpos] == 0, Message[MapLevelPatterns::nomatch, pattern, work]; expr, expr // MapLevelParts[func, {toppart, levelpos}]]] Let's try your expression. Simplify did not give the desired form, FullSimplify did. One could also use collect. expr = q - q Exp[-a x] + c Exp[-a x]; Simplify[expr] FullSimplify[expr] Collect[expr, Exp[-a x]] One could also use MapLevelParts to apply Simplify to only the Exp terms. expr // MapLevelParts[Simplify, {{1, 3}}] (c - q)/E^(a*x) + q Here is a more complicated expression. expr2 = Cos[t]^2 + 1/((Exp[a*t] + 1/Sqrt[h])*Cos[t]^2 + (-a + Exp[a*t] + 1/Sqrt[h])*Sin[t]^2 + c); Suppose we just want to simplify the common (Sin[t]^2 + Cos[t]^2) factor leaving a Sin[t]^2 term. FullSimplify does not give us that form. But by mapping Simplify onto just two of the terms we get the answer we want. expr2 // FullSimplify % // MapLevelParts[Simplify, {2, 1, {1, 5}}] Cos[t]^2 + 1/(-(a/2) + c + E^(a*t) + 1/Sqrt[h] + (1/2)*a*Cos[2*t]) Cos[t]^2 + 1/(c + E^(a*t) + 1/Sqrt[h] - a*Sin[t]^2) Or we could have expanded expr2 and then mapped Simplify to the desired terms. expr2 // ExpandAll % // MapLevelParts[Simplify, {2, 1, {2, 3, 5, 6}}] Cos[t]^2 + 1/(c + E^(a*t)*Cos[t]^2 + Cos[t]^2/Sqrt[h] - a*Sin[t]^2 + E^(a*t)*Sin[t]^2 + Sin[t]^2/Sqrt[h]) Cos[t]^2 + 1/(c + E^(a*t) + 1/Sqrt[h] - a*Sin[t]^2) We could also have simplified this using two MapAt statements. Here Simplify took a different path because we factored out the trig identity. We could also have mapped right onto the trig identity. MapAt[Collect[#1, E^(a*t) + 1/Sqrt[h]] & , expr2, {{2, 1}}] MapAt[Simplify, %, {{2, 1, 3, 2}}] Cos[t]^2 + 1/(c - a*Sin[t]^2 + (E^(a*t) + 1/Sqrt[h])* (Cos[t]^2 + Sin[t]^2)) Cos[t]^2 + 1/(c + E^(a*t) + 1/Sqrt[h] - a*Sin[t]^2) In any case, simplifying specific parts of an expression, or selected terms in a sum or factors in a product gives a much more controllable situation. David Park djmp at earthlink.net http://home.earthlink.net/~djmp/ From: fizzy [mailto:fizzycist at knology.net] To: mathgroup at smc.vnet.net A result of a calculation I was doing generated this expression.... q-q Exp[-a x] + c Exp[-a x] naturally my next step was Simplify and I thought I'd get the Exp[- ax] collected.....to my complete surprize I got the following: Exp[-a x] (c + (-1+ Exp[a x]) q How on Earth did Mathematica come up with this? I checked FullSimplify which did collect Exp[-a x].... On re-reading my question before I submitted it, I see that with Simplify Mathematica 'collected' using Exp[- a x] q.....of course, visually this expression seems quite complex and would seem to take much more 'thinking' to get ......why do Simplify and FullSimplify have such a vast difference in what is considered 'Simpler'? Thanks....Jerry Blimbaum