# Pushing Mathematica's FullSimplify to a global complexity minimum

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}]];



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!

• What is your example? Feb 4, 2021 at 23:52
• Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! Feb 4, 2021 at 23:55
• Have you examined the options, TransformationFunctions and ComplexityFunction? Feb 4, 2021 at 23:56
• A reasonable example how ComplexityFunction works can be found here FullSimplify does not work on this expression with no unknowns. Feb 5, 2021 at 0:26
• On the topic of aiding and guiding the expression simplification process, also see Advice for Mathematica as Mathematician's Aid Feb 5, 2021 at 4:53

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;
e,

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