예제 #1
0
def test_random_poly():
    poly = random_poly(x, 10, -100, 100, polys=False)

    assert Poly(poly).degree() == 10
    assert all(-100 <= coeff <= 100 for coeff in Poly(poly).coeffs()) is True

    poly = random_poly(x, 10, -100, 100, polys=True)

    assert poly.degree() == 10
    assert all(-100 <= coeff <= 100 for coeff in poly.coeffs()) is True
예제 #2
0
def test_random_poly():
    poly = random_poly(x, 10, -100, 100, polys=False)

    assert Poly(poly).degree() == 10
    assert all(-100 <= coeff <= 100 for coeff in Poly(poly).coeffs()) is True

    poly = random_poly(x, 10, -100, 100, polys=True)

    assert poly.degree() == 10
    assert all(-100 <= coeff <= 100 for coeff in poly.coeffs()) is True
예제 #3
0
def dmp_deflate(f, u, K):
    """Map `x_i**m_i` to `y_i` in a polynomial in `K[X]`. """
    if dmp_zero_p(f, u):
        return (1, ) * (u + 1), f

    F = dmp_to_dict(f, u)
    B = [0] * (u + 1)

    for M in F.iterkeys():
        for i, m in enumerate(M):
            B[i] = igcd(B[i], m)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([b == 1 for b in B]):
        return B, f

    H = {}

    for A, coeff in F.iteritems():
        N = [a // b for a, b in zip(A, B)]
        H[tuple(N)] = coeff

    return B, dmp_from_dict(H, u, K)
예제 #4
0
def dmp_ext_factor(f, u, K):
    """Factor multivariate polynomials over algebraic number fields. """
    if not u:
        return dup_ext_factor(f, K)

    lc = dmp_ground_LC(f, u, K)
    f = dmp_ground_monic(f, u, K)

    if all([d <= 0 for d in dmp_degree_list(f, u)]):
        return lc, []

    f, F = dmp_sqf_part(f, u, K), f
    s, g, r = dmp_sqf_norm(f, u, K)

    factors = dmp_factor_list_include(r, u, K.dom)

    if len(factors) == 1:
        coeff, factors = lc, [f]
    else:
        H = dmp_raise([K.one, s * K.unit], u, 0, K)

        for i, (factor, _) in enumerate(factors):
            h = dmp_convert(factor, u, K.dom, K)
            h, _, g = dmp_inner_gcd(h, g, u, K)
            h = dmp_compose(h, H, u, K)
            factors[i] = h

    return lc, dmp_trial_division(F, factors, u, K)
예제 #5
0
def dmp_terms_gcd(f, u, K):
    """
    Remove GCD of terms from ``f`` in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_terms_gcd

    >>> f = ZZ.map([[1, 0], [1, 0, 0], [], []])

    >>> dmp_terms_gcd(f, 1, ZZ)
    ((2, 1), [[1], [1, 0]])

    """
    if dmp_ground_TC(f, u, K) or dmp_zero_p(f, u):
        return (0,)*(u+1), f

    F = dmp_to_dict(f, u)
    G = monomial_min(*F.keys())

    if all([ g == 0 for g in G ]):
        return G, f

    f = {}

    for monom, coeff in F.iteritems():
        f[monomial_div(monom, G)] = coeff

    return G, dmp_from_dict(f, u, K)
예제 #6
0
def test_roots_quartic():
    assert roots_quartic(Poly(x**4, x)) == [0, 0, 0, 0]
    assert roots_quartic(Poly(x**4 + x**3, x)) in [
        [-1,0,0,0],
        [0,-1,0,0],
        [0,0,-1,0],
        [0,0,0,-1]
    ]
    assert roots_quartic(Poly(x**4 - x**3, x)) in [
        [1,0,0,0],
        [0,1,0,0],
        [0,0,1,0],
        [0,0,0,1]
    ]

    lhs = roots_quartic(Poly(x**4 + x, x))
    rhs = [S.Half + I*sqrt(3)/2, S.Half - I*sqrt(3)/2, S.Zero, -S.One]

    assert sorted(lhs, key=hash) == sorted(rhs, key=hash)

    # test of all branches of roots quartic
    for i, (a, b, c, d) in enumerate([(1, 2, 3, 0),
                                      (3, -7, -9, 9),
                                      (1, 2, 3, 4),
                                      (1, 2, 3, 4),
                                      (-7, -3, 3, -6),
                                      (-3, 5, -6, -4)]):
        if i == 2:
            c = -a*(a**2/S(8) - b/S(2))
        elif i == 3:
            d = a*(a*(3*a**2/S(256) - b/S(16)) + c/S(4))
        eq = x**4 + a*x**3 + b*x**2 + c*x + d
        ans = roots_quartic(Poly(eq, x))
        assert all([eq.subs(x, ai).n(chop=True) == 0 for ai in ans])
예제 #7
0
    def __new__(cls, function, *symbols, **assumptions):

        # Any embedded piecewise functions need to be brought out to the
        # top level so that integration can go into piecewise mode at the
        # earliest possible moment.
        function = piecewise_fold(sympify(function))

        if function is S.NaN:
            return S.NaN

        if symbols:
            limits, sign = _process_limits(*symbols)
        else:
            # no symbols provided -- let's compute full anti-derivative
            limits, sign = [Tuple(s) for s in function.free_symbols], 1
            if not limits:
                raise ValueError('An integration variable is required.')


        while isinstance(function, Integral):
            # denest the integrand
            limits = list(function.limits) + limits
            function = function.function


        obj = Expr.__new__(cls, **assumptions)
        arglist = [sign*function]
        arglist.extend(limits)
        obj._args = tuple(arglist)
        obj.is_commutative = all(s.is_commutative for s in obj.free_symbols)

        return obj
예제 #8
0
파일: polyroots.py 프로젝트: pernici/sympy
def roots_binomial(f):
    """Returns a list of roots of a binomial polynomial."""
    n = f.degree()

    a, b = f.nth(n), f.nth(0)
    alpha = (-cancel(b / a))**Rational(1, n)

    if alpha.is_number:
        alpha = alpha.expand(complex=True)

    roots, I = [], S.ImaginaryUnit

    for k in xrange(n):
        zeta = exp(2 * k * S.Pi * I / n).expand(complex=True)
        roots.append((alpha * zeta).expand(power_base=False))

    if all([r.is_number for r in roots]):
        reals, complexes = [], []

        for root in roots:
            if root.is_real:
                reals.append(root)
            else:
                complexes.append(root)

        roots = sorted(reals) + sorted(complexes,
                                       key=lambda r: (re(r), -im(r)))

    return roots
예제 #9
0
def dmp_deflate(f, u, K):
    """Map `x_i**m_i` to `y_i` in a polynomial in `K[X]`. """
    if dmp_zero_p(f, u):
        return (1,)*(u+1), f

    F = dmp_to_dict(f, u)
    B = [0]*(u+1)

    for M in F.iterkeys():
        for i, m in enumerate(M):
            B[i] = igcd(B[i], m)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([ b == 1 for b in B ]):
        return B, f

    H = {}

    for A, coeff in F.iteritems():
        N = [ a // b for a, b in zip(A, B) ]
        H[tuple(N)] = coeff

    return B, dmp_from_dict(H, u, K)
예제 #10
0
파일: integrals.py 프로젝트: Jerryy/sympy
    def __new__(cls, function, *symbols, **assumptions):

        # Any embedded piecewise functions need to be brought out to the
        # top level so that integration can go into piecewise mode at the
        # earliest possible moment.
        function = piecewise_fold(sympify(function))

        if function is S.NaN:
            return S.NaN

        if symbols:
            limits, sign = _process_limits(*symbols)
        else:
            # no symbols provided -- let's compute full anti-derivative
            limits, sign = [Tuple(s) for s in function.free_symbols], 1

            if len(limits) != 1:
                raise ValueError("specify integration variables to integrate %s" % function)

        while isinstance(function, Integral):
            # denest the integrand
            limits = list(function.limits) + limits
            function = function.function

        obj = Expr.__new__(cls, **assumptions)
        arglist = [sign*function]
        arglist.extend(limits)
        obj._args = tuple(arglist)
        obj.is_commutative = all(s.is_commutative for s in obj.free_symbols)

        return obj
예제 #11
0
파일: factortools.py 프로젝트: haz/sympy
def dmp_ext_factor(f, u, K):
    """Factor multivariate polynomials over algebraic number fields. """
    if not u:
        return dup_ext_factor(f, K)

    lc = dmp_ground_LC(f, u, K)
    f = dmp_ground_monic(f, u, K)

    if all([ d <= 0 for d in dmp_degree_list(f, u) ]):
        return lc, []

    f, F = dmp_sqf_part(f, u, K), f
    s, g, r = dmp_sqf_norm(f, u, K)

    factors = dmp_factor_list_include(r, u, K.dom)

    if len(factors) == 1:
        coeff, factors = lc, [f]
    else:
        H = dmp_raise([K.one, s*K.unit], u, 0, K)

        for i, (factor, _) in enumerate(factors):
            h = dmp_convert(factor, u, K.dom, K)
            h, _, g = dmp_inner_gcd(h, g, u, K)
            h = dmp_compose(h, H, u, K)
            factors[i] = h

    return lc, dmp_trial_division(F, factors, u, K)
예제 #12
0
def monomial_div(A, B):
    """
    Division of tuples representing monomials.

    Lets divide `x**3*y**4*z` by `x*y**2`::

        >>> from sympy.polys.monomialtools import monomial_div

        >>> monomial_div((3, 4, 1), (1, 2, 0))
        (2, 2, 1)

    which gives `x**2*y**2*z`. However::

        >>> monomial_div((3, 4, 1), (1, 2, 2)) is None
        True

    `x*y**2*z**2` does not divide `x**3*y**4*z`.

    """
    C = [ a - b for a, b in zip(A, B) ]

    if all([ c >= 0 for c in C ]):
        return tuple(C)
    else:
        return None
예제 #13
0
def monomial_div(A, B):
    """
    Division of tuples representing monomials.

    Lets divide `x**3*y**4*z` by `x*y**2`::

        >>> from sympy.polys.monomialtools import monomial_div

        >>> monomial_div((3, 4, 1), (1, 2, 0))
        (2, 2, 1)

    which gives `x**2*y**2*z`. However::

        >>> monomial_div((3, 4, 1), (1, 2, 2)) is None
        True

    `x*y**2*z**2` does not divide `x**3*y**4*z`.

    """
    C = [a - b for a, b in zip(A, B)]

    if all([c >= 0 for c in C]):
        return tuple(C)
    else:
        return None
예제 #14
0
def _separatevars_dict(expr, *symbols):
    if symbols:
        assert all((t.is_Atom for t in symbols)), "symbols must be Atoms."
    ret = dict(((i,sympify(1)) for i in symbols))
    ret['coeff'] = sympify(1)
    if expr.is_Mul:
        for i in expr.args:
            expsym = i.atoms(Symbol)
            if len(set(symbols).intersection(expsym)) > 1:
                return None
            if len(set(symbols).intersection(expsym)) == 0:
                # There are no symbols, so it is part of the coefficient
                ret['coeff'] *= i
            else:
                ret[expsym.pop()] *= i
    else:
        expsym = expr.atoms(Symbol)
        if len(set(symbols).intersection(expsym)) > 1:
            return None
        if len(set(symbols).intersection(expsym)) == 0:
            # There are no symbols, so it is part of the coefficient
            ret['coeff'] *= expr
        else:
            ret[expsym.pop()] *= expr

    return ret
예제 #15
0
def roots_binomial(f):
    """Returns a list of roots of a binomial polynomial."""
    n = f.degree()

    a, b = f.nth(n), f.nth(0)
    alpha = (-cancel(b/a))**Rational(1, n)

    if alpha.is_number:
        alpha = alpha.expand(complex=True)

    roots, I = [], S.ImaginaryUnit

    for k in xrange(n):
        zeta = exp(2*k*S.Pi*I/n).expand(complex=True)
        roots.append((alpha*zeta).expand(power_base=False))

    if all([ r.is_number for r in roots ]):
        reals, complexes = [], []

        for root in roots:
            if root.is_real:
                reals.append(root)
            else:
                complexes.append(root)

        roots = sorted(reals) + sorted(complexes, key=lambda r: (re(r), -im(r)))

    return roots
예제 #16
0
def dmp_terms_gcd(f, u, K):
    """
    Remove GCD of terms from ``f`` in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_terms_gcd

    >>> f = ZZ.map([[1, 0], [1, 0, 0], [], []])

    >>> dmp_terms_gcd(f, 1, ZZ)
    ((2, 1), [[1], [1, 0]])

    """
    if dmp_ground_TC(f, u, K) or dmp_zero_p(f, u):
        return (0, ) * (u + 1), f

    F = dmp_to_dict(f, u)
    G = monomial_min(*F.keys())

    if all([g == 0 for g in G]):
        return G, f

    f = {}

    for monom, coeff in F.iteritems():
        f[monomial_div(monom, G)] = coeff

    return G, dmp_from_dict(f, u, K)
예제 #17
0
파일: test_simplify.py 프로젝트: haz/sympy
def test_simplify():
    x, y, z, k, n, m, w, f, s, A = symbols('x,y,z,k,n,m,w,f,s,A')

    assert all(simplify(tmp) == tmp for tmp in [I, E, oo, x, -x, -oo, -E, -I])

    e = 1/x + 1/y
    assert e != (x+y)/(x*y)
    assert simplify(e) == (x+y)/(x*y)

    e = A**2*s**4/(4*pi*k*m**3)
    assert simplify(e) == e

    e = (4+4*x-2*(2+2*x))/(2+2*x)
    assert simplify(e) == 0

    e = (-4*x*y**2-2*y**3-2*x**2*y)/(x+y)**2
    assert simplify(e) == -2*y

    e = -x-y-(x+y)**(-1)*y**2+(x+y)**(-1)*x**2
    assert simplify(e) == -2*y

    e = (x+x*y)/x
    assert simplify(e) == 1 + y

    e = (f(x)+y*f(x))/f(x)
    assert simplify(e) == 1 + y

    e = (2 * (1/n - cos(n * pi)/n))/pi
    assert simplify(e) == 2*((1 - 1*cos(pi*n))/(pi*n))

    e = integrate(1/(x**3+1), x).diff(x)
    assert simplify(e) == 1/(x**3+1)

    e = integrate(x/(x**2+3*x+1), x).diff(x)
    assert simplify(e) == x/(x**2+3*x+1)

    A = Matrix([[2*k-m*w**2, -k], [-k, k-m*w**2]]).inv()

    assert simplify((A*Matrix([0,f]))[1]) == \
        (f*(2*k - m*w**2))/(k**2 - 3*k*m*w**2 + m**2*w**4)

    a, b, c, d, e, f, g, h, i = symbols('a,b,c,d,e,f,g,h,i')

    f_1 = x*a + y*b + z*c - 1
    f_2 = x*d + y*e + z*f - 1
    f_3 = x*g + y*h + z*i - 1

    solutions = solve([f_1, f_2, f_3], x, y, z, simplified=False)

    assert simplify(solutions[y]) == \
        (a*i+c*d+f*g-a*f-c*g-d*i)/(a*e*i+b*f*g+c*d*h-a*f*h-b*d*i-c*e*g)

    f = -x + y/(z + t) + z*x/(z + t) + z*a/(z + t) + t*x/(z + t)

    assert simplify(f) == (y + a*z)/(z + t)

    A, B = symbols('A,B', commutative=False)

    assert simplify(A*B - B*A) == A*B - B*A
예제 #18
0
def test_simplify():
    x, y, z, k, n, m, w, f, s, A = symbols('x,y,z,k,n,m,w,f,s,A')

    assert all(simplify(tmp) == tmp for tmp in [I, E, oo, x, -x, -oo, -E, -I])

    e = 1 / x + 1 / y
    assert e != (x + y) / (x * y)
    assert simplify(e) == (x + y) / (x * y)

    e = A**2 * s**4 / (4 * pi * k * m**3)
    assert simplify(e) == e

    e = (4 + 4 * x - 2 * (2 + 2 * x)) / (2 + 2 * x)
    assert simplify(e) == 0

    e = (-4 * x * y**2 - 2 * y**3 - 2 * x**2 * y) / (x + y)**2
    assert simplify(e) == -2 * y

    e = -x - y - (x + y)**(-1) * y**2 + (x + y)**(-1) * x**2
    assert simplify(e) == -2 * y

    e = (x + x * y) / x
    assert simplify(e) == 1 + y

    e = (f(x) + y * f(x)) / f(x)
    assert simplify(e) == 1 + y

    e = (2 * (1 / n - cos(n * pi) / n)) / pi
    assert simplify(e) == 2 * ((1 - 1 * cos(pi * n)) / (pi * n))

    e = integrate(1 / (x**3 + 1), x).diff(x)
    assert simplify(e) == 1 / (x**3 + 1)

    e = integrate(x / (x**2 + 3 * x + 1), x).diff(x)
    assert simplify(e) == x / (x**2 + 3 * x + 1)

    A = Matrix([[2 * k - m * w**2, -k], [-k, k - m * w**2]]).inv()

    assert simplify((A*Matrix([0,f]))[1]) == \
        (f*(2*k - m*w**2))/(k**2 - 3*k*m*w**2 + m**2*w**4)

    a, b, c, d, e, f, g, h, i = symbols('a,b,c,d,e,f,g,h,i')

    f_1 = x * a + y * b + z * c - 1
    f_2 = x * d + y * e + z * f - 1
    f_3 = x * g + y * h + z * i - 1

    solutions = solve([f_1, f_2, f_3], x, y, z, simplified=False)

    assert simplify(solutions[y]) == \
        (a*i+c*d+f*g-a*f-c*g-d*i)/(a*e*i+b*f*g+c*d*h-a*f*h-b*d*i-c*e*g)

    f = -x + y / (z + t) + z * x / (z + t) + z * a / (z + t) + t * x / (z + t)

    assert simplify(f) == (y + a * z) / (z + t)

    A, B = symbols('A,B', commutative=False)

    assert simplify(A * B - B * A) == A * B - B * A
예제 #19
0
def dmp_inflate(f, M, u, K):
    """Map `y_i` to `x_i**k_i` in a polynomial in `K[X]`. """
    if not u:
        return dup_inflate(f, M[0], K)

    if all([m == 1 for m in M]):
        return f
    else:
        return _rec_inflate(f, M, u, 0, K)
예제 #20
0
def denester(nested):
    """
    Denests a list of expressions that contain nested square roots.
    This method should not be called directly - use 'denest' instead.
    This algorithm is based on <http://www.almaden.ibm.com/cs/people/fagin/symb85.pdf>.

    It is assumed that all of the elements of 'nested' share the same
    bottom-level radicand. (This is stated in the paper, on page 177, in
    the paragraph immediately preceding the algorithm.)

    When evaluating all of the arguments in parallel, the bottom-level
    radicand only needs to be denested once. This means that calling
    denester with x arguments results in a recursive invocation with x+1
    arguments; hence denester has polynomial complexity.

    However, if the arguments were evaluated separately, each call would
    result in two recursive invocations, and the algorithm would have
    exponential complexity.

    This is discussed in the paper in the middle paragraph of page 179.
    """
    if all((n ** 2).is_Number for n in nested):  # If none of the arguments are nested
        for f in subsets(len(nested)):  # Test subset 'f' of nested
            p = prod(nested[i] ** 2 for i in range(len(f)) if f[i]).expand()
            if 1 in f and f.count(1) > 1 and f[-1]:
                p = -p
            if sqrt(p).is_Number:
                return sqrt(p), f  # If we got a perfect square, return its square root.
        return nested[-1], [0] * len(nested)  # Otherwise, return the radicand from the previous invocation.
    else:
        a, b, r, R = Wild("a"), Wild("b"), Wild("r"), None
        values = [expr.match(sqrt(a + b * sqrt(r))) for expr in nested]
        for v in values:
            if r in v:  # Since if b=0, r is not defined
                if R is not None:
                    assert R == v[r]  # All the 'r's should be the same.
                else:
                    R = v[r]
        d, f = denester([sqrt((v[a] ** 2).expand() - (R * v[b] ** 2).expand()) for v in values] + [sqrt(R)])
        if not any([f[i] for i in range(len(nested))]):  # If f[i]=0 for all i < len(nested)
            v = values[-1]
            return sqrt(v[a] + v[b] * d), f
        else:
            v = prod(nested[i] ** 2 for i in range(len(nested)) if f[i]).expand().match(a + b * sqrt(r))
            if 1 in f and f.index(1) < len(nested) - 1 and f[len(nested) - 1]:
                v[a] = -1 * v[a]
                v[b] = -1 * v[b]
            if not f[len(nested)]:  # Solution denests with square roots
                return (
                    (
                        sqrt((v[a] + d).expand() / 2) + sign(v[b]) * sqrt((v[b] ** 2 * R / (2 * (v[a] + d))).expand())
                    ).expand(),
                    f,
                )
            else:  # Solution requires a fourth root
                FR, s = (R.expand() ** Rational(1, 4)), sqrt((v[b] * R).expand() + d)
                return (s / (sqrt(2) * FR) + v[a] * FR / (sqrt(2) * s)).expand(), f
예제 #21
0
def dmp_inflate(f, M, u, K):
    """Map `y_i` to `x_i**k_i` in a polynomial in `K[X]`. """
    if not u:
        return dup_inflate(f, M[0], K)

    if all([ m == 1 for m in M ]):
        return f
    else:
        return _rec_inflate(f, M, u, 0, K)
예제 #22
0
파일: integrals.py 프로젝트: pyc111/sympy
    def __new__(cls, function, *symbols, **assumptions):
        # Any embedded piecewise functions need to be brought out to the
        # top level so that integration can go into piecewise mode at the
        # earliest possible moment.
        function = piecewise_fold(sympify(function))

        if function is S.NaN:
            return S.NaN

        symbols = list(symbols)
        if not symbols:
            # no symbols provided -- let's compute full anti-derivative
            symbols = sorted(function.free_symbols, Basic.compare)
            if not symbols:
                raise ValueError('An integration variable is required.')

        while isinstance(function, Integral):
            # denest the integrand
            symbols = list(function.limits) + symbols
            function = function.function

        limits = []
        for V in symbols:
            if isinstance(V, Symbol):
                limits.append(Tuple(V))
                continue
            elif isinstance(V, (tuple, list, Tuple)):
                V = sympify(flatten(V))
                if V[0].is_Symbol:
                    newsymbol = V[0]
                    if len(V) == 3:
                        if V[1] is None and V[2] is not None:
                            nlim = [V[2]]
                        elif V[1] is not None and V[2] is None:
                            function = -function
                            nlim = [V[1]]
                        elif V[1] is None and V[2] is None:
                            nlim = []
                        else:
                            nlim = V[1:]
                        limits.append(Tuple(newsymbol, *nlim ))
                        continue
                    elif len(V) == 1 or (len(V) == 2 and V[1] is None):
                        limits.append(Tuple(newsymbol))
                        continue
                    elif len(V) == 2:
                        limits.append(Tuple(newsymbol, V[1]))
                        continue
            raise ValueError("Invalid integration variable or limits: %s" % str(symbols))

        obj = Expr.__new__(cls, **assumptions)
        obj._args = tuple([function] + limits)
        obj.is_commutative = all(s.is_commutative for s in obj.free_symbols)

        return obj
예제 #23
0
def test_dup_random():
    f = dup_random(0, -10, 10, ZZ)

    assert dup_degree(f) == 0
    assert all([-10 <= c <= 10 for c in f])

    f = dup_random(1, -20, 20, ZZ)

    assert dup_degree(f) == 1
    assert all([-20 <= c <= 20 for c in f])

    f = dup_random(2, -30, 30, ZZ)

    assert dup_degree(f) == 2
    assert all([-30 <= c <= 30 for c in f])

    f = dup_random(3, -40, 40, ZZ)

    assert dup_degree(f) == 3
    assert all([-40 <= c <= 40 for c in f])
예제 #24
0
def test_dup_random():
    f = dup_random(0, -10, 10, ZZ)

    assert dup_degree(f) == 0
    assert all([ -10 <= c <= 10 for c in f ])

    f = dup_random(1, -20, 20, ZZ)

    assert dup_degree(f) == 1
    assert all([ -20 <= c <= 20 for c in f ])

    f = dup_random(2, -30, 30, ZZ)

    assert dup_degree(f) == 2
    assert all([ -30 <= c <= 30 for c in f ])

    f = dup_random(3, -40, 40, ZZ)

    assert dup_degree(f) == 3
    assert all([ -40 <= c <= 40 for c in f ])
예제 #25
0
def dmp_multi_deflate(polys, u, K):
    """
    Map ``x_i**m_i`` to ``y_i`` in a set of polynomials in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_multi_deflate

    >>> f = ZZ.map([[1, 0, 0, 2], [], [3, 0, 0, 4]])
    >>> g = ZZ.map([[1, 0, 2], [], [3, 0, 4]])

    >>> dmp_multi_deflate((f, g), 1, ZZ)
    ((2, 1), ([[1, 0, 0, 2], [3, 0, 0, 4]], [[1, 0, 2], [3, 0, 4]]))

    """
    if not u:
        M, H = dup_multi_deflate(polys, K)
        return (M, ), H

    F, B = [], [0] * (u + 1)

    for p in polys:
        f = dmp_to_dict(p, u)

        if not dmp_zero_p(p, u):
            for M in f.iterkeys():
                for i, m in enumerate(M):
                    B[i] = igcd(B[i], m)

        F.append(f)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([b == 1 for b in B]):
        return B, polys

    H = []

    for f in F:
        h = {}

        for A, coeff in f.iteritems():
            N = [a // b for a, b in zip(A, B)]
            h[tuple(N)] = coeff

        H.append(dmp_from_dict(h, u, K))

    return B, tuple(H)
예제 #26
0
def dmp_multi_deflate(polys, u, K):
    """
    Map ``x_i**m_i`` to ``y_i`` in a set of polynomials in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_multi_deflate

    >>> f = ZZ.map([[1, 0, 0, 2], [], [3, 0, 0, 4]])
    >>> g = ZZ.map([[1, 0, 2], [], [3, 0, 4]])

    >>> dmp_multi_deflate((f, g), 1, ZZ)
    ((2, 1), ([[1, 0, 0, 2], [3, 0, 0, 4]], [[1, 0, 2], [3, 0, 4]]))

    """
    if not u:
        M, H = dup_multi_deflate(polys, K)
        return (M,), H

    F, B = [], [0]*(u+1)

    for p in polys:
        f = dmp_to_dict(p, u)

        if not dmp_zero_p(p, u):
            for M in f.iterkeys():
                for i, m in enumerate(M):
                    B[i] = igcd(B[i], m)

        F.append(f)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([ b == 1 for b in B ]):
        return B, polys

    H = []

    for f in F:
        h = {}

        for A, coeff in f.iteritems():
            N = [ a // b for a, b in zip(A, B) ]
            h[tuple(N)] = coeff

        H.append(dmp_from_dict(h, u, K))

    return B, tuple(H)
예제 #27
0
def dmp_terms_gcd(f, u, K):
    """Remove GCD of terms from `f` in `K[X]`. """
    if dmp_ground_TC(f, u, K) or dmp_zero_p(f, u):
        return (0,)*(u+1), f

    F = dmp_to_dict(f, u)
    G = monomial_min(*F.keys())

    if all([ g == 0 for g in G ]):
        return G, f

    f = {}

    for monom, coeff in F.iteritems():
        f[monomial_div(monom, G)] = coeff

    return G, dmp_from_dict(f, u, K)
예제 #28
0
def dmp_terms_gcd(f, u, K):
    """Remove GCD of terms from `f` in `K[X]`. """
    if dmp_ground_TC(f, u, K) or dmp_zero_p(f, u):
        return (0, ) * (u + 1), f

    F = dmp_to_dict(f, u)
    G = monomial_min(*F.keys())

    if all([g == 0 for g in G]):
        return G, f

    f = {}

    for monom, coeff in F.iteritems():
        f[monomial_div(monom, G)] = coeff

    return G, dmp_from_dict(f, u, K)
예제 #29
0
def _get_indices_Add(expr):
    """Determine outer indices of an Add object.

    In a sum, each term must have the same set of outer indices.  A valid
    expression could be

        x(i)*y(j) - x(j)*y(i)

    But we do not allow expressions like:

        x(i)*y(j) - z(j)*z(j)

    FIXME: Add support for Numpy broadcasting

    >>> from sympy.tensor.index_methods import _get_indices_Add
    >>> from sympy.tensor.indexed import IndexedBase, Idx
    >>> i, j, k = map(Idx, ['i', 'j', 'k'])
    >>> x = IndexedBase('x')
    >>> y = IndexedBase('y')
    >>> _get_indices_Add(x[i] + x[k]*y[i, k])
    (set([i]), {})

    """

    inds = map(get_indices, expr.args)
    inds, syms = zip(*inds)

    # allow broadcast of scalars
    non_scalars = filter(lambda x: x != set(), inds)
    if not non_scalars:
        return set(), {}

    if not all(map(lambda x: x == non_scalars[0], non_scalars[1:])):
        raise IndexConformanceException("Indices are not consistent: %s" %
                                        expr)
    if not reduce(lambda x, y: x != y or y, syms):
        symmetries = syms[0]
    else:
        # FIXME: search for symmetries
        symmetries = {}

    return non_scalars[0], symmetries
예제 #30
0
def dmp_deflate(f, u, K):
    """
    Map ``x_i**m_i`` to ``y_i`` in a polynomial in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_deflate

    >>> f = ZZ.map([[1, 0, 0, 2], [], [3, 0, 0, 4]])

    >>> dmp_deflate(f, 1, ZZ)
    ((2, 3), [[1, 2], [3, 4]])

    """
    if dmp_zero_p(f, u):
        return (1, ) * (u + 1), f

    F = dmp_to_dict(f, u)
    B = [0] * (u + 1)

    for M in F.iterkeys():
        for i, m in enumerate(M):
            B[i] = igcd(B[i], m)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([b == 1 for b in B]):
        return B, f

    H = {}

    for A, coeff in F.iteritems():
        N = [a // b for a, b in zip(A, B)]
        H[tuple(N)] = coeff

    return B, dmp_from_dict(H, u, K)
예제 #31
0
파일: index_methods.py 프로젝트: fxkr/sympy
def _get_indices_Add(expr):
    """Determine outer indices of an Add object.

    In a sum, each term must have the same set of outer indices.  A valid
    expression could be

        x(i)*y(j) - x(j)*y(i)

    But we do not allow expressions like:

        x(i)*y(j) - z(j)*z(j)

    FIXME: Add support for Numpy broadcasting

    >>> from sympy.tensor.index_methods import _get_indices_Add
    >>> from sympy.tensor.indexed import IndexedBase, Idx
    >>> i, j, k = map(Idx, ['i', 'j', 'k'])
    >>> x = IndexedBase('x')
    >>> y = IndexedBase('y')
    >>> _get_indices_Add(x[i] + x[k]*y[i, k])
    (set([i]), {})

    """

    inds = map(get_indices, expr.args)
    inds, syms = zip(*inds)

    # allow broadcast of scalars
    non_scalars = filter(lambda x: x != set(), inds)
    if not non_scalars:
        return set(), {}

    if not all(map(lambda x: x == non_scalars[0], non_scalars[1:])):
        raise IndexConformanceException("Indices are not consistent: %s"%expr)
    if not reduce(lambda x, y: x!=y or y, syms):
        symmetries = syms[0]
    else:
        # FIXME: search for symmetries
        symmetries = {}

    return non_scalars[0], symmetries
예제 #32
0
def dmp_deflate(f, u, K):
    """
    Map ``x_i**m_i`` to ``y_i`` in a polynomial in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_deflate

    >>> f = ZZ.map([[1, 0, 0, 2], [], [3, 0, 0, 4]])

    >>> dmp_deflate(f, 1, ZZ)
    ((2, 3), [[1, 2], [3, 4]])

    """
    if dmp_zero_p(f, u):
        return (1,)*(u+1), f

    F = dmp_to_dict(f, u)
    B = [0]*(u+1)

    for M in F.iterkeys():
        for i, m in enumerate(M):
            B[i] = igcd(B[i], m)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([ b == 1 for b in B ]):
        return B, f

    H = {}

    for A, coeff in F.iteritems():
        N = [ a // b for a, b in zip(A, B) ]
        H[tuple(N)] = coeff

    return B, dmp_from_dict(H, u, K)
예제 #33
0
def dmp_inflate(f, M, u, K):
    """
    Map ``y_i`` to ``x_i**k_i`` in a polynomial in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_inflate

    >>> f = ZZ.map([[1, 2], [3, 4]])

    >>> dmp_inflate(f, (2, 3), 1, ZZ)
    [[1, 0, 0, 2], [], [3, 0, 0, 4]]

    """
    if not u:
        return dup_inflate(f, M[0], K)

    if all([m == 1 for m in M]):
        return f
    else:
        return _rec_inflate(f, M, u, 0, K)
예제 #34
0
def dmp_multi_deflate(polys, u, K):
    """Map `x_i**m_i` to `y_i` in a set of polynomials in `K[X]`. """
    if not u:
        M, H = dup_multi_deflate(polys, K)
        return (M, ), H

    F, B = [], [0] * (u + 1)

    for p in polys:
        f = dmp_to_dict(p, u)

        if not dmp_zero_p(p, u):
            for M in f.iterkeys():
                for i, m in enumerate(M):
                    B[i] = igcd(B[i], m)

        F.append(f)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([b == 1 for b in B]):
        return B, polys

    H = []

    for f in F:
        h = {}

        for A, coeff in f.iteritems():
            N = [a // b for a, b in zip(A, B)]
            h[tuple(N)] = coeff

        H.append(dmp_from_dict(h, u, K))

    return B, tuple(H)
예제 #35
0
def dmp_multi_deflate(polys, u, K):
    """Map `x_i**m_i` to `y_i` in a set of polynomials in `K[X]`. """
    if not u:
        M, H = dup_multi_deflate(polys, K)
        return (M,), H

    F, B = [], [0]*(u+1)

    for p in polys:
        f = dmp_to_dict(p, u)

        if not dmp_zero_p(p, u):
            for M in f.iterkeys():
                for i, m in enumerate(M):
                    B[i] = igcd(B[i], m)

        F.append(f)

    for i, b in enumerate(B):
        if not b:
            B[i] = 1

    B = tuple(B)

    if all([ b == 1 for b in B ]):
        return B, polys

    H = []

    for f in F:
        h = {}

        for A, coeff in f.iteritems():
            N = [ a // b for a, b in zip(A, B) ]
            h[tuple(N)] = coeff

        H.append(dmp_from_dict(h, u, K))

    return B, tuple(H)
예제 #36
0
def dmp_inflate(f, M, u, K):
    """
    Map ``y_i`` to ``x_i**k_i`` in a polynomial in ``K[X]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densebasic import dmp_inflate

    >>> f = ZZ.map([[1, 2], [3, 4]])

    >>> dmp_inflate(f, (2, 3), 1, ZZ)
    [[1, 0, 0, 2], [], [3, 0, 0, 4]]

    """
    if not u:
        return dup_inflate(f, M[0], K)

    if all([ m == 1 for m in M ]):
        return f
    else:
        return _rec_inflate(f, M, u, 0, K)
예제 #37
0
def monomial_div(a, b):
    """Division of tuples representing monomials.

       Lets divide x**3*y**4*z by x*y**2:

       >>> monomial_div((3, 4, 1), (1, 2, 0))
       (2, 2, 1)

       which gives x**2*y**2*z. However

       >>> monomial_div((3, 4, 1), (1, 2, 2))
       None

       x*y**2*z**2 does not divide x**3*y**4*z.

    """
    result = [x - y for x, y in zip(a, b)]

    if all(e >= 0 for e in result):
        return tuple(result)
    else:
        return None
예제 #38
0
def monomial_div(a, b):
    """Division of tuples representing monomials.

       Lets divide x**3*y**4*z by x*y**2:

       >>> monomial_div((3, 4, 1), (1, 2, 0))
       (2, 2, 1)

       which gives x**2*y**2*z. However

       >>> monomial_div((3, 4, 1), (1, 2, 2))
       None

       x*y**2*z**2 does not divide x**3*y**4*z.

    """
    result = [x - y for x, y in zip(a, b)]

    if all(e >= 0 for e in result):
        return tuple(result)
    else:
        return None
예제 #39
0
def monomial_div(a, b):
    """Division of tuples representing monomials.

       Lets divide x**3*y**4*z by x*y**2:

       >>> from sympy.polys.monomial import monomial_div
       >>> monomial_div((3, 4, 1), (1, 2, 0))
       (2, 2, 1)

       which gives x**2*y**2*z. However, nothing is obtained for the
       following,

       >>> monomial_div((3, 4, 1), (1, 2, 2))
       <BLANKLINE>

       since x*y**2*z**2 does not divide x**3*y**4*z.
    """
    result = [ x - y for x, y in zip(a, b) ]

    if all(e >= 0 for e in result):
        return tuple(result)
    else:
        return None
예제 #40
0
파일: polyroots.py 프로젝트: fxkr/sympy
def preprocess_roots(poly):
    """Try to get rid of symbolic coefficients from ``poly``. """
    coeff = S.One

    try:
        _, poly = poly.clear_denoms(convert=True)
    except DomainError:
        return coeff, poly

    poly = poly.primitive()[1]
    poly = poly.retract()

    if poly.get_domain().is_Poly and all(c.is_monomial for c in poly.rep.coeffs()):
        poly = poly.inject()

        strips = zip(*poly.monoms())
        gens = list(poly.gens[1:])

        base, strips = strips[0], strips[1:]

        for gen, strip in zip(gens, strips):
            reverse = False

            if strip[0] < strip[-1]:
                strip = reversed(strip)
                reverse = True

            ratio = None

            for a, b in zip(base, strip):
                if not a and not b:
                    continue
                elif not a or not b:
                    break
                elif b % a != 0:
                    break
                else:
                    _ratio = b // a

                    if ratio is None:
                        ratio = _ratio
                    elif ratio != _ratio:
                        break
            else:
                if reverse:
                    ratio = -ratio

                poly = poly.eval(gen, 1)
                coeff *= gen**(-ratio)
                gens.remove(gen)

        if gens:
            poly = poly.eject(*gens)

    if poly.is_univariate and poly.get_domain().is_ZZ:
        basis = _integer_basis(poly)

        if basis is not None:
            n = poly.degree()

            def func((k,), coeff):
                return coeff//basis**(n-k)

            poly = poly.termwise(func)
            coeff *= basis
예제 #41
0
def solve(f, *symbols, **flags):
    """Solves equations and systems of equations.

       Currently supported are univariate polynomial and transcendental
       equations and systems of linear and polynomial equations.  Input
       is formed as a single expression or an equation,  or an iterable
       container in case of an equation system.  The type of output may
       vary and depends heavily on the input. For more details refer to
       more problem specific functions.

       By default all solutions are simplified to make the output more
       readable. If this is not the expected behavior,  eg. because of
       speed issues, set simplified=False in function arguments.

       To solve equations and systems of equations of other kind, eg.
       recurrence relations of differential equations use rsolve() or
       dsolve() functions respectively.

       >>> from sympy import *
       >>> x,y = symbols('xy')

       Solve a polynomial equation:

       >>> solve(x**4-1, x)
       [1, -1, -I, I]

       Solve a linear system:

       >>> solve((x+5*y-2, -3*x+6*y-15), x, y)
       {x: -3, y: 1}

    """
    if not symbols:
        raise ValueError('no symbols were given')

    if len(symbols) == 1:
        if isinstance(symbols[0], (list, tuple, set)):
            symbols = symbols[0]

    symbols = map(sympify, symbols)

    if any(not s.is_Symbol for s in symbols):
        raise TypeError('not a Symbol')

    if not isinstance(f, (tuple, list, set)):
        f = sympify(f)

        if isinstance(f, Equality):
            f = f.lhs - f.rhs

        if len(symbols) != 1:
            raise NotImplementedError('multivariate equation')

        symbol = symbols[0]

        strategy = guess_solve_strategy(f, symbol)

        if strategy == GS_POLY:
            poly = f.as_poly(symbol)
            assert poly is not None
            result = roots(poly, cubics=True, quartics=True).keys()

        elif strategy == GS_RATIONAL:
            P, Q = f.as_numer_denom()
            #TODO: check for Q != 0
            return solve(P, symbol, **flags)

        elif strategy == GS_POLY_CV_1:
            # we must search for a suitable change of variable
            # collect exponents
            exponents_denom = list()
            args = list(f.args)
            if isinstance(f, Add):
                for arg in args:
                    if isinstance(arg, Pow):
                        exponents_denom.append(arg.exp.q)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                exponents_denom.append(mul_arg.exp.q)
            elif isinstance(f, Mul):
                for mul_arg in args:
                    if isinstance(mul_arg, Pow):
                        exponents_denom.append(mul_arg.exp.q)

            assert len(exponents_denom) > 0
            if len(exponents_denom) == 1:
                m = exponents_denom[0]
            else:
                # get the GCD of the denominators
                m = ilcm(*exponents_denom)
            # x -> y**m.
            # we assume positive for simplification purposes
            t = Symbol('t', positive=True, dummy=True)
            f_ = f.subs(symbol, t**m)
            if guess_solve_strategy(f_, t) != GS_POLY:
                raise TypeError(
                    "Could not convert to a polynomial equation: %s" % f_)
            cv_sols = solve(f_, t)
            result = list()
            for sol in cv_sols:
                result.append(sol**(S.One / m))

        elif strategy == GS_POLY_CV_2:
            m = 0
            args = list(f.args)
            if isinstance(f, Add):
                for arg in args:
                    if isinstance(arg, Pow):
                        m = min(m, arg.exp)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                m = min(m, mul_arg.exp)
            elif isinstance(f, Mul):
                for mul_arg in args:
                    if isinstance(mul_arg, Pow):
                        m = min(m, mul_arg.exp)
            f1 = simplify(f * symbol**(-m))
            result = solve(f1, symbol)
            # TODO: we might have introduced unwanted solutions
            # when multiplied by x**-m

        elif strategy == GS_TRASCENDENTAL:
            #a, b = f.as_numer_denom()
            # Let's throw away the denominator for now. When we have robust
            # assumptions, it should be checked, that for the solution,
            # b!=0.
            result = tsolve(f, *symbols)
        elif strategy == -1:
            raise Exception('Could not parse expression %s' % f)
        else:
            raise NotImplementedError(
                "No algorithms where implemented to solve equation %s" % f)

        if flags.get('simplified', True):
            return map(simplify, result)
        else:
            return result
    else:
        if not f:
            return {}
        else:
            polys = []

            for g in f:
                g = sympify(g)

                if isinstance(g, Equality):
                    g = g.lhs - g.rhs

                poly = g.as_poly(*symbols)

                if poly is not None:
                    polys.append(poly)
                else:
                    raise NotImplementedError

            if all(p.is_linear for p in polys):
                n, m = len(f), len(symbols)
                matrix = zeros((n, m + 1))

                for i, poly in enumerate(polys):
                    for coeff, monom in poly.iter_terms():
                        try:
                            j = list(monom).index(1)
                            matrix[i, j] = coeff
                        except ValueError:
                            matrix[i, m] = -coeff

                return solve_linear_system(matrix, *symbols, **flags)
            else:
                return solve_poly_system(polys)
예제 #42
0
파일: solvers.py 프로젝트: Jerryy/sympy
def _solve(f, *symbols, **flags):
    """ Return a checked solution for f in terms of one or more of the symbols."""

    if not iterable(f):

        if len(symbols) != 1:
            soln = None
            free = f.free_symbols
            ex = free - set(symbols)
            if len(ex) == 1:
                ex = ex.pop()
                try:
                    # may come back as dict or list (if non-linear)
                    soln = solve_undetermined_coeffs(f, symbols, ex)
                except NotImplementedError:
                    pass
            if not soln is None:
                return soln
            # find first successful solution
            failed = []
            for s in symbols:
                n, d = solve_linear(f, x=[s])
                if n.is_Symbol:
                    soln = {n: cancel(d)}
                    return soln
                failed.append(s)
            for s in failed:
                try:
                    soln = _solve(f, s, **flags)
                    return soln
                except NotImplementedError:
                    pass
            else:
                msg = "No algorithms are implemented to solve equation %s"
                raise NotImplementedError(msg % f)

        symbol = symbols[0]

        # first see if it really depends on symbol and whether there
        # is a linear solution
        f_num, sol = solve_linear(f, x=symbols)
        if not symbol in f_num.free_symbols:
            return []
        elif f_num.is_Symbol:
            return [cancel(sol)]

        strategy = guess_solve_strategy(f, symbol)
        result = False  # no solution was obtained

        if strategy == GS_POLY:
            poly = f.as_poly(symbol)
            if poly is None:
                msg = "Cannot solve equation %s for %s" % (f, symbol)
            else:
                # for cubics and quartics, if the flag wasn't set, DON'T do it
                # by default since the results are quite long. Perhaps one could
                # base this decision on a certain critical length of the roots.
                if poly.degree() > 2:
                    flags['simplified'] = flags.get('simplified', False)
                result = roots(poly, cubics=True, quartics=True).keys()

        elif strategy == GS_RATIONAL:
            P, _ = f.as_numer_denom()
            dens = denoms(f, x=symbols)
            try:
                soln = _solve(P, symbol, **flags)
            except NotImplementedError:
                msg = "Cannot solve equation %s for %s" % (P, symbol)
                result = []
            else:
                if dens:
                    # reject any result that makes any denom. affirmatively 0;
                    # if in doubt, keep it
                    result = [
                        s for s in soln
                        if all(not checksol(den, {symbol: s}) for den in dens)
                    ]
                else:
                    result = soln

        elif strategy == GS_POLY_CV_1:
            args = list(f.args)
            if isinstance(f, Pow):
                result = _solve(args[0], symbol, **flags)
            elif isinstance(f, Add):
                # we must search for a suitable change of variables
                # collect exponents
                exponents_denom = list()
                for arg in args:
                    if isinstance(arg, Pow):
                        exponents_denom.append(arg.exp.q)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                exponents_denom.append(mul_arg.exp.q)
                assert len(exponents_denom) > 0
                if len(exponents_denom) == 1:
                    m = exponents_denom[0]
                else:
                    # get the LCM of the denominators
                    m = reduce(ilcm, exponents_denom)
                # x -> y**m.
                # we assume positive for simplification purposes
                t = Dummy('t', positive=True)
                f_ = f.subs(symbol, t**m)
                if guess_solve_strategy(f_, t) != GS_POLY:
                    msg = "Could not convert to a polynomial equation: %s" % f_
                    result = []
                else:
                    soln = [s**m for s in _solve(f_, t)]
                    # we might have introduced solutions from another branch
                    # when changing variables; check and keep solutions
                    # unless they definitely aren't a solution
                    result = [
                        s for s in soln
                        if checksol(f, {symbol: s}) is not False
                    ]

            elif isinstance(f, Mul):
                result = []
                for m in f.args:
                    result.extend(_solve(m, symbol, **flags) or [])

        elif strategy == GS_POLY_CV_2:
            m = 0
            args = list(f.args)
            if isinstance(f, Add):
                for arg in args:
                    if isinstance(arg, Pow):
                        m = min(m, arg.exp)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                m = min(m, mul_arg.exp)
            elif isinstance(f, Mul):
                for mul_arg in args:
                    if isinstance(mul_arg, Pow):
                        m = min(m, mul_arg.exp)

            if m and m != 1:
                f_ = simplify(f * symbol**(-m))
                try:
                    sols = _solve(f_, symbol)
                except NotImplementedError:
                    msg = 'Could not solve %s for %s' % (f_, symbol)
                else:
                    # we might have introduced unwanted solutions
                    # when multiplying by x**-m; check and keep solutions
                    # unless they definitely aren't a solution
                    if sols:
                        result = [
                            s for s in sols
                            if checksol(f, {symbol: s}) is not False
                        ]
            else:
                msg = 'CV_2 calculated %d but it should have been other than 0 or 1' % m

        elif strategy == GS_PIECEWISE:
            result = set()
            for expr, cond in f.args:
                candidates = _solve(expr, *symbols)
                if isinstance(cond, bool) or cond.is_Number:
                    if not cond:
                        continue

                    # Only include solutions that do not match the condition
                    # of any of the other pieces.
                    for candidate in candidates:
                        matches_other_piece = False
                        for other_expr, other_cond in f.args:
                            if isinstance(other_cond, bool) \
                               or other_cond.is_Number:
                                continue
                            if bool(other_cond.subs(symbol, candidate)):
                                matches_other_piece = True
                                break
                        if not matches_other_piece:
                            result.add(candidate)
                else:
                    for candidate in candidates:
                        if bool(cond.subs(symbol, candidate)):
                            result.add(candidate)

            result = list(result)

        elif strategy == -1:
            raise ValueError('Could not parse expression %s' % f)

        # this is the fallback for not getting any other solution
        if result is False or strategy == GS_TRANSCENDENTAL:
            soln = tsolve(f_num, symbol)
            dens = denoms(f, x=symbols)
            if not dens:
                result = soln
            else:
                # reject any result that makes any denom. affirmatively 0;
                # if in doubt, keep it
                result = [
                    s for s in soln
                    if all(not checksol(den, {symbol: s}) for den in dens)
                ]

        if result is False:
            raise NotImplementedError(
                msg +
                "\nNo algorithms are implemented to solve equation %s" % f)

        if flags.get('simplified', True) and strategy != GS_RATIONAL:
            result = map(simplify, result)

        return result
    else:
        if not f:
            return []
        else:

            polys = []

            for g in f:

                poly = g.as_poly(*symbols, **{'extension': True})

                if poly is not None:
                    polys.append(poly)
                else:
                    raise NotImplementedError()

            if all(p.is_linear for p in polys):
                n, m = len(f), len(symbols)
                matrix = zeros((n, m + 1))

                for i, poly in enumerate(polys):
                    for monom, coeff in poly.terms():
                        try:
                            j = list(monom).index(1)
                            matrix[i, j] = coeff
                        except ValueError:
                            matrix[i, m] = -coeff

                # a dictionary of symbols: values or None
                result = solve_linear_system(matrix, *symbols, **flags)
                return result
            else:
                # a list of tuples, T, where T[i] [j] corresponds to the ith solution for symbols[j]
                result = solve_poly_system(polys)
                return result
예제 #43
0
파일: polyclasses.py 프로젝트: fxkr/sympy
 def is_quadratic(f):
     """Returns `True` if `f` is quadratic in all its variables. """
     return all([ sum(monom) <= 2 for monom in dmp_to_dict(f.rep, f.lev, f.dom).keys() ])
예제 #44
0
파일: polyclasses.py 프로젝트: fxkr/sympy
 def is_linear(f):
     """Returns `True` if `f` is linear in all its variables. """
     return all([ sum(monom) <= 1 for monom in dmp_to_dict(f.rep, f.lev, f.dom).keys() ])
예제 #45
0
    def _together(expr):

        from sympy.core.function import Function

        if expr.is_Add:
            items, coeffs, basis = [], [], {}

            for elem in expr.args:
                numer, q = fraction(_together(elem))

                denom = {}

                for term in make_list(q.expand(), Mul):
                    expo = S.One
                    coeff = S.One

                    if term.is_Pow:
                        if term.exp.is_Rational:
                            term, expo = term.base, term.exp
                        elif term.exp.is_Mul:
                            coeff, tail = term.exp.as_coeff_terms()
                            if coeff.is_Rational:
                                tail = C.Mul(*tail)
                                term, expo = Pow(term.base, tail), coeff
                        coeff = S.One
                    elif term.func is C.exp:
                        if term.args[0].is_Rational:
                            term, expo = S.Exp1, term.args[0]
                        elif term.args[0].is_Mul:
                            coeff, tail = term.args[0].as_coeff_terms()
                            if coeff.is_Rational:
                                tail = C.Mul(*tail)
                                term, expo = C.exp(tail), coeff
                        coeff = S.One
                    elif term.is_Rational:
                        coeff = Integer(term.q)
                        term = Integer(term.p)

                    if term in denom:
                        denom[term] += expo
                    else:
                        denom[term] = expo

                    if term in basis:
                        total, maxi = basis[term]

                        n_total = total + expo
                        n_maxi = max(maxi, expo)

                        basis[term] = (n_total, n_maxi)
                    else:
                        basis[term] = (expo, expo)

                    coeffs.append(coeff)
                items.append((numer, denom))

            numerator, denominator = [], []

            for (term, (total, maxi)) in basis.iteritems():
                basis[term] = (total, total - maxi)

                if term.func is C.exp:
                    denominator.append(C.exp(maxi * term.args[0]))
                else:
                    if maxi is S.One:
                        denominator.append(term)
                    else:
                        denominator.append(Pow(term, maxi))

            if all([c.is_integer for c in coeffs]):
                gcds = lambda x, y: igcd(int(x), int(y))
                common = Rational(reduce(gcds, coeffs))
            else:
                common = S.One

            product = Mul(*coeffs) / common

            for ((numer, denom), coeff) in zip(items, coeffs):

                expr, coeff = [], product / (coeff * common)

                for term in basis.iterkeys():
                    total, sub = basis[term]

                    if term in denom:
                        expo = total - denom[term] - sub
                    else:
                        expo = total - sub

                    if term.func is C.exp:
                        expr.append(C.exp(expo * term.args[0]))
                    else:
                        if expo is S.One:
                            expr.append(term)
                        else:
                            expr.append(Pow(term, expo))

                numerator.append(coeff * Mul(*([numer] + expr)))

            return Add(*numerator) / (product * Mul(*denominator))
        elif expr.is_Mul or expr.is_Pow:
            return type(expr)(*[_together(t) for t in expr.args])
        elif expr.is_Function and deep:
            return expr.func(*[_together(t) for t in expr.args])
        else:
            return expr
예제 #46
0
 def is_linear(f):
     """Returns `True` if `f` is linear in all its variables. """
     return all(
         [sum(monom) <= 1 for monom in dmp_to_dict(f.rep, f.lev).keys()])
예제 #47
0
파일: function.py 프로젝트: addisonc/sympy
 def is_commutative(self):
     if all(getattr(t, 'is_commutative') for t in self.args):
         return True
     else:
         return False
예제 #48
0
 def is_quadratic(f):
     """Returns `True` if `f` is quadratic in all its variables. """
     return all(
         [sum(monom) <= 2 for monom in dmp_to_dict(f.rep, f.lev).keys()])
예제 #49
0
파일: polyclasses.py 프로젝트: haz/sympy
 def is_ground(f):
     """Returns `True` if `f` is an element of the ground domain. """
     return all(d <= 0 for d in dmp_degree_list(f.rep, f.lev))
예제 #50
0
def solve(f, *symbols, **flags):
    """Solves equations and systems of equations.

       Currently supported are univariate polynomial and transcendental
       equations and systems of linear and polynomial equations.  Input
       is formed as a single expression or an equation,  or an iterable
       container in case of an equation system.  The type of output may
       vary and depends heavily on the input. For more details refer to
       more problem specific functions.

       By default all solutions are simplified to make the output more
       readable. If this is not the expected behavior,  eg. because of
       speed issues, set simplified=False in function arguments.

       To solve equations and systems of equations of other kind, eg.
       recurrence relations of differential equations use rsolve() or
       dsolve() functions respectively.

       >>> from sympy import *
       >>> x,y = symbols('xy')

       Solve a polynomial equation:

       >>> solve(x**4-1, x)
       [1, -1, -I, I]

       Solve a linear system:

       >>> solve((x+5*y-2, -3*x+6*y-15), x, y)
       {x: -3, y: 1}

    """
    if not symbols:
        raise ValueError('no symbols were given')

    if len(symbols) == 1:
        if isinstance(symbols[0], (list, tuple, set)):
            symbols = symbols[0]

    symbols = map(sympify, symbols)
    result = list()

    # Begin code handling for Function and Derivative instances
    # Basic idea:  store all the passed symbols in symbols_passed, check to see
    # if any of them are Function or Derivative types, if so, use a dummy
    # symbol in their place, and set symbol_swapped = True so that other parts
    # of the code can be aware of the swap.  Once all swapping is done, the
    # continue on with regular solving as usual, and swap back at the end of
    # the routine, so that whatever was passed in symbols is what is returned.
    symbols_new = []
    symbol_swapped = False

    if isinstance(symbols, (list, tuple)):
        symbols_passed = symbols[:]
    elif isinstance(symbols, set):
        symbols_passed = list(symbols)

    i = 0
    for s in symbols:
        if s.is_Symbol:
            s_new = s
        elif s.is_Function:
            symbol_swapped = True
            s_new = Symbol('F%d' % i, dummy=True)
        elif s.is_Derivative:
            symbol_swapped = True
            s_new = Symbol('D%d' % i, dummy=True)
        else:
            raise TypeError('not a Symbol or a Function')
        symbols_new.append(s_new)
        i += 1

        if symbol_swapped:
            swap_back_dict = dict(zip(symbols_new, symbols))
    # End code for handling of Function and Derivative instances

    if not isinstance(f, (tuple, list, set)):
        f = sympify(f)

        # Create a swap dictionary for storing the passed symbols to be solved
        # for, so that they may be swapped back.
        if symbol_swapped:
            swap_dict = zip(symbols, symbols_new)
            f = f.subs(swap_dict)
            symbols = symbols_new

        if isinstance(f, Equality):
            f = f.lhs - f.rhs

        if len(symbols) != 1:
            raise NotImplementedError('multivariate equation')

        symbol = symbols[0]

        strategy = guess_solve_strategy(f, symbol)

        if strategy == GS_POLY:
            poly = f.as_poly(symbol)
            assert poly is not None
            result = roots(poly, cubics=True, quartics=True).keys()

        elif strategy == GS_RATIONAL:
            P, Q = f.as_numer_denom()
            #TODO: check for Q != 0
            return solve(P, symbol, **flags)

        elif strategy == GS_POLY_CV_1:
            args = list(f.args)
            if isinstance(f, Add):
                # we must search for a suitable change of variable
                # collect exponents
                exponents_denom = list()
                for arg in args:
                    if isinstance(arg, Pow):
                        exponents_denom.append(arg.exp.q)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                exponents_denom.append(mul_arg.exp.q)
                assert len(exponents_denom) > 0
                if len(exponents_denom) == 1:
                    m = exponents_denom[0]
                else:
                    # get the GCD of the denominators
                    m = ilcm(*exponents_denom)
                # x -> y**m.
                # we assume positive for simplification purposes
                t = Symbol('t', positive=True, dummy=True)
                f_ = f.subs(symbol, t**m)
                if guess_solve_strategy(f_, t) != GS_POLY:
                    raise TypeError(
                        "Could not convert to a polynomial equation: %s" % f_)
                cv_sols = solve(f_, t)
                for sol in cv_sols:
                    result.append(sol**m)

            elif isinstance(f, Mul):
                for mul_arg in args:
                    result.extend(solve(mul_arg, symbol))

        elif strategy == GS_POLY_CV_2:
            m = 0
            args = list(f.args)
            if isinstance(f, Add):
                for arg in args:
                    if isinstance(arg, Pow):
                        m = min(m, arg.exp)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                m = min(m, mul_arg.exp)
            elif isinstance(f, Mul):
                for mul_arg in args:
                    if isinstance(mul_arg, Pow):
                        m = min(m, mul_arg.exp)
            f1 = simplify(f * symbol**(-m))
            result = solve(f1, symbol)
            # TODO: we might have introduced unwanted solutions
            # when multiplied by x**-m

        elif strategy == GS_TRANSCENDENTAL:
            #a, b = f.as_numer_denom()
            # Let's throw away the denominator for now. When we have robust
            # assumptions, it should be checked, that for the solution,
            # b!=0.
            result = tsolve(f, *symbols)
        elif strategy == -1:
            raise ValueError('Could not parse expression %s' % f)
        else:
            raise NotImplementedError(
                "No algorithms are implemented to solve equation %s" % f)

        if flags.get('simplified', True):
            return map(simplify, result)
        else:
            return result
    else:
        if not f:
            return {}
        else:
            # Create a swap dictionary for storing the passed symbols to be
            # solved for, so that they may be swapped back.
            if symbol_swapped:
                swap_dict = zip(symbols, symbols_new)
                f = [fi.subs(swap_dict) for fi in f]
                symbols = symbols_new

            polys = []

            for g in f:
                g = sympify(g)

                if isinstance(g, Equality):
                    g = g.lhs - g.rhs

                poly = g.as_poly(*symbols)

                if poly is not None:
                    polys.append(poly)
                else:
                    raise NotImplementedError()

            if all(p.is_linear for p in polys):
                n, m = len(f), len(symbols)
                matrix = zeros((n, m + 1))

                for i, poly in enumerate(polys):
                    for coeff, monom in poly.iter_terms():
                        try:
                            j = list(monom).index(1)
                            matrix[i, j] = coeff
                        except ValueError:
                            matrix[i, m] = -coeff

                soln = solve_linear_system(matrix, *symbols, **flags)
            else:
                soln = solve_poly_system(polys)

            # Use swap_dict to ensure we return the same type as what was
            # passed
            if symbol_swapped:
                if isinstance(soln, dict):
                    res = {}
                    for k in soln.keys():
                        res.update({swap_back_dict[k]: soln[k]})
                    return res
                else:
                    return soln
            else:
                return soln
예제 #51
0
 def is_commutative(self):
     if all(getattr(t, 'is_commutative') for t in self.args):
         return True
     else:
         return False
예제 #52
0
def reduce_inequalities(inequalities, assume=True):
    """Reduce a system of inequalities with rational coefficients. """
    if not hasattr(inequalities, '__iter__'):
        inequalities = [inequalities]

    poly_part, abs_part, extra_assume = {}, {}, []

    for inequality in inequalities:
        if isinstance(inequality, bool):
            if inequality is False:
                return False
            else:
                continue

        if isinstance(inequality, AppliedPredicate):
            extra_assume.append(inequality)
            continue

        if inequality.is_Relational:
            expr, rel = inequality.lhs - inequality.rhs, inequality.rel_op
        else:
            expr, rel = inequality, '=='

        gens = expr.atoms(Symbol)

        if not gens:
            return False
        elif len(gens) == 1:
            gen = gens.pop()
        else:
            raise NotImplementedError("only univariate inequalities are supported")

        components = expr.find(lambda u: u.is_Function)

        if not components:
            if gen in poly_part:
                poly_part[gen].append((expr, rel))
            else:
                poly_part[gen] = [(expr, rel)]
        else:
            if all(isinstance(comp, Abs) for comp in components):
                if gen in abs_part:
                    abs_part[gen].append((expr, rel))
                else:
                    abs_part[gen] = [(expr, rel)]
            else:
                raise NotImplementedError("can't reduce %s" % inequalities)

    extra_assume = And(*extra_assume)

    if assume is not None:
        assume = And(assume, extra_assume)
    else:
        assume = extra_assume

    poly_reduced = []
    abs_reduced = []

    for gen, exprs in poly_part.iteritems():
        poly_reduced.append(reduce_poly_inequalities([exprs], gen, assume))

    for gen, exprs in abs_part.iteritems():
        abs_reduced.append(reduce_abs_inequalities(exprs, gen, assume))

    return And(*(poly_reduced + abs_reduced))
예제 #53
0
파일: solvers.py 프로젝트: pyc111/sympy
def solve(f, *symbols, **flags):
    """Solves equations and systems of equations.

       Currently supported are univariate polynomial, transcendental
       equations, piecewise combinations thereof and systems of linear
       and polynomial equations.  Input is formed as a single expression
       or an equation,  or an iterable container in case of an equation
       system.  The type of output may vary and depends heavily on the
       input. For more details refer to more problem specific functions.

       By default all solutions are simplified to make the output more
       readable. If this is not the expected behavior (e.g., because of
       speed issues) set simplified=False in function arguments.

       To solve equations and systems of equations like recurrence relations
       or differential equations, use rsolve() or dsolve(), respectively.

       >>> from sympy import I, solve
       >>> from sympy.abc import x, y

       Solve a polynomial equation:

       >>> solve(x**4-1, x)
       [1, -1, -I, I]

       Solve a linear system:

       >>> solve((x+5*y-2, -3*x+6*y-15), x, y)
       {x: -3, y: 1}

    """
    def sympit(w):
        return map(sympify, iff(isinstance(w, (list, tuple, set)), w, [w]))

    # make f and symbols into lists of sympified quantities
    # keeping track of how f was passed since if it is a list
    # a dictionary of results will be returned.
    bare_f = not isinstance(f, (list, tuple, set))
    f, symbols = (sympit(w) for w in [f, symbols])

    for i, fi in enumerate(f):
        if isinstance(fi, Equality):
            f[i] = fi.lhs - fi.rhs

    if not symbols:
        #get symbols from equations or supply dummy symbols since
        #solve(3,x) returns []...though it seems that it should raise some sort of error TODO
        symbols = set([])
        for fi in f:
            symbols |= fi.atoms(Symbol) or set([Dummy('x')])
        symbols = list(symbols)

    if bare_f:
        f = f[0]
    if len(symbols) == 1:
        if isinstance(symbols[0], (list, tuple, set)):
            symbols = symbols[0]

    result = list()

    # Begin code handling for Function and Derivative instances
    # Basic idea:  store all the passed symbols in symbols_passed, check to see
    # if any of them are Function or Derivative types, if so, use a dummy
    # symbol in their place, and set symbol_swapped = True so that other parts
    # of the code can be aware of the swap.  Once all swapping is done, the
    # continue on with regular solving as usual, and swap back at the end of
    # the routine, so that whatever was passed in symbols is what is returned.
    symbols_new = []
    symbol_swapped = False

    symbols_passed = list(symbols)

    for i, s in enumerate(symbols):
        if s.is_Symbol:
            s_new = s
        elif s.is_Function:
            symbol_swapped = True
            s_new = Dummy('F%d' % i)
        elif s.is_Derivative:
            symbol_swapped = True
            s_new = Dummy('D%d' % i)
        else:
            raise TypeError('not a Symbol or a Function')
        symbols_new.append(s_new)

        if symbol_swapped:
            swap_back_dict = dict(zip(symbols_new, symbols))
    # End code for handling of Function and Derivative instances

    if not isinstance(f, (tuple, list, set)):

        # Create a swap dictionary for storing the passed symbols to be solved
        # for, so that they may be swapped back.
        if symbol_swapped:
            swap_dict = zip(symbols, symbols_new)
            f = f.subs(swap_dict)
            symbols = symbols_new

        # Any embedded piecewise functions need to be brought out to the
        # top level so that the appropriate strategy gets selected.
        f = piecewise_fold(f)

        if len(symbols) != 1:
            result = {}
            for s in symbols:
                result[s] = solve(f, s, **flags)
            if flags.get('simplified', True):
                for s, r in result.items():
                    result[s] = map(simplify, r)
            return result

        symbol = symbols[0]
        strategy = guess_solve_strategy(f, symbol)

        if strategy == GS_POLY:
            poly = f.as_poly(symbol)
            if poly is None:
                raise NotImplementedError("Cannot solve equation " + str(f) +
                                          " for " + str(symbol))
            # for cubics and quartics, if the flag wasn't set, DON'T do it
            # by default since the results are quite long. Perhaps one could
            # base this decision on a certain crtical length of the roots.
            if poly.degree > 2:
                flags['simplified'] = flags.get('simplified', False)
            result = roots(poly, cubics=True, quartics=True).keys()

        elif strategy == GS_RATIONAL:
            P, Q = f.as_numer_denom()
            #TODO: check for Q != 0
            result = solve(P, symbol, **flags)

        elif strategy == GS_POLY_CV_1:
            args = list(f.args)
            if isinstance(f, Add):
                # we must search for a suitable change of variable
                # collect exponents
                exponents_denom = list()
                for arg in args:
                    if isinstance(arg, Pow):
                        exponents_denom.append(arg.exp.q)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                exponents_denom.append(mul_arg.exp.q)
                assert len(exponents_denom) > 0
                if len(exponents_denom) == 1:
                    m = exponents_denom[0]
                else:
                    # get the LCM of the denominators
                    m = reduce(ilcm, exponents_denom)
                # x -> y**m.
                # we assume positive for simplification purposes
                t = Dummy('t', positive=True)
                f_ = f.subs(symbol, t**m)
                if guess_solve_strategy(f_, t) != GS_POLY:
                    raise NotImplementedError(
                        "Could not convert to a polynomial equation: %s" % f_)
                cv_sols = solve(f_, t)
                for sol in cv_sols:
                    result.append(sol**m)

            elif isinstance(f, Mul):
                for mul_arg in args:
                    result.extend(solve(mul_arg, symbol))

        elif strategy == GS_POLY_CV_2:
            m = 0
            args = list(f.args)
            if isinstance(f, Add):
                for arg in args:
                    if isinstance(arg, Pow):
                        m = min(m, arg.exp)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                m = min(m, mul_arg.exp)
            elif isinstance(f, Mul):
                for mul_arg in args:
                    if isinstance(mul_arg, Pow):
                        m = min(m, mul_arg.exp)
            f1 = simplify(f * symbol**(-m))
            result = solve(f1, symbol)
            # TODO: we might have introduced unwanted solutions
            # when multiplied by x**-m

        elif strategy == GS_PIECEWISE:
            result = set()
            for expr, cond in f.args:
                candidates = solve(expr, *symbols)
                if isinstance(cond, bool) or cond.is_Number:
                    if not cond:
                        continue

                    # Only include solutions that do not match the condition
                    # of any of the other pieces.
                    for candidate in candidates:
                        matches_other_piece = False
                        for other_expr, other_cond in f.args:
                            if isinstance(other_cond, bool) \
                               or other_cond.is_Number:
                                continue
                            if bool(other_cond.subs(symbol, candidate)):
                                matches_other_piece = True
                                break
                        if not matches_other_piece:
                            result.add(candidate)
                else:
                    for candidate in candidates:
                        if bool(cond.subs(symbol, candidate)):
                            result.add(candidate)

            result = list(result)

        elif strategy == GS_TRANSCENDENTAL:
            #a, b = f.as_numer_denom()
            # Let's throw away the denominator for now. When we have robust
            # assumptions, it should be checked, that for the solution,
            # b!=0.
            result = tsolve(f, *symbols)
        elif strategy == -1:
            raise ValueError('Could not parse expression %s' % f)
        else:
            raise NotImplementedError(
                "No algorithms are implemented to solve equation %s" % f)

        # This symbol swap should not be necessary for the single symbol case: if you've
        # solved for the symbol the it will not appear in the solution. Right now, however
        # ode's are getting solutions for solve (even though they shouldn't be -- see the
        # swap_back test in test_solvers).
        if symbol_swapped:
            result = [ri.subs(swap_back_dict) for ri in result]

        if flags.get('simplified', True) and strategy != GS_RATIONAL:
            return map(simplify, result)
        else:
            return result
    else:
        if not f:
            return {}
        else:
            # Create a swap dictionary for storing the passed symbols to be
            # solved for, so that they may be swapped back.
            if symbol_swapped:
                swap_dict = zip(symbols, symbols_new)
                f = [fi.subs(swap_dict) for fi in f]
                symbols = symbols_new

            polys = []

            for g in f:

                poly = g.as_poly(*symbols)

                if poly is not None:
                    polys.append(poly)
                else:
                    raise NotImplementedError()

            if all(p.is_linear for p in polys):
                n, m = len(f), len(symbols)
                matrix = zeros((n, m + 1))

                for i, poly in enumerate(polys):
                    for monom, coeff in poly.terms():
                        try:
                            j = list(monom).index(1)
                            matrix[i, j] = coeff
                        except ValueError:
                            matrix[i, m] = -coeff

                soln = solve_linear_system(matrix, *symbols, **flags)
            else:
                soln = solve_poly_system(polys)

            # Use swap_dict to ensure we return the same type as what was
            # passed
            if symbol_swapped:
                if isinstance(soln, dict):
                    res = {}
                    for k in soln.keys():
                        res.update({swap_back_dict[k]: soln[k]})
                    return res
                else:
                    return soln
            else:
                return soln
예제 #54
0
 def is_ground(f):
     """Returns `True` if `f` is an element of the ground domain. """
     return all(d <= 0 for d in dmp_degree_list(f.rep, f.lev))
예제 #55
0
파일: solvers.py 프로젝트: cran/rSymPy
def solve(f, *symbols, **flags):
    """Solves equations and systems of equations.

       Currently supported are univariate polynomial and transcendental
       equations and systems of linear and polynomial equations.  Input
       is formed as a single expression or an equation,  or an iterable
       container in case of an equation system.  The type of output may
       vary and depends heavily on the input. For more details refer to
       more problem specific functions.

       By default all solutions are simplified to make the output more
       readable. If this is not the expected behavior,  eg. because of
       speed issues, set simplified=False in function arguments.

       To solve equations and systems of equations of other kind, eg.
       recurrence relations of differential equations use rsolve() or
       dsolve() functions respectively.

       >>> from sympy import *
       >>> x,y = symbols('xy')

       Solve a polynomial equation:

       >>> solve(x**4-1, x)
       [1, -1, -I, I]

       Solve a linear system:

       >>> solve((x+5*y-2, -3*x+6*y-15), x, y)
       {x: -3, y: 1}

    """
    if not symbols:
        raise ValueError('no symbols were given')

    if len(symbols) == 1:
        if isinstance(symbols[0], (list, tuple, set)):
            symbols = symbols[0]

    symbols = map(sympify, symbols)
    result = list()

    # Begin code handling for Function and Derivative instances
    # Basic idea:  store all the passed symbols in symbols_passed, check to see
    # if any of them are Function or Derivative types, if so, use a dummy
    # symbol in their place, and set symbol_swapped = True so that other parts
    # of the code can be aware of the swap.  Once all swapping is done, the
    # continue on with regular solving as usual, and swap back at the end of
    # the routine, so that whatever was passed in symbols is what is returned.
    symbols_new = []
    symbol_swapped = False

    if isinstance(symbols, (list, tuple)):
        symbols_passed = symbols[:]
    elif isinstance(symbols, set):
        symbols_passed = list(symbols)

    i = 0
    for s in symbols:
        if s.is_Symbol:
            s_new = s
        elif s.is_Function:
            symbol_swapped = True
            s_new = Symbol('F%d' % i, dummy=True)
        elif s.is_Derivative:
            symbol_swapped = True
            s_new = Symbol('D%d' % i, dummy=True)
        else:
            raise TypeError('not a Symbol or a Function')
        symbols_new.append(s_new)
        i += 1

        if symbol_swapped:
            swap_back_dict = dict(zip(symbols_new, symbols))
    # End code for handling of Function and Derivative instances

    if not isinstance(f, (tuple, list, set)):
        f = sympify(f)

        # Create a swap dictionary for storing the passed symbols to be solved
        # for, so that they may be swapped back.
        if symbol_swapped:
            swap_dict = zip(symbols, symbols_new)
            f = f.subs(swap_dict)
            symbols = symbols_new

        if isinstance(f, Equality):
            f = f.lhs - f.rhs

        if len(symbols) != 1:
            raise NotImplementedError('multivariate equation')

        symbol = symbols[0]

        strategy = guess_solve_strategy(f, symbol)

        if strategy == GS_POLY:
            poly = f.as_poly( symbol )
            assert poly is not None
            result = roots(poly, cubics=True, quartics=True).keys()

        elif strategy == GS_RATIONAL:
            P, Q = f.as_numer_denom()
            #TODO: check for Q != 0
            return solve(P, symbol, **flags)

        elif strategy == GS_POLY_CV_1:
            args = list(f.args)
            if isinstance(f, Add):
                # we must search for a suitable change of variable
                # collect exponents
                exponents_denom = list()
                for arg in args:
                    if isinstance(arg, Pow):
                        exponents_denom.append(arg.exp.q)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                exponents_denom.append(mul_arg.exp.q)
                assert len(exponents_denom) > 0
                if len(exponents_denom) == 1:
                    m = exponents_denom[0]
                else:
                    # get the GCD of the denominators
                    m = ilcm(*exponents_denom)
                # x -> y**m.
                # we assume positive for simplification purposes
                t = Symbol('t', positive=True, dummy=True)
                f_ = f.subs(symbol, t**m)
                if guess_solve_strategy(f_, t) != GS_POLY:
                    raise TypeError("Could not convert to a polynomial equation: %s" % f_)
                cv_sols = solve(f_, t)
                for sol in cv_sols:
                    result.append(sol**m)

            elif isinstance(f, Mul):
                for mul_arg in args:
                    result.extend(solve(mul_arg, symbol))

        elif strategy == GS_POLY_CV_2:
            m = 0
            args = list(f.args)
            if isinstance(f, Add):
                for arg in args:
                    if isinstance(arg, Pow):
                        m = min(m, arg.exp)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                m = min(m, mul_arg.exp)
            elif isinstance(f, Mul):
                for mul_arg in args:
                    if isinstance(mul_arg, Pow):
                        m = min(m, mul_arg.exp)
            f1 = simplify(f*symbol**(-m))
            result = solve(f1, symbol)
            # TODO: we might have introduced unwanted solutions
            # when multiplied by x**-m

        elif strategy == GS_TRANSCENDENTAL:
            #a, b = f.as_numer_denom()
            # Let's throw away the denominator for now. When we have robust
            # assumptions, it should be checked, that for the solution,
            # b!=0.
            result = tsolve(f, *symbols)
        elif strategy == -1:
            raise ValueError('Could not parse expression %s' % f)
        else:
            raise NotImplementedError("No algorithms are implemented to solve equation %s" % f)

        if flags.get('simplified', True):
            return map(simplify, result)
        else:
            return result
    else:
        if not f:
            return {}
        else:
            # Create a swap dictionary for storing the passed symbols to be
            # solved for, so that they may be swapped back.
            if symbol_swapped:
                swap_dict = zip(symbols, symbols_new)
                f = [fi.subs(swap_dict) for fi in f]
                symbols = symbols_new

            polys = []

            for g in f:
                g = sympify(g)

                if isinstance(g, Equality):
                    g = g.lhs - g.rhs

                poly = g.as_poly(*symbols)

                if poly is not None:
                    polys.append(poly)
                else:
                    raise NotImplementedError()

            if all(p.is_linear for p in polys):
                n, m = len(f), len(symbols)
                matrix = zeros((n, m + 1))

                for i, poly in enumerate(polys):
                    for coeff, monom in poly.iter_terms():
                        try:
                            j = list(monom).index(1)
                            matrix[i, j] = coeff
                        except ValueError:
                            matrix[i, m] = -coeff

                soln = solve_linear_system(matrix, *symbols, **flags)
            else:
                soln = solve_poly_system(polys)

            # Use swap_dict to ensure we return the same type as what was
            # passed
            if symbol_swapped:
                if isinstance(soln, dict):
                    res = {}
                    for k in soln.keys():
                        res.update({swap_back_dict[k]: soln[k]})
                    return res
                else:
                    return soln
            else:
                return soln
예제 #56
0
파일: polyclasses.py 프로젝트: fxkr/sympy
 def nth(f, *N):
     """Returns the `n`-th coefficient of `f`. """
     if all(isinstance(n, int) for n in N):
         return dmp_ground_nth(f.rep, N, f.lev, f.dom)
     else:
         raise TypeError("a sequence of integers expected")
예제 #57
0
파일: solvers.py 프로젝트: mackaka/sympy
def solve(f, *symbols, **flags):
    """Solves equations and systems of equations.

       Currently supported are univariate polynomial, transcendental
       equations, piecewise combinations thereof and systems of linear
       and polynomial equations.  Input is formed as a single expression
       or an equation,  or an iterable container in case of an equation
       system.  The type of output may vary and depends heavily on the
       input. For more details refer to more problem specific functions.

       By default all solutions are simplified to make the output more
       readable. If this is not the expected behavior (e.g., because of
       speed issues) set simplified=False in function arguments.

       To solve equations and systems of equations like recurrence relations
       or differential equations, use rsolve() or dsolve(), respectively.

       >>> from sympy import I, solve
       >>> from sympy.abc import x, y

       Solve a polynomial equation:

       >>> solve(x**4-1, x)
       [1, -1, -I, I]

       Solve a linear system:

       >>> solve((x+5*y-2, -3*x+6*y-15), x, y)
       {x: -3, y: 1}

    """

    def sympit(w):
        return map(sympify, iff(isinstance(w, (list, tuple, set)), w, [w]))

    # make f and symbols into lists of sympified quantities
    # keeping track of how f was passed since if it is a list
    # a dictionary of results will be returned.
    bare_f = not isinstance(f, (list, tuple, set))
    f, symbols = (sympit(w) for w in [f, symbols])

    if any(isinstance(fi, bool) or (fi.is_Relational and not fi.is_Equality) for fi in f):
        return reduce_inequalities(f, assume=flags.get("assume"))

    for i, fi in enumerate(f):
        if fi.is_Equality:
            f[i] = fi.lhs - fi.rhs

    if not symbols:
        # get symbols from equations or supply dummy symbols since
        # solve(3,x) returns []...though it seems that it should raise some sort of error TODO
        symbols = set([])
        for fi in f:
            symbols |= fi.atoms(Symbol) or set([Dummy("x")])
        symbols = list(symbols)

    if bare_f:
        f = f[0]
    if len(symbols) == 1:
        if isinstance(symbols[0], (list, tuple, set)):
            symbols = symbols[0]

    result = list()

    # Begin code handling for Function and Derivative instances
    # Basic idea:  store all the passed symbols in symbols_passed, check to see
    # if any of them are Function or Derivative types, if so, use a dummy
    # symbol in their place, and set symbol_swapped = True so that other parts
    # of the code can be aware of the swap.  Once all swapping is done, the
    # continue on with regular solving as usual, and swap back at the end of
    # the routine, so that whatever was passed in symbols is what is returned.
    symbols_new = []
    symbol_swapped = False

    symbols_passed = list(symbols)

    for i, s in enumerate(symbols):
        if s.is_Symbol:
            s_new = s
        elif s.is_Function:
            symbol_swapped = True
            s_new = Dummy("F%d" % i)
        elif s.is_Derivative:
            symbol_swapped = True
            s_new = Dummy("D%d" % i)
        else:
            raise TypeError("not a Symbol or a Function")
        symbols_new.append(s_new)

        if symbol_swapped:
            swap_back_dict = dict(zip(symbols_new, symbols))
    # End code for handling of Function and Derivative instances

    if not isinstance(f, (tuple, list, set)):

        # Create a swap dictionary for storing the passed symbols to be solved
        # for, so that they may be swapped back.
        if symbol_swapped:
            swap_dict = zip(symbols, symbols_new)
            f = f.subs(swap_dict)
            symbols = symbols_new

        # Any embedded piecewise functions need to be brought out to the
        # top level so that the appropriate strategy gets selected.
        f = piecewise_fold(f)

        if len(symbols) != 1:
            result = {}
            for s in symbols:
                result[s] = solve(f, s, **flags)
            if flags.get("simplified", True):
                for s, r in result.items():
                    result[s] = map(simplify, r)
            return result

        symbol = symbols[0]
        strategy = guess_solve_strategy(f, symbol)

        if strategy == GS_POLY:
            poly = f.as_poly(symbol)
            if poly is None:
                raise NotImplementedError("Cannot solve equation " + str(f) + " for " + str(symbol))
            # for cubics and quartics, if the flag wasn't set, DON'T do it
            # by default since the results are quite long. Perhaps one could
            # base this decision on a certain crtical length of the roots.
            if poly.degree > 2:
                flags["simplified"] = flags.get("simplified", False)
            result = roots(poly, cubics=True, quartics=True).keys()

        elif strategy == GS_RATIONAL:
            P, Q = f.as_numer_denom()
            # TODO: check for Q != 0
            result = solve(P, symbol, **flags)

        elif strategy == GS_POLY_CV_1:
            args = list(f.args)
            if isinstance(f, Add):
                # we must search for a suitable change of variable
                # collect exponents
                exponents_denom = list()
                for arg in args:
                    if isinstance(arg, Pow):
                        exponents_denom.append(arg.exp.q)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                exponents_denom.append(mul_arg.exp.q)
                assert len(exponents_denom) > 0
                if len(exponents_denom) == 1:
                    m = exponents_denom[0]
                else:
                    # get the LCM of the denominators
                    m = reduce(ilcm, exponents_denom)
                # x -> y**m.
                # we assume positive for simplification purposes
                t = Dummy("t", positive=True)
                f_ = f.subs(symbol, t ** m)
                if guess_solve_strategy(f_, t) != GS_POLY:
                    raise NotImplementedError("Could not convert to a polynomial equation: %s" % f_)
                cv_sols = solve(f_, t)
                for sol in cv_sols:
                    result.append(sol ** m)

            elif isinstance(f, Mul):
                for mul_arg in args:
                    result.extend(solve(mul_arg, symbol))

        elif strategy == GS_POLY_CV_2:
            m = 0
            args = list(f.args)
            if isinstance(f, Add):
                for arg in args:
                    if isinstance(arg, Pow):
                        m = min(m, arg.exp)
                    elif isinstance(arg, Mul):
                        for mul_arg in arg.args:
                            if isinstance(mul_arg, Pow):
                                m = min(m, mul_arg.exp)
            elif isinstance(f, Mul):
                for mul_arg in args:
                    if isinstance(mul_arg, Pow):
                        m = min(m, mul_arg.exp)
            f1 = simplify(f * symbol ** (-m))
            result = solve(f1, symbol)
            # TODO: we might have introduced unwanted solutions
            # when multiplied by x**-m

        elif strategy == GS_PIECEWISE:
            result = set()
            for expr, cond in f.args:
                candidates = solve(expr, *symbols)
                if isinstance(cond, bool) or cond.is_Number:
                    if not cond:
                        continue

                    # Only include solutions that do not match the condition
                    # of any of the other pieces.
                    for candidate in candidates:
                        matches_other_piece = False
                        for other_expr, other_cond in f.args:
                            if isinstance(other_cond, bool) or other_cond.is_Number:
                                continue
                            if bool(other_cond.subs(symbol, candidate)):
                                matches_other_piece = True
                                break
                        if not matches_other_piece:
                            result.add(candidate)
                else:
                    for candidate in candidates:
                        if bool(cond.subs(symbol, candidate)):
                            result.add(candidate)

            result = list(result)

        elif strategy == GS_TRANSCENDENTAL:
            # a, b = f.as_numer_denom()
            # Let's throw away the denominator for now. When we have robust
            # assumptions, it should be checked, that for the solution,
            # b!=0.
            result = tsolve(f, *symbols)
        elif strategy == -1:
            raise ValueError("Could not parse expression %s" % f)
        else:
            raise NotImplementedError("No algorithms are implemented to solve equation %s" % f)

        # This symbol swap should not be necessary for the single symbol case: if you've
        # solved for the symbol the it will not appear in the solution. Right now, however
        # ode's are getting solutions for solve (even though they shouldn't be -- see the
        # swap_back test in test_solvers).
        if symbol_swapped:
            result = [ri.subs(swap_back_dict) for ri in result]

        if flags.get("simplified", True) and strategy != GS_RATIONAL:
            return map(simplify, result)
        else:
            return result
    else:
        if not f:
            return {}
        else:
            # Create a swap dictionary for storing the passed symbols to be
            # solved for, so that they may be swapped back.
            if symbol_swapped:
                swap_dict = zip(symbols, symbols_new)
                f = [fi.subs(swap_dict) for fi in f]
                symbols = symbols_new

            polys = []

            for g in f:

                poly = g.as_poly(*symbols)

                if poly is not None:
                    polys.append(poly)
                else:
                    raise NotImplementedError()

            if all(p.is_linear for p in polys):
                n, m = len(f), len(symbols)
                matrix = zeros((n, m + 1))

                for i, poly in enumerate(polys):
                    for monom, coeff in poly.terms():
                        try:
                            j = list(monom).index(1)
                            matrix[i, j] = coeff
                        except ValueError:
                            matrix[i, m] = -coeff

                soln = solve_linear_system(matrix, *symbols, **flags)
            else:
                soln = solve_poly_system(polys)

            # Use swap_dict to ensure we return the same type as what was
            # passed
            if symbol_swapped:
                if isinstance(soln, dict):
                    res = {}
                    for k in soln.keys():
                        res.update({swap_back_dict[k]: soln[k]})
                    return res
                else:
                    return soln
            else:
                return soln
예제 #58
0
def dmp_zz_factor(f, u, K):
    """
    Factor (non square-free) polynomials in `Z[X]`.

    Given a multivariate polynomial `f` in `Z[x]` computes its complete
    factorization `f_1, ..., f_n` into irreducibles over integers::

                 f = content(f) f_1**k_1 ... f_n**k_n

    The factorization is computed by reducing the input polynomial
    into a primitive square-free polynomial and factoring it using
    Enhanced Extended Zassenhaus (EEZ) algorithm. Trial division
    is used to recover the multiplicities of factors.

    The result is returned as a tuple consisting of::

             (content(f), [(f_1, k_1), ..., (f_n, k_n))

    Consider polynomial `f = 2*(x**2 - y**2)`::

        >>> from sympy.polys.factortools import dmp_zz_factor
        >>> from sympy.polys.domains import ZZ

        >>> dmp_zz_factor([[2], [], [-2, 0, 0]], 1, ZZ)
        (2, [([[1], [-1, 0]], 1), ([[1], [1, 0]], 1)])

    In result we got the following factorization::

                    f = 2 (x - y) (x + y)

    **References**

    1. [Gathen99]_

    """
    if not u:
        return dup_zz_factor(f, K)

    if dmp_zero_p(f, u):
        return K.zero, []

    cont, g = dmp_ground_primitive(f, u, K)

    if dmp_ground_LC(g, u, K) < 0:
        cont, g = -cont, dmp_neg(g, u, K)

    if all([d <= 0 for d in dmp_degree_list(g, u)]):
        return cont, []

    G, g = dmp_primitive(g, u, K)

    factors = []

    if dmp_degree(g, u) > 0:
        g = dmp_sqf_part(g, u, K)
        H = dmp_zz_wang(g, u, K)

        for h in H:
            k = 0

            while True:
                q, r = dmp_div(f, h, u, K)

                if dmp_zero_p(r, u):
                    f, k = q, k + 1
                else:
                    break

            factors.append((h, k))

    for g, k in dmp_zz_factor(G, u - 1, K)[1]:
        factors.insert(0, ([g], k))

    return cont, _sort_factors(factors)