TransWikia.com

Pushing Mathematica's FullSimplify to a global complexity minimum

Mathematica Asked by Filipe Miguel on April 17, 2021

Original: Is there any way to control Mathematica’s inner simplification algorithm? I have seen several instances where FullSimplify does not yield the most optimal solution but instead gets stuck in a local minimum. I can provide with some examples if needed.

Edit: Here are some details of the most recent place I stumbled into this:

So I am defining a derivative operator, myD, such that:

myD[x_?NumericQ*y_] := x myD[y];
myD[x_?NumericQ] := 0;

i.e. If myD acts on a scalar*something he will take the scalar outside, and if myD acts on a scalar, the output will be 0. Then, to impose linearity I impose the two following transformation functions:

myDSumTransform[x_?(MatchQ[#, myD[a_]] &)] := 
    (x /. (myD[HoldPattern[Plus[y__]]] :> Plus @@ (myD /@ List[y])));

myDSumTransformInverse[x_?(MatchQ[#,Optional[a_?NumericQ] myD[b_] + Optional[c_?NumericQ] myD[d_]] &)] := 
    (x /. Optional[e_?NumericQ, 1] myD[f_] + Optional[g_?NumericQ, 1] myD[h_] :> myD[e f + g h]);

The first transformation equation takes myD[a+b+c+...] and maps it into myD[a] + myD[b] +...
The second transformation takes a myD[b] + c myD[d] and maps it into myD[a b + c d].

Now I define myFullSimplify based on FullSimplify, using TransformationFunctions, such that:

$transfFunctions ={};
addToTransfFunctions[rules__]:=AppendTo[$transfFunctions, #]&/@List[rules];
myFullSimplify[expr_]:=FullSimplify[expr,TransformationFunctions->Flatten[{Automatic, $transfFunctions}]];

addToTransfFunctions[myDSumTransform, myDSumTransformInverse];

Alright, now comes the example. Take:

myD[a + b + c + 5]//myFullSimplify

The expected output would be

myD[a + b + c]

However what I get is


myD[a + b + c + 5]

My understanding is that the FullSimplify algorithm takes myD[a+b+5] applies myDSumTransform, arrives at myD[a] + myD[b] + myD[c], finds that the LeafCount is bigger, fiddles a bit with it to no avail and rejects the output. To get to the desired output, he would need to apply myDSumTransformInverse, two times and arriving at

myD[a + b + c]

If I try something a little less complex, e.g.

myD[a + b + 5 ] // myFullSimplify

I get myD[a+b] as expected.

So I guess what really need is to increase Mathematica’s persistence setting, or to find a smarter way to write myDSumTransformInverse.

Sorry for the convoluted question, I understand it a complex example, but I am not sure if there is a systematic way to deal with these issues. Hence, it would be nice to have some guidance on how to proceed here.

Thanks in advance for all the help!

One Answer

Here's a function linearCombine[] for un-distributing a linear operator that is a complement to linearExpand[] found in How to do algebra on unevaluated integrals? There is an optional argument to both to specify symbols that are to be treated as constants, which has no application in the present question.

ClearAll[linearCombine];
Module[{f},
  SetAttributes[f, NumericFunction];
  constantQ = NumericQ[# /.
      s_Symbol /; MemberQ[Attributes[s], Constant] :> f[0]] &
  ];
linearCombine[e_Plus, head_, constants_List : {}] := Block[constants,
   SetAttributes[#, Constant] & /@ constants;
   head@Replace[
      e,
      {c_?constantQ*head[a_] :> c*a,
       head[a_] :> a},
      1
      ] /; MatchQ[e, _[((_?constantQ)*_myD | _myD) ..]]
   ];

Example:

linearCombine[myD[a] + 2 Sqrt[2] myD[b] + 3 E myD[c], myD]
(*  myD[a + 2 Sqrt[2] b + 3 c E]  *)

Correct answer by Michael E2 on April 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP