Re: Effect of Simplify on numeric vs symbolic
- To: mathgroup at smc.vnet.net
- Subject: [mg56009] Re: [mg55971] Effect of Simplify on numeric vs symbolic
- From: Daniel Lichtblau <danl at wolfram.com>
- Date: Wed, 13 Apr 2005 01:10:51 -0400 (EDT)
- References: <200504120926.FAA27663@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
carlos at colorado.edu wrote:
> In my previous example of FEM symbolic vs numeric speed all
> computations were with numbers. No variables were involved.
> The difference (minutes vs seconds) due largely due to Simplify.
>
> Here is a simpler example that illustrates the point, also taken from
> the same course. LineGaussRuleInfo returns weights and abcissae of 1D
> Gauss-Legendre quadrature rules of 1 to 5 points. Argument numer asks
> for exact information if False; if True it returns N[information].
> All computations involve nunbers only.
>
> Results of calls (at end of post) on a Mac laptop:
>
> numer rule n Eval time Simplify time
> True 4 50 0.00 sec 0.00 sec
> False 4 50 0.00 sec 78.01 sec (* Note: FullSimplify needed *)
> False 4 50 0.00 sec 0.00 sec (* found result in cache *)
>
> LineGaussRuleInfo[{rule_,numer_},point_]:= Module[
> {g2={-1,1}/Sqrt[3],w3={5/9,8/9,5/9},
> g3={-Sqrt[3/5],0,Sqrt[3/5]},
> w4={(1/2)-Sqrt[5/6]/6, (1/2)+Sqrt[5/6]/6,
> (1/2)+Sqrt[5/6]/6, (1/2)-Sqrt[5/6]/6},
> g4={-Sqrt[(3+2*Sqrt[6/5])/7],-Sqrt[(3-2*Sqrt[6/5])/7],
> Sqrt[(3-2*Sqrt[6/5])/7], Sqrt[(3+2*Sqrt[6/5])/7]},
> g5={-Sqrt[5+2*Sqrt[10/7]],-Sqrt[5-2*Sqrt[10/7]],0,
> Sqrt[5-2*Sqrt[10/7]], Sqrt[5+2*Sqrt[10/7]]}/3,
> w5={322-13*Sqrt[70],322+13*Sqrt[70],512,
> 322+13*Sqrt[70],322-13*Sqrt[70]}/900,
> i=point,p=rule,info={{Null,Null},0}},
> If [p==1, info={0,2}];
> If [p==2, info={g2[[i]],1}];
> If [p==3, info={g3[[i]],w3[[i]]}];
> If [p==4, info={g4[[i]],w4[[i]]}];
> If [p==5, info={g5[[i]],w5[[i]]}];
> If [numer, Return[N[info]], Return[info] ];
> ];
>
> PerverseExpression[rule_,n_,numer_]:=Module[{xw,tEval,tSymb,x},
> xw=Table[LineGaussRuleInfo[{rule,numer},i],{i,1,rule}];
> {tEval,x}=Timing[Product[(i+2)*xw[[i,1]]^n,{i,1,rule}]];
> {tSymp,x}=Timing[FullSimplify[x]];
> Return[{tEval,tSymp,x}]];
>
> Print[PerverseExpression[4,50,True ]];
> Print[PerverseExpression[4,50,False]];
> Print[PerverseExpression[4,50,False]]; (* Cached *)
I have run this example on several Linux versions (3.0, 4.2, present,
and future). It never seems to take more than about 0.1 second for the
first invocation of PerverseExpression[4,50,False]. So either you have
found a strange platform dependency or you ran something other than what
you sent.
The general question remains as to whether or why something of this sort
(involving products of possibly nested radicals) might be slow to
simplify. I'll just say that symbolic simplification can employ methods
that become arbitrarily bad for a given type of problem. In this case
there is a way out. I'll start with the code.
First I rewrote so it would be more to my liking (maybe I should mention
that I don't much like Fortran. In any language.) This is a bit awkward
in that it uses globals for g and w, but I saw no point to doing
otherwise as they used in a way that is essentially static. In
production code one might do as I did but put them in a specialized context.
g = {{0}, {-1,1}/Sqrt[3], Sqrt[3/5]*{-1,0,1},
{-Sqrt[(3+2*Sqrt[6/5])/7],-Sqrt[(3-2*Sqrt[6/5])/7],
Sqrt[(3-2*Sqrt[6/5])/7], Sqrt[(3+2*Sqrt[6/5])/7]},
{-Sqrt[5+2*Sqrt[10/7]],-Sqrt[5-2*Sqrt[10/7]],0,
Sqrt[5-2*Sqrt[10/7]], Sqrt[5+2*Sqrt[10/7]]}/3};
w = {{2}, {1,1}, {5/9,8/9,5/9},
{(1/2)-Sqrt[5/6]/6, (1/2)+Sqrt[5/6]/6,
(1/2)+Sqrt[5/6]/6, (1/2)-Sqrt[5/6]/6},
{322-13*Sqrt[70],322+13*Sqrt[70],512,
322+13*Sqrt[70],322-13*Sqrt[70]}/900};
LineGaussRuleInfo[p_,i_,numer_:True] :=
If [numer,N[#],#]& [{g[[p,i]],w[[p,i]]}]
PerverseExpression[rule_,n_,numer_:True] := Module[{xw, x},
xw = Table[LineGaussRuleInfo[rule,i,numer], {i,rule}];
x = Product[(i+2)*xw[[i,1]]^n, {i,rule}];
Timing[FullSimplify[x]]
]
This alone does not buy us any speed; I simply prefer the code in this
form for further work. The next undocumented tactic will put the
algebraics we use into a common number field. This will often make the
speed of manipulation considerably better than might otherwise be the case.
g = {{0}, {-1,1}/Sqrt[3], Sqrt[3/5]*{-1,0,1},
Algebraics`Private`NFToCommonField[
{-Sqrt[(3+2*Sqrt[6/5])/7],-Sqrt[(3-2*Sqrt[6/5])/7],
Sqrt[(3-2*Sqrt[6/5])/7], Sqrt[(3+2*Sqrt[6/5])/7]}],
Algebraics`Private`NFToCommonField[
{-Sqrt[5+2*Sqrt[10/7]],-Sqrt[5-2*Sqrt[10/7]],0,
Sqrt[5-2*Sqrt[10/7]], Sqrt[5+2*Sqrt[10/7]]}/3]};
If we now do the rest of the computations, in a fresh kernel session,
say, we find that the exact case is about as fast as the numeric and
still gives
51688655113813386391457928 /
31947156789289937013270310127837514166970738216377867502160\
370349884033203125
(about 1.62*10^(-51)).
This simply illustrates the age-old lesson that a specialized approach
will often beat a general one, if it is not obvious in the general case
what specialized route(s) to take and in what order.
Daniel Lichtblau
Wolfram Research
- References:
- Effect of Simplify on numeric vs symbolic
- From: carlos@colorado.edu
- Effect of Simplify on numeric vs symbolic