[GiNaC-devel] [PATCH] {add,
power}::eval(): convert terms into primitive polynomials
when possible.
Sheplyakov Alexei
varg at theor.jinr.ru
Sun Aug 12 04:06:00 CEST 2007
On Sat, Aug 11, 2007 at 11:11:57PM +0200, Richard B. Kreckel wrote:
> It is not some overhead that worries me. Rather, it is the algorithmic
> complexity of the new overhead. The new transformation appears to
> introduce quadratic behavior at the eval() level.
[snipped]
> >>Looking at the code it appears to me like mul::eval recurses now.
> >
> >mul::eval calls evalchildren, so it is recursive even without my patch.
>
>
> Well, but that recurses into *children* only! At the end of the loop
> that you introduced into mul::eval(), a new mul object is returned. It
> is not evaluated yet and enters mul::eval() again. And it might contain
> most of the original terms. This is an entirely different quantity of
> recursion that is responsible for potentially quadratic behavior, IINM.
mul::eval() *is quadratic* even without my patch:
ex mul::eval(int level) const
{
std::auto_ptr<epvector> evaled_seqp = evalchildren(level);
if (evaled_seqp.get()) {
// do more evaluation later
return (new mul(evaled_seqp, overall_coeff))->
setflag(status_flags::dynallocated);
}
If evaluation of children gives something non-trivial, a new mul object
is returned. It is not evaluated and enters mul::eval() again.
> That's bad.
My patch increases the coefficient. And that is indeed awful.
> One of the points of choosing the algorithms that are done at the eval()
> stage to be only subquadratic algorithms was that otherwise one might be
> unable to merely construct the ex object.
I think this requirement is way too strict. I'd say anything of polynomial
complexity (with "reasonable" coefficients) is OK.
> >>Wouldn't it be faster to collect the coefficients in one sweep?
> >
> >I've tried this (see the patch [1]), it has almost no effect.
>
>
> It still appears to be quadratic. Must it really be quadratic?
Yes. After numeric coefficients are collected, some re-evaluation is
necessary. For example,
(3*x+3*y)*(x+y) -> (3*(x+y)*(x+y)).eval() -> 3*(x+y)^2
1/9*(9*x+9*y)*(x+y)^2 -> ((x+y)*(x+y)^2).eval() -> (x+y)^3
(N.B.: the result is not mul object)
> >>Well, I recognize that most terms will be trivial in the following
> >>recursions, but still.
> >
> >My patch causes overhead even in the trivial case, e.g. when the
> >polynomial is already unit normal. Consider e.g.
> >
> >e = (x+1)*(2*x^2+x+1)*...*(100*x^100+99*x^99+...+1);
>
>
> Indeed. This expression is well suited to study the asymptotic behavior:
>
> $ { echo -n "time((1+x)"; for i in $(seq 2 100); do echo -n "*(1+x"; for
> j in $(seq 2 $i); do echo -n "+${j}*x^${j}"; done; echo -n ")"; done;
> echo ");";} | ginsh-1.3.5
> 0.089994s
To make the test a little bit more interesting, let's take more than 2 points:
{ echo "plot '-' using 1:2 with lines title 'mul::eval() asymptotic behaviour'"
echo
for N in `seq 100 100 2000`; do
TIME=$({ echo -n "time((1+x)"
for i in $(seq 2 $N); do
echo -n "*(1+x"
for j in $(seq 2 $i); do
echo -n "+${j}*x^${j}"
done
echo -n ")"
done
echo ");" ; } | ginsh | sed -e 's/s//g')
echo "$N $TIME"
done
echo "e" ; } | gnuplot -persist '-'
This gives a beautiful parabola (both with my patch or without it).
Coefficients are different, but both versions of mul::eval() are
quadratic.
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-devel/attachments/20070812/55d822ac/attachment.pgp
More information about the GiNaC-devel
mailing list