Comment #32 on issue 2607 by asmeurer: as_numer_denom() is too slow
http://code.google.com/p/sympy/issues/detail?id=2607

(those benchmarks are done with cache off, so maybe this is the difference?).

Ah, that's it.  Here's what I get with the cache off:

In [1]: numers, denoms = zip(*((Symbol('n%d'%i),Symbol('d%d'%i)) for i in xrange(1000)))

In [2]: a = Add(*(n/d for n, d in zip(numers, denoms)))

In [3]: %timeit together(a)
1 loops, best of 3: 185 s per loop

In [4]: %timeit a.as_numer_denom4()
1 loops, best of 3: 182 s per loopIn [1]: numers, denoms = zip(*((Symbol('n%d'%i),Symbol('d%d'%i)) for i in xrange(1000)))

In [2]: a = Add(*(n/d for n, d in zip(numers, denoms)))

In [3]: %timeit together(a)
1 loops, best of 3: 185 s per loop

In [4]: %timeit a.as_numer_denom4()
1 loops, best of 3: 182 s per loop

This just illuminates something I've noticed here, which is that we are not really testing algorithms for their own sake, but against the current implementation of things like Mul.flatten. For example, as_numer_denom1() is so slow because *= is slow in SymPy (I guess it's quadratic, as it recomputes Mul.flatten each time, which makes as_numer_denom1() worse than as_numer_denom_orig()).

Therefore, I think we maybe shouldn't ignore that enormous speedup that the cache gives us for as_numer_denom4(). Perhaps as we optimize Mul.flatten and others in different ways, other options will become faster, but we should reconsider this when that heppens.

But the fact is, when the cache is on (as it usually is), as_numer_denom4() is very fast and together() is slow, And when it's off, they are both about the same.

together() computes structural lcm of denominators (not algebraic as lcm() does). This guarantees that the resulting denominator is minimal with respect to the structure of the input (as I said before). It also removes numerical contents.

So far, none of the as_numer_denom options do this, but I think they should (see comments 22 and 24), because this kind of preprocessing would be very fast and would result in smaller answers (ultimately making the whole thing faster). As for numerical factors, we would have to have to handle this anyway in as_numer_denom4 because of the issue noted in 20.

3) make as_numer_denom() call together() and return (numer, denom) without any further computations.

I disagree. The computation should happen in as_numer_denom() and together() should call that. See the last paragraph in comment 28. It doesn't make sense for together to compute the numerator and denominator, put them together, and then have as_numer_denom pull them apart again.

This sort of putting things together and pull them apart again has led to wrong results with as_real_imag and expand(complex=True) (I again refer you to issue 1985). I could easily see this happening here too.

--
You received this message because you are subscribed to the Google Groups 
"sympy-issues" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sympy-issues?hl=en.

Reply via email to