|
"""Tools for manipulation of rational expressions. """ |
|
|
|
|
|
from sympy.core import Basic, Add, sympify |
|
from sympy.core.exprtools import gcd_terms |
|
from sympy.utilities import public |
|
from sympy.utilities.iterables import iterable |
|
|
|
|
|
@public |
|
def together(expr, deep=False, fraction=True): |
|
""" |
|
Denest and combine rational expressions using symbolic methods. |
|
|
|
This function takes an expression or a container of expressions |
|
and puts it (them) together by denesting and combining rational |
|
subexpressions. No heroic measures are taken to minimize degree |
|
of the resulting numerator and denominator. To obtain completely |
|
reduced expression use :func:`~.cancel`. However, :func:`~.together` |
|
can preserve as much as possible of the structure of the input |
|
expression in the output (no expansion is performed). |
|
|
|
A wide variety of objects can be put together including lists, |
|
tuples, sets, relational objects, integrals and others. It is |
|
also possible to transform interior of function applications, |
|
by setting ``deep`` flag to ``True``. |
|
|
|
By definition, :func:`~.together` is a complement to :func:`~.apart`, |
|
so ``apart(together(expr))`` should return expr unchanged. Note |
|
however, that :func:`~.together` uses only symbolic methods, so |
|
it might be necessary to use :func:`~.cancel` to perform algebraic |
|
simplification and minimize degree of the numerator and denominator. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import together, exp |
|
>>> from sympy.abc import x, y, z |
|
|
|
>>> together(1/x + 1/y) |
|
(x + y)/(x*y) |
|
>>> together(1/x + 1/y + 1/z) |
|
(x*y + x*z + y*z)/(x*y*z) |
|
|
|
>>> together(1/(x*y) + 1/y**2) |
|
(x + y)/(x*y**2) |
|
|
|
>>> together(1/(1 + 1/x) + 1/(1 + 1/y)) |
|
(x*(y + 1) + y*(x + 1))/((x + 1)*(y + 1)) |
|
|
|
>>> together(exp(1/x + 1/y)) |
|
exp(1/y + 1/x) |
|
>>> together(exp(1/x + 1/y), deep=True) |
|
exp((x + y)/(x*y)) |
|
|
|
>>> together(1/exp(x) + 1/(x*exp(x))) |
|
(x + 1)*exp(-x)/x |
|
|
|
>>> together(1/exp(2*x) + 1/(x*exp(3*x))) |
|
(x*exp(x) + 1)*exp(-3*x)/x |
|
|
|
""" |
|
def _together(expr): |
|
if isinstance(expr, Basic): |
|
if expr.is_Atom or (expr.is_Function and not deep): |
|
return expr |
|
elif expr.is_Add: |
|
return gcd_terms(list(map(_together, Add.make_args(expr))), fraction=fraction) |
|
elif expr.is_Pow: |
|
base = _together(expr.base) |
|
|
|
if deep: |
|
exp = _together(expr.exp) |
|
else: |
|
exp = expr.exp |
|
|
|
return expr.func(base, exp) |
|
else: |
|
return expr.func(*[ _together(arg) for arg in expr.args ]) |
|
elif iterable(expr): |
|
return expr.__class__([ _together(ex) for ex in expr ]) |
|
|
|
return expr |
|
|
|
return _together(sympify(expr)) |
|
|