Comment #29 on issue 2607 by [email protected]: as_numer_denom() is too slow
http://code.google.com/p/sympy/issues/detail?id=2607

I'm not sure what I'm missing here, but:

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

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

In [3]: %time u = a.as_numer_denom4()
CPU times: user 0.14 s, sys: 0.00 s, total: 0.14 s
Wall time: 0.14 s

In [5]: %time u = together(a)
CPU times: user 0.16 s, sys: 0.00 s, total: 0.16 s
Wall time: 0.17 s

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

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

In [9]: %time u = a.as_numer_denom4()
CPU times: user 0.61 s, sys: 0.00 s, total: 0.61 s
Wall time: 0.62 s

In [11]: %time u = together(a)
CPU times: user 0.70 s, sys: 0.00 s, total: 0.70 s
Wall time: 0.70 s

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

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

In [15]: %time u = a.as_numer_denom4()
CPU times: user 88.68 s, sys: 0.01 s, total: 88.69 s
Wall time: 88.70 s

In [17]: %time u = together(a)
CPU times: user 97.71 s, sys: 0.00 s, total: 97.71 s
Wall time: 97.72 s

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

Does together() make any other promises about the structure of the output (...)?

Yes:

In [1]: from operator import div

In [2]: f = 1/x**2 + 1/x

In [3]: f
Out[3]:
1   1
─ + ──
x    2
    x

In [4]: div(*f.as_numer_denom())
Out[4]:
 2
x  + x
──────
   3
  x

In [5]: div(*f.as_numer_denom1())
Out[5]:
 2
x  + x
──────
   3
  x

In [6]: div(*f.as_numer_denom2())
Out[6]:
 2
x  + x
──────
   3
  x

In [7]: div(*f.as_numer_denom3())
Out[7]:
 2
x  + x
──────
   3
  x

In [8]: div(*f.as_numer_denom4())
Out[8]:
 2
x  + x
──────
   3
  x

In [9]: together(f)
Out[9]:
x + 1
─────
   2
  x

but

In [10]: 1/(x**2 - 1) + 1/(x - 1)
Out[10]:
  1        1
────── + ─────
 2       x - 1
x  - 1

In [11]: together(_)
Out[11]:
    2
   x  + x - 2
────────────────
        ⎛ 2    ⎞
(x - 1)⋅⎝x  - 1⎠

In [11]: cancel(_)
Out[11]:
x + 2
──────
 2
x  - 1

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, currently this is very nice that we get results on three levels: 1) no lcm (as_numer_denom()), 2) structural lcm (together()) and 3) algebraic lcm (together() and cancel()).

It would be nice to: 1) make lcm() aware of gcd_terms() (give it symbolic capabilities as factor() (for example) has), 2) make together() aware of all three variations of putting fractions together and 3) make as_numer_denom() call together() and return (numer, denom) without any further computations.

--
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