Skip to main content

performance tuning - Progress bar for FullSimplify


Sometimes FullSimplify takes a really long time and it is not really clear if it makes sense to wait another half an hour in hopes for it to finish, or if it will actually take three years in which case cancelling it and improving the approach would be the way to go. Having a progress bar in place, which shows the percent of calculation per unit of time (and maybe even a time prediction until finish) would be highly useful to make such decisions. I looked online and found a few links talking about progress bars. However, these realizations rely on an explicit iterator to keep track of. My interest is solely in monitoring the FullSimplify function and I do not know of any iterator to access there. So basically, I guess my question is:


Is there any way to predict how much time FullSimplify will need to finish in each case?



Answer



I don't think it is possible for FullSimplify to assess how far it is from a meaningful reduction of complexity. At every stage parts of the expression may after some transformation cancel (or not).


Sometimes complexity has to be increased before it can be lowered (as I showed in this answer). Simplification is the process of minimizing complexity, where the complexity function has numerous local minimums. This is basically a very difficult and unpredictable problem.


To have some kind of progress indication you could provide FullSimplify with a ComplexityFunction of your own, one which stores the complexity of the expressions fed through it:


lc = {}; (* List to store intermediate complicity values *)
myLeafCount[expr_] := Module[{c}, AppendTo[lc, c = LeafCount[expr]]; c]


The Automatic method is slightly more complicated than LeafCount (you can find it at the bottom of the ComplexityFunction page), but for a demonstration this suffices.


First, lets pick a function to simplify. This question has a nice, complex one:


expr = x[t] /. 
DSolve[{z'[t] == d (x[t] + u) - k (z[t] + s),
y'[t] == -R*x[t] v - R y[t] u - R u v + k (1 - c (x[t] + u) - (y[t] + v)),
x'[t] == R x[t] v + R y[t] u + R u v - x[t] - u},
{y[t], z[t], x[t]}, t];

It has a huge LeafCount:



myLeafCount[expr]
(* 34464 *)

Then we generate a dynamic plot of the intermediate results


Dynamic[ListPlot[lc]]

and we start the simplification:


FullSimplify[expr, ComplexityFunction -> myLeafCount]

We get a refresh of the plot for every call to myLeafCount.



After 20 steps:


Mathematica graphics


100 steps:


Mathematica graphics


1,000 steps (note Mathematica rescales the plot to show the parts it thinks are most interesting):


Mathematica graphics


10,000 steps:


Mathematica graphics


100,000 steps:


Mathematica graphics



200,000 steps:


Mathematica graphics


and after a few hours it ends at 312,893 steps:


Mathematica graphics


with a result that has a LeafCount of 727.


As you can see there are quite a few very similar patterns in it. My guess it is trying various permutations of sub-expressions recursively.


Although this is a poor substitute for a progress bar (especially given that it is still difficult to see when it will finish), it will give you some indication of what's going on and whether the simplification process got stuck somewhere.


I guess this all should also suffice to show why it would be very difficult to make a real progress bar.


Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

How to thread a list

I have data in format data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}} Tableform: I want to thread it to : tdata = {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} Tableform: And I would like to do better then pseudofunction[n_] := Transpose[{data2[[1]], data2[[n]]}]; SetAttributes[pseudofunction, Listable]; Range[2, 4] // pseudofunction Here is my benchmark data, where data3 is normal sample of real data. data3 = Drop[ExcelWorkBook[[Column1 ;; Column4]], None, 1]; data2 = {a #, b #, c #, d #} & /@ Range[1, 10^5]; data = RandomReal[{0, 1}, {10^6, 4}]; Here is my benchmark code kptnw[list_] := Transpose[{Table[First@#, {Length@# - 1}], Rest@#}, {3, 1, 2}] &@list kptnw2[list_] := Transpose[{ConstantArray[First@#, Length@# - 1], Rest@#}, {3, 1, 2}] &@list OleksandrR[list_] := Flatten[Outer[List, List@First[list], Rest[list], 1], {{2}, {1, 4}}] paradox2[list_] := Partition[Riffle[list[[1]], #], 2] & /@ Drop[list, 1] RM[list_] := FoldList[Transpose[{First@li...

front end - keyboard shortcut to invoke Insert new matrix

I frequently need to type in some matrices, and the menu command Insert > Table/Matrix > New... allows matrices with lines drawn between columns and rows, which is very helpful. I would like to make a keyboard shortcut for it, but cannot find the relevant frontend token command (4209405) for it. Since the FullForm[] and InputForm[] of matrices with lines drawn between rows and columns is the same as those without lines, it's hard to do this via 3rd party system-wide text expanders (e.g. autohotkey or atext on mac). How does one assign a keyboard shortcut for the menu item Insert > Table/Matrix > New... , preferably using only mathematica? Thanks! Answer In the MenuSetup.tr (for linux located in the $InstallationDirectory/SystemFiles/FrontEnd/TextResources/X/ directory), I changed the line MenuItem["&New...", "CreateGridBoxDialog"] to read MenuItem["&New...", "CreateGridBoxDialog", MenuKey["m", Modifiers-...