Exemplo n.º 1
0
def MacMahonOmega(var,
                  expression,
                  denominator=None,
                  op=operator.ge,
                  Factorization_sort=False,
                  Factorization_simplify=True):
    r"""
    Return `\Omega_{\mathrm{op}}` of ``expression`` with respect to ``var``.

    To be more precise, calculate

    .. MATH::

        \Omega_{\mathrm{op}} \frac{n}{d_1 \dots d_n}

    for the numerator `n` and the factors `d_1`, ..., `d_n` of
    the denominator, all of which are Laurent polynomials in ``var``
    and return a (partial) factorization of the result.

    INPUT:

    - ``var`` -- a variable or a representation string of a variable

    - ``expression`` -- a
      :class:`~sage.structure.factorization.Factorization`
      of Laurent polynomials or, if ``denominator`` is specified,
      a Laurent polynomial interpreted as the numerator of the
      expression

    - ``denominator`` -- a Laurent polynomial or a
      :class:`~sage.structure.factorization.Factorization` (consisting
      of Laurent polynomial factors) or a tuple/list of factors (Laurent
      polynomials)

    - ``op`` -- (default: ``operator.ge``) an operator

      At the moment only ``operator.ge`` is implemented.

    - ``Factorization_sort`` (default: ``False``) and
      ``Factorization_simplify`` (default: ``True``) -- are passed on to
      :class:`sage.structure.factorization.Factorization` when creating
      the result

    OUTPUT:

    A (partial) :class:`~sage.structure.factorization.Factorization`
    of the result whose factors are Laurent polynomials

    .. NOTE::

        The numerator of the result may not be factored.

    REFERENCES:

    - [Mac1915]_

    - [APR2001]_

    EXAMPLES::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(ZZ)

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu, 1 - z/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1 * (-x*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu])
        (-x*y*z + 1) * (-x + 1)^-1 * (-y + 1)^-1 * (-x*z + 1)^-1 * (-y*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^2])
        1 * (-x + 1)^-1 * (-x^2*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu])
        (x*y + 1) * (-x + 1)^-1 * (-x*y^2 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu^2])
        (-x^2*y*z - x*y^2*z + x*y*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x^2*z + 1)^-1 * (-y^2*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^3])
        1 * (-x + 1)^-1 * (-x^3*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^4])
        1 * (-x + 1)^-1 * (-x^4*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^3, 1 - y/mu])
        (x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^3 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^4, 1 - y/mu])
        (x*y^3 + x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^4 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu, 1 - z/mu])
        (x*y*z + x*y + x*z + 1) *
        (-x + 1)^-1 * (-x*y^2 + 1)^-1 * (-x*z^2 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y*mu, 1 - z/mu])
        (-x*y*z^2 - x*y*z + x*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x*z^2 + 1)^-1 * (-y*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z*mu, 1 - w/mu])
        (x*y*z*w^2 + x*y*z*w - x*y*w - x*z*w - y*z*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-z + 1)^-1 *
        (-x*w + 1)^-1 * (-y*w + 1)^-1 * (-z*w + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu, 1 - w/mu])
        (x^2*y*z*w + x*y^2*z*w - x*y*z*w - x*y*z - x*y*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 *
        (-x*z + 1)^-1 * (-x*w + 1)^-1 * (-y*z + 1)^-1 * (-y*w + 1)^-1

        sage: MacMahonOmega(mu, mu^-2, [1 - x*mu, 1 - y/mu])
        x^2 * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^-1, [1 - x*mu, 1 - y/mu])
        x * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu, [1 - x*mu, 1 - y/mu])
        (-x*y + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    We demonstrate the different allowed input variants::

        sage: MacMahonOmega(mu,
        ....:     Factorization([(mu, 2), (1 - x*mu, -1), (1 - y/mu, -1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, (1 - x*mu)*(1 - y/mu))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2 / ((1 - x*mu)*(1 - y/mu)))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    TESTS::

        sage: MacMahonOmega(mu, 1, [1 - x*mu])
        1 * (-x + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x/mu])
        1
        sage: MacMahonOmega(mu, 0, [1 - x*mu])
        0
        sage: MacMahonOmega(mu, L(1), [])
        1
        sage: MacMahonOmega(mu, L(0), [])
        0
        sage: MacMahonOmega(mu, 2, [])
        2
        sage: MacMahonOmega(mu, 2*mu, [])
        2
        sage: MacMahonOmega(mu, 2/mu, [])
        0

    ::

        sage: MacMahonOmega(mu, Factorization([(1/mu, 1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x, -1)]))
        0
        sage: MacMahonOmega(mu, Factorization([(2, -1)]))
        1 * 2^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - z, 1 - y/mu])
        1 * (-z + 1)^-1 * (-x + 1)^-1 * (-x*y + 1)^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu], op=operator.lt)
        Traceback (most recent call last):
        ...
        NotImplementedError: At the moment, only Omega_ge is implemented.

        sage: MacMahonOmega(mu, 1, Factorization([(1 - x*mu, -1)]))
        Traceback (most recent call last):
        ...
        ValueError: Factorization (-mu*x + 1)^-1 of the denominator
        contains negative exponents.

        sage: MacMahonOmega(2*mu, 1, [1 - x*mu])
        Traceback (most recent call last):
        ...
        ValueError: 2*mu is not a variable.

        sage: MacMahonOmega(mu, 1, Factorization([(0, 2)]))
        Traceback (most recent call last):
        ...
        ZeroDivisionError: Denominator contains a factor 0.

        sage: MacMahonOmega(mu, 1, [2 - x*mu])
        Traceback (most recent call last):
        ...
        NotImplementedError: Factor 2 - x*mu is not normalized.

        sage: MacMahonOmega(mu, 1, [1 - x*mu - mu^2])
        Traceback (most recent call last):
        ...
        NotImplementedError: Cannot handle factor 1 - x*mu - mu^2.

    ::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(QQ)
        sage: MacMahonOmega(mu, 1/mu,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 2)], unit=2))
        1/2*x * (-x + 1)^-1 * (-x*y + 1)^-2
    """
    from sage.arith.misc import factor
    from sage.misc.misc_c import prod
    from sage.rings.integer_ring import ZZ
    from sage.rings.polynomial.laurent_polynomial_ring \
        import LaurentPolynomialRing, LaurentPolynomialRing_univariate
    from sage.structure.factorization import Factorization

    if op != operator.ge:
        raise NotImplementedError(
            'At the moment, only Omega_ge is implemented.')

    if denominator is None:
        if isinstance(expression, Factorization):
            numerator = expression.unit() * \
                        prod(f**e for f, e in expression if e > 0)
            denominator = tuple(f for f, e in expression if e < 0
                                for _ in range(-e))
        else:
            numerator = expression.numerator()
            denominator = expression.denominator()
    else:
        numerator = expression
    # at this point we have numerator/denominator

    if isinstance(denominator, (list, tuple)):
        factors_denominator = denominator
    else:
        if not isinstance(denominator, Factorization):
            denominator = factor(denominator)
        if not denominator.is_integral():
            raise ValueError(
                'Factorization {} of the denominator '
                'contains negative exponents.'.format(denominator))
        numerator *= ZZ(1) / denominator.unit()
        factors_denominator = tuple(factor for factor, exponent in denominator
                                    for _ in range(exponent))
    # at this point we have numerator/factors_denominator

    P = var.parent()
    if isinstance(P, LaurentPolynomialRing_univariate) and P.gen() == var:
        L = P
        L0 = L.base_ring()
    elif var in P.gens():
        var = repr(var)
        L0 = LaurentPolynomialRing(
            P.base_ring(), tuple(v for v in P.variable_names() if v != var))
        L = LaurentPolynomialRing(L0, var)
        var = L.gen()
    else:
        raise ValueError('{} is not a variable.'.format(var))

    other_factors = []
    to_numerator = []
    decoded_factors = []
    for factor in factors_denominator:
        factor = L(factor)
        D = factor.dict()
        if not D:
            raise ZeroDivisionError('Denominator contains a factor 0.')
        elif len(D) == 1:
            exponent, coefficient = next(iteritems(D))
            if exponent == 0:
                other_factors.append(L0(factor))
            else:
                to_numerator.append(factor)
        elif len(D) == 2:
            if D.get(0, 0) != 1:
                raise NotImplementedError(
                    'Factor {} is not normalized.'.format(factor))
            D.pop(0)
            exponent, coefficient = next(iteritems(D))
            decoded_factors.append((-coefficient, exponent))
        else:
            raise NotImplementedError(
                'Cannot handle factor {}.'.format(factor))
    numerator = L(numerator) / prod(to_numerator)

    result_numerator, result_factors_denominator = \
        _Omega_(numerator.dict(), decoded_factors)
    if result_numerator == 0:
        return Factorization([], unit=result_numerator)

    return Factorization([(result_numerator, 1)] + list(
        (f, -1) for f in other_factors) + list(
            (1 - f, -1) for f in result_factors_denominator),
                         sort=Factorization_sort,
                         simplify=Factorization_simplify)
Exemplo n.º 2
0
def MacMahonOmega(var, expression, denominator=None, op=operator.ge,
          Factorization_sort=False, Factorization_simplify=True):
    r"""
    Return `\Omega_{\mathrm{op}}` of ``expression`` with respect to ``var``.

    To be more precise, calculate

    .. MATH::

        \Omega_{\mathrm{op}} \frac{n}{d_1 \dots d_n}

    for the numerator `n` and the factors `d_1`, ..., `d_n` of
    the denominator, all of which are Laurent polynomials in ``var``
    and return a (partial) factorization of the result.

    INPUT:

    - ``var`` -- a variable or a representation string of a variable

    - ``expression`` -- a
      :class:`~sage.structure.factorization.Factorization`
      of Laurent polynomials or, if ``denominator`` is specified,
      a Laurent polynomial interpreted as the numerator of the
      expression

    - ``denominator`` -- a Laurent polynomial or a
      :class:`~sage.structure.factorization.Factorization` (consisting
      of Laurent polynomial factors) or a tuple/list of factors (Laurent
      polynomials)

    - ``op`` -- (default: ``operator.ge``) an operator

      At the moment only ``operator.ge`` is implemented.

    - ``Factorization_sort`` (default: ``False``) and
      ``Factorization_simplify`` (default: ``True``) -- are passed on to
      :class:`sage.structure.factorization.Factorization` when creating
      the result

    OUTPUT:

    A (partial) :class:`~sage.structure.factorization.Factorization`
    of the result whose factors are Laurent polynomials

    .. NOTE::

        The numerator of the result may not be factored.

    REFERENCES:

    - [Mac1915]_

    - [APR2001]_

    EXAMPLES::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(ZZ)

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu, 1 - z/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1 * (-x*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu])
        (-x*y*z + 1) * (-x + 1)^-1 * (-y + 1)^-1 * (-x*z + 1)^-1 * (-y*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^2])
        1 * (-x + 1)^-1 * (-x^2*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu])
        (x*y + 1) * (-x + 1)^-1 * (-x*y^2 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu^2])
        (-x^2*y*z - x*y^2*z + x*y*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x^2*z + 1)^-1 * (-y^2*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^3])
        1 * (-x + 1)^-1 * (-x^3*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^4])
        1 * (-x + 1)^-1 * (-x^4*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^3, 1 - y/mu])
        (x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^3 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^4, 1 - y/mu])
        (x*y^3 + x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^4 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu, 1 - z/mu])
        (x*y*z + x*y + x*z + 1) *
        (-x + 1)^-1 * (-x*y^2 + 1)^-1 * (-x*z^2 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y*mu, 1 - z/mu])
        (-x*y*z^2 - x*y*z + x*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x*z^2 + 1)^-1 * (-y*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z*mu, 1 - w/mu])
        (x*y*z*w^2 + x*y*z*w - x*y*w - x*z*w - y*z*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-z + 1)^-1 *
        (-x*w + 1)^-1 * (-y*w + 1)^-1 * (-z*w + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu, 1 - w/mu])
        (x^2*y*z*w + x*y^2*z*w - x*y*z*w - x*y*z - x*y*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 *
        (-x*z + 1)^-1 * (-x*w + 1)^-1 * (-y*z + 1)^-1 * (-y*w + 1)^-1

        sage: MacMahonOmega(mu, mu^-2, [1 - x*mu, 1 - y/mu])
        x^2 * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^-1, [1 - x*mu, 1 - y/mu])
        x * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu, [1 - x*mu, 1 - y/mu])
        (-x*y + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    We demonstrate the different allowed input variants::

        sage: MacMahonOmega(mu,
        ....:     Factorization([(mu, 2), (1 - x*mu, -1), (1 - y/mu, -1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, (1 - x*mu)*(1 - y/mu))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2 / ((1 - x*mu)*(1 - y/mu)))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    TESTS::

        sage: MacMahonOmega(mu, 1, [1 - x*mu])
        1 * (-x + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x/mu])
        1
        sage: MacMahonOmega(mu, 0, [1 - x*mu])
        0
        sage: MacMahonOmega(mu, L(1), [])
        1
        sage: MacMahonOmega(mu, L(0), [])
        0
        sage: MacMahonOmega(mu, 2, [])
        2
        sage: MacMahonOmega(mu, 2*mu, [])
        2
        sage: MacMahonOmega(mu, 2/mu, [])
        0

    ::

        sage: MacMahonOmega(mu, Factorization([(1/mu, 1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x, -1)]))
        0
        sage: MacMahonOmega(mu, Factorization([(2, -1)]))
        1 * 2^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - z, 1 - y/mu])
        1 * (-z + 1)^-1 * (-x + 1)^-1 * (-x*y + 1)^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu], op=operator.lt)
        Traceback (most recent call last):
        ...
        NotImplementedError: At the moment, only Omega_ge is implemented.

        sage: MacMahonOmega(mu, 1, Factorization([(1 - x*mu, -1)]))
        Traceback (most recent call last):
        ...
        ValueError: Factorization (-mu*x + 1)^-1 of the denominator
        contains negative exponents.

        sage: MacMahonOmega(2*mu, 1, [1 - x*mu])
        Traceback (most recent call last):
        ...
        ValueError: 2*mu is not a variable.

        sage: MacMahonOmega(mu, 1, Factorization([(0, 2)]))
        Traceback (most recent call last):
        ...
        ZeroDivisionError: Denominator contains a factor 0.

        sage: MacMahonOmega(mu, 1, [2 - x*mu])
        Traceback (most recent call last):
        ...
        NotImplementedError: Factor 2 - x*mu is not normalized.

        sage: MacMahonOmega(mu, 1, [1 - x*mu - mu^2])
        Traceback (most recent call last):
        ...
        NotImplementedError: Cannot handle factor 1 - x*mu - mu^2.

    ::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(QQ)
        sage: MacMahonOmega(mu, 1/mu,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 2)], unit=2))
        1/2*x * (-x + 1)^-1 * (-x*y + 1)^-2
    """
    from sage.arith.misc import factor
    from sage.misc.misc_c import prod
    from sage.rings.integer_ring import ZZ
    from sage.rings.polynomial.laurent_polynomial_ring \
        import LaurentPolynomialRing, LaurentPolynomialRing_univariate
    from sage.structure.factorization import Factorization

    if op != operator.ge:
        raise NotImplementedError('At the moment, only Omega_ge is implemented.')

    if denominator is None:
        if isinstance(expression, Factorization):
            numerator = expression.unit() * \
                        prod(f**e for f, e in expression if e > 0)
            denominator = tuple(f for f, e in expression if e < 0
                                for _ in range(-e))
        else:
            numerator = expression.numerator()
            denominator = expression.denominator()
    else:
        numerator = expression
    # at this point we have numerator/denominator

    if isinstance(denominator, (list, tuple)):
        factors_denominator = denominator
    else:
        if not isinstance(denominator, Factorization):
            denominator = factor(denominator)
        if not denominator.is_integral():
            raise ValueError('Factorization {} of the denominator '
                             'contains negative exponents.'.format(denominator))
        numerator *= ZZ(1) / denominator.unit()
        factors_denominator = tuple(factor
                                    for factor, exponent in denominator
                                    for _ in range(exponent))
    # at this point we have numerator/factors_denominator

    P = var.parent()
    if isinstance(P, LaurentPolynomialRing_univariate) and P.gen() == var:
        L = P
        L0 = L.base_ring()
    elif var in P.gens():
        var = repr(var)
        L0 = LaurentPolynomialRing(
            P.base_ring(), tuple(v for v in P.variable_names() if v != var))
        L = LaurentPolynomialRing(L0, var)
        var = L.gen()
    else:
        raise ValueError('{} is not a variable.'.format(var))

    other_factors = []
    to_numerator = []
    decoded_factors = []
    for factor in factors_denominator:
        factor = L(factor)
        D = factor.dict()
        if not D:
            raise ZeroDivisionError('Denominator contains a factor 0.')
        elif len(D) == 1:
            exponent, coefficient = next(iteritems(D))
            if exponent == 0:
                other_factors.append(L0(factor))
            else:
                to_numerator.append(factor)
        elif len(D) == 2:
            if D.get(0, 0) != 1:
                raise NotImplementedError('Factor {} is not normalized.'.format(factor))
            D.pop(0)
            exponent, coefficient = next(iteritems(D))
            decoded_factors.append((-coefficient, exponent))
        else:
            raise NotImplementedError('Cannot handle factor {}.'.format(factor))
    numerator = L(numerator) / prod(to_numerator)

    result_numerator, result_factors_denominator = \
        _Omega_(numerator.dict(), decoded_factors)
    if result_numerator == 0:
        return Factorization([], unit=result_numerator)

    return Factorization([(result_numerator, 1)] +
                         list((f, -1) for f in other_factors) +
                         list((1-f, -1) for f in result_factors_denominator),
                         sort=Factorization_sort,
                         simplify=Factorization_simplify)