# How do I invoke the default complexity function?

Documentation on ComplexityFunction says:

With the default setting ComplexityFunction->Automatic, forms are ranked primarily according to their LeafCount, with corrections to treat integers with more digits as more complex.

I need to use this default function on its own, not in Simplify or FullSimplify. Can I invoke it from my code?

If no, could you give me a custom function that behaves as close to the default function as possible?

Thanks!

• You could use this as one of your test cases. And then explain to me what's going on :) – Rojo May 30 '13 at 22:42
• Do you mean that you want to know the Complexity as measured by Mathematica of a function? Can you define your own using LeafCount and integer sizes or does it need to be precisely that as defined by Mathematica? – Jonathan Shock May 30 '13 at 23:16
• The code for the automatic complexity function is listed in the help file for ComplexityFunction reference.wolfram.com/mathematica/ref/ComplexityFunction.html It is the first item under Properties and Relations. – bill s May 31 '13 at 5:26
• @bills nice find. – rcollyer May 31 '13 at 12:16

The code for the default ComplexityFunction was posted on MathSource a number of years ago by Adam Strzebonski (of Wolfram Research). You will see reference to the original reply from Adam referenced in a MathGroup reply from Andrzej Kozlowski dated 12 Jan 2010 with the subject: "[mg106386] Re : Radicals simplify". I mention all that because I can't get the hyperlink to work (: The code Adam provided is there as well. The implementation from Adam used nested If statements. I can't resist the urge to use Which instead. I give my version below. I don't know for sure that the same function is used, but I have seen no reports indicating that it has changed.

SimplifyCount[p_]:=With[{hd=Head[p]},
Which[
hd===Symbol,1,
hd===Integer,If[p===0,1,Floor[N[Log[2,Abs[p]]/Log[2,10]]]+If[Positive[p],1,2]],
hd===Rational,SimplifyCount[Numerator[p]]+SimplifyCount[Denominator[p]]+1,
hd===Complex,SimplifyCount[Re[p]]+SimplifyCount[Im[p]]+1,
NumberQ[p],2,
]
]

• The automatic function is also provided in the last example of the ComplexityFunction help page. – Sjoerd C. de Vries May 31 '13 at 5:27

This function lives in the system as SimplifySimplifyCount.

• Could you provide some example that supports the case that this is in fact the function used or its equivalent? – Mr.Wizard Jun 1 '15 at 23:15
• @Mr.Wizard Well, we can see it's presence in top-level code, but unfortunately only parts of Simplify are written in Mathematica. In[12]:= Select[( Unprotect[#]; ClearAttributes[#,ReadProtected]; # -> Count[FullDefinition[#]//ToBoxes,"SimplifySimplifyCount",\[Infinity],Heads -> True] )&/@Join[Names["Simplify*"],Names["SimplifyDump*"]],Last[#]>0&] giving Out[12]= {SimplifyFunctionExpandRules -> 4,SimplifySimplifyCount -> 1,SimplifyDumpConjunctionSimplify -> 2,SimplifyDumpPiecewiseRule -> 4,SimplifyDump$FSTab -> 4} – Chip Hurst Jun 2 '15 at 0:31 Based on Vladimirs solution I wanted to post a faster alternative to SimplifyCount which produces the same results as SimplifyCount, but is a factor 3 faster. This can be very significant in case of complicated functions, it is however still significantly slower then Automatic. myNumberComplexity[x_Integer] := If[Positive[x], IntegerLength[x] - 1, IntegerLength[x]] myNumberComplexity[x_Real] := 1; myNumberComplexity[x_Rational] := myNumberComplexity[Numerator[x]] + myNumberComplexity[Denominator[x]] myNumberComplexity[x_Complex] := myNumberComplexity[Re[x]] + myNumberComplexity[Im[x]] myNumberComplexity[x_] := 0; myComplexityFunctionNC[x_] := LeafCount[x] + Plus @@ myNumberComplexity /@ Level[x, {-1}]  It is also possible to increase the speed of SimplifyCount by a factor of two by replacing the sum of the two Ifs after hd===Integer with just this If[Positive[p], IntegerLength[p], IntegerLength[p] + 1]. I must however say that I have my doubts that SimplifyCount is still exactly what is being done in (Full-)Simplify. I have an example were SimplifyCount (or my alternateive) does not produce the same as Automatic. Here the example (which might take a full day (!) with SimplifyCount): $Assumptions = {{a, b, m, s, q, k, x, y, x0, x1, x2, x3,
X} \[Element] Reals , s > 0, b > 0, a > 0};
kuskgaus0b[a_, b_, m_, s_] :=
ProbabilityDistribution[(b*Sqrt[Gamma[3/b]/Gamma[b^(-1)]]*
Piecewise[{{Gamma[
b^(-1), ((a*(-\[FormalX] + m)*
Sqrt[Gamma[3/b]/Gamma[b^(-1)]])/s)^b]/(2*
Gamma[b^(-1)]), a*(\[FormalX] - m) <= 0}},
1 - Gamma[
b^(-1), ((a*(\[FormalX] - m)*Sqrt[Gamma[3/b]/Gamma[b^(-1)]])/
s)^b]/(2*
Gamma[b^(-1)])])/(E^(((\[FormalX] - m)^2*Gamma[3/b])/(s^2*
Gamma[b^(-1)]))^(b/2)*s*
Gamma[b^(-1)]), {\[FormalX], -Infinity, Infinity}]
D[PDF[kuskgaus0b[a, b, 0, 1], x]*x, b] /. b -> 2;
FullSimplify[%, ComplexityFunction -> Automatic] // AbsoluteTiming


And here the result with Automatic:

Piecewise[
{{(x*(Sqrt[2]*a*x*(-3 + EulerGamma + Log[2] + 2*Log[a*x]) + E^((a^2*x^2)/2)*(Sqrt[Pi]*(-2*(1 + x^2*(-3 + EulerGamma + Log[2]) + 2*x^2*Log[x]) +
Erfc[(a*x)/Sqrt[2]]*(1 + EulerGamma*(1 + x^2) + x^2*(-3 + Log[2]) + Log[2] + 2*x^2*Log[x] + 2*Log[a*x])) + MeijerG[{{}, {1, 1}}, {{0, 0, 1/2}, {}},
(a^2*x^2)/2])))/(4*Sqrt[2]*E^(((1 + a^2)*x^2)/2)*Pi), x > 0}},
(x*(a*x*(-6 + 2*EulerGamma + Log[4*a^4*x^4]) - Sqrt[2]*E^((a^2*x^2)/2)*(Sqrt[Pi]*(1 + Erf[(a*x)/Sqrt[2]])*(1 + EulerGamma + (-3 + EulerGamma)*x^2 + x^2*Log[2*x^2] +
Log[2*a^2*x^2]) + MeijerG[{{}, {1, 1}}, {{0, 0, 1/2}, {}}, (a^2*x^2)/2])))/(8*E^(((1 + a^2)*x^2)/2)*Pi)]


And now with SimplifyCount:

Piecewise[{{ComplexInfinity, x == 0},
{(x*(Sqrt[2]*a*x*(-3 + EulerGamma + Log[2] + 2*Log[a*x]) - E^((a^2*x^2)/2)*(-2*Sqrt[2]*a*x*HypergeometricPFQ[{1/2, 1/2}, {3/2, 3/2}, -(a^2*x^2)/2] +
Sqrt[Pi]*x^2*(1 + Erf[(a*x)/Sqrt[2]])*(-3 + EulerGamma + Log[2] + 2*Log[x]) + Sqrt[Pi]*(1 + Erf[(a*x)/Sqrt[2]]*(1 + EulerGamma + Log[2] + 2*Log[a*x])))))/
(4*Sqrt[2]*E^(((1 + a^2)*x^2)/2)*Pi), x > 0}},
(x*(E^((a^2*x^2)/2)*(4*a*x*HypergeometricPFQ[{1/2, 1/2}, {3/2, 3/2}, -(a^2*x^2)/2] - Sqrt[2*Pi]*(1 + (-3 + EulerGamma)*x^2 + x^2*Log[2*x^2] +
Erf[(a*x)/Sqrt[2]]*(1 + EulerGamma + (-3 + EulerGamma)*x^2 + x^2*Log[2*x^2] + Log[2*a^2*x^2]))) + a*x*(-6 + 2*EulerGamma + Log[4*a^4*x^4])))/
(8*E^(((1 + a^2)*x^2)/2)*Pi)]


The differences are the additional Infinity at 0, and the change from MeijerG to HypergeometricPFQ.

• Could you include that example? If it is extremely long perhaps you could put it on pastebin or similar? – Mr.Wizard Jun 2 '15 at 0:14
• Ok I edited my post to include the results. I do not know where to put the input though, since it is huge. I will see tomorrow where to put it. – erazortt Jun 2 '15 at 1:11
• I have managed to strip down the example to something presentable. Have fun – erazortt Jun 2 '15 at 8:07

I ended up with this code:

NumberComplexity[x_Integer] := IntegerLength[x];
NumberComplexity[x_Real] := Round[Precision[x]];
NumberComplexity[x_Rational] := NumberComplexity[Numerator[x]] +
NumberComplexity[Denominator[x]];
NumberComplexity[x_Complex] := NumberComplexity[Re[x]] + NumberComplexity[Im[x]];
MyComplexityFunction[x_] := LeafCount[x] +
Total[NumberComplexity /@ Cases[x, _Integer | _Real | _Rational | _Complex, {0, ∞}]];


• You might want to be careful of the Hold attributes of these functions. When you put in, for instance 4000/2000, Mathematica will automatically convert this to 2 before calculating the complexity of the expression in its original form. Try using Trace` to see precisely what is happening. When you ask for improvements, it also depends what you are looking for. You haven't specified precisely what you want so it's hard to recommend improvements. Finally, I would recommend using lower cases for your function names as this avoids accidentally chosing Mathematica's built in functions. – Jonathan Shock May 31 '13 at 0:45