コード例 #1
0
    def _eval_(self, n, m, theta, phi, **kwargs):
        r"""
        TESTS::

            sage: x, y = var('x y')
            sage: spherical_harmonic(1, 2, x, y)
            0
            sage: spherical_harmonic(1, -2, x, y)
            0
            sage: spherical_harmonic(1/2, 2, x, y)
            spherical_harmonic(1/2, 2, x, y)
            sage: spherical_harmonic(3, 2, x, y)
            15/4*sqrt(7/30)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi)
            sage: spherical_harmonic(3, 2, 1, 2)
            15/4*sqrt(7/30)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi)
            sage: spherical_harmonic(3 + I, 2., 1, 2)
            -0.351154337307488 - 0.415562233975369*I
        """
        from sage.structure.coerce import parent
        cc = get_coercion_model().canonical_coercion
        coerced = cc(phi, cc(theta, cc(n, m)[0])[0])[0]
        if is_inexact(coerced) and not isinstance(coerced, Expression):
            return self._evalf_(n, m, theta, phi, parent=parent(coerced))
        elif n in ZZ and m in ZZ and n > -1:
            if abs(m) > n:
                return ZZ(0)
            return meval("spherical_harmonic({},{},{},{})".format(
                ZZ(n), ZZ(m), maxima(theta), maxima(phi)))
        return
コード例 #2
0
ファイル: special.py プロジェクト: acrlakshman/sage
    def _eval_(self, n, m, theta, phi, **kwargs):
        r"""
        TESTS::

            sage: x, y = var('x y')
            sage: spherical_harmonic(1, 2, x, y)
            0
            sage: spherical_harmonic(1, -2, x, y)
            0
            sage: spherical_harmonic(1/2, 2, x, y)
            spherical_harmonic(1/2, 2, x, y)
            sage: spherical_harmonic(3, 2, x, y)
            15/4*sqrt(7/30)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi)
            sage: spherical_harmonic(3, 2, 1, 2)
            15/4*sqrt(7/30)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi)
            sage: spherical_harmonic(3 + I, 2., 1, 2)
            -0.351154337307488 - 0.415562233975369*I
        """
        from sage.structure.coerce import parent
        cc = get_coercion_model().canonical_coercion
        coerced = cc(phi, cc(theta, cc(n, m)[0])[0])[0]
        if is_inexact(coerced) and not isinstance(coerced, Expression):
            return self._evalf_(n, m, theta, phi, parent=parent(coerced))
        elif n in ZZ and m in ZZ and n > -1:
            if abs(m) > n:
                return ZZ(0)
            return meval("spherical_harmonic({},{},{},{})".format(
                ZZ(n), ZZ(m), maxima(theta), maxima(phi)))
        return
コード例 #3
0
ファイル: special.py プロジェクト: pombredanne/sage-1
    def _eval_(self, *args):
        """
        Returns a string which represents this function evaluated at
        *args* in Maxima.

        EXAMPLES::

            sage: from sage.functions.special import MaximaFunction
            sage: f = MaximaFunction("jacobi_sn")
            sage: f(1,1)
            tanh(1)
            
            sage: f._eval_(1,1)
            tanh(1)

        Here arccoth doesn't have 1 in its domain, so we just hold the expression:

            sage: elliptic_e(arccoth(1), x^2*e)
            elliptic_e(arccoth(1), x^2*e) 
        """
        _init()
        try:
            s = maxima(self._maxima_init_evaled_(*args))
        except TypeError:
            return None
        if self.name() in repr(s):
            return None
        else:
            return s.sage()
コード例 #4
0
ファイル: special.py プロジェクト: pombredanne/sage-1
    def _evalf_(self, *args, **kwds):
        """
        Returns a numerical approximation of this function using
        Maxima.  Currently, this is limited to 53 bits of precision.

        EXAMPLES::

            sage: from sage.functions.special import MaximaFunction
            sage: f = MaximaFunction("jacobi_sn")
            sage: f(1/2,1/2)
            jacobi_sn(1/2, 1/2)
            sage: f(1/2,1/2).n()
            0.470750473655657
            
        TESTS::

            sage: f(1/2,1/2).n(150)
            Traceback (most recent call last):
            ...
            NotImplementedError: jacobi_sn not implemented for precision > 53
        """
        parent = kwds['parent']
        if hasattr(parent, 'prec') and parent.prec() > 53:
            raise NotImplementedError, "%s not implemented for precision > 53"%self.name()
        _init()
        return parent(maxima("%s, numer"%self._maxima_init_evaled_(*args)))
コード例 #5
0
    def _eval_(self, *args):
        """
        Returns a string which represents this function evaluated at
        *args* in Maxima.

        EXAMPLES::

            sage: from sage.functions.special import MaximaFunction
            sage: f = MaximaFunction("jacobi_sn")
            sage: f(1,1)
            tanh(1)
            
            sage: f._eval_(1,1)
            tanh(1)

        Here arccoth doesn't have 1 in its domain, so we just hold the expression:

            sage: elliptic_e(arccoth(1), x^2*e)
            elliptic_e(arccoth(1), x^2*e) 
        """
        _init()
        try:
            s = maxima(self._maxima_init_evaled_(*args))
        except TypeError:
            return None
        if self.name() in repr(s):
            return None
        else:
            return s.sage()
コード例 #6
0
    def _evalf_(self, *args, **kwds):
        """
        Returns a numerical approximation of this function using
        Maxima.  Currently, this is limited to 53 bits of precision.

        EXAMPLES::

            sage: from sage.functions.special import MaximaFunction
            sage: f = MaximaFunction("jacobi_sn")
            sage: f(1/2,1/2)
            jacobi_sn(1/2, 1/2)
            sage: f(1/2,1/2).n()
            0.470750473655657
            
        TESTS::

            sage: f(1/2,1/2).n(150)
            Traceback (most recent call last):
            ...
            NotImplementedError: jacobi_sn not implemented for precision > 53
        """
        parent = kwds['parent']
        if hasattr(parent, 'prec') and parent.prec() > 53:
            raise NotImplementedError, "%s not implemented for precision > 53" % self.name(
            )
        _init()
        return parent(maxima("%s, numer" % self._maxima_init_evaled_(*args)))
コード例 #7
0
ファイル: assumptions.py プロジェクト: sajedel/testsage
    def assume(self):
        """
        TEST::

            sage: from sage.symbolic.assumptions import GenericDeclaration
            sage: decl = GenericDeclaration(x, 'even')
            sage: decl.assume()
            sage: cos(x*pi).simplify()
            1
            sage: decl2 = GenericDeclaration(x, 'odd')
            sage: decl2.assume()
            Traceback (most recent call last):
            ...
            ValueError: Assumption is inconsistent
            sage: decl.forget()
        """
        from sage.calculus.calculus import maxima
        if self._context is None:
            # We get the list here because features may be added with time.
            valid_features = list(maxima("features"))
            if self._assumption not in [repr(x).strip() for x in list(valid_features)]:
                raise ValueError, "%s not a valid assumption, must be one of %s" % (self._assumption, valid_features)
            cur = maxima.get("context")
            self._context = maxima.newcontext('context' + maxima._next_var_name())
            try:
                maxima.eval("declare(%s, %s)" % (repr(self._var), self._assumption))
#            except TypeError, mess:
#                if 'inconsistent' in str(mess): # note Maxima doesn't tell you if declarations are redundant
#                    raise ValueError, "Assumption is inconsistent"
            except RuntimeError, mess:
                if 'inconsistent' in str(mess): # note Maxima doesn't tell you if declarations are redundant
                    raise ValueError, "Assumption is inconsistent"
                else:
                    raise
            maxima.set("context", cur)
コード例 #8
0
ファイル: assumptions.py プロジェクト: swewers/mein_sage
    def _validate_feature(self):
        """
        Check if this assumption is a known maxima feature, raise an error otherwise

        EXAMPLES::

            sage: from sage.symbolic.assumptions import GenericDeclaration as GDecl
            sage: var('b')
            b
            sage: GDecl(b, 'bougie')
            b is bougie
            sage: _.assume()
            Traceback (most recent call last):
            ...
            ValueError: bougie not a valid assumption, must be one of ['analytic', ... 'symmetric']
        """
        from sage.calculus.calculus import maxima
        global _valid_feature_strings
        if self._assumption in _valid_feature_strings:
            return
        # We get the list here because features may be added with time.
        _valid_feature_strings.update(
            repr(x).strip() for x in list(maxima("features")))
        if self._assumption in _valid_feature_strings:
            return
        raise ValueError("%s not a valid assumption, must be one of %s" %
                         (self._assumption, sorted(_valid_feature_strings)))
コード例 #9
0
ファイル: special.py プロジェクト: pombredanne/sage-1
def meval(x):
    """
    Returns ``x`` evaluated in Maxima, then returned to Sage.
    This is used to evaluate several of these special functions.
    
    TEST::

        sage: from sage.functions.special import airy_ai
        sage: airy_bi(1.0)
        1.20742359495
    """
    return maxima(x).sage()
コード例 #10
0
def meval(x):
    """
    Returns ``x`` evaluated in Maxima, then returned to Sage.
    This is used to evaluate several of these special functions.
    
    TEST::

        sage: from sage.functions.special import airy_ai
        sage: airy_bi(1.0)
        1.20742359495
    """
    return maxima(x).sage()
コード例 #11
0
ファイル: special.py プロジェクト: manguluka/sage
def meval(x):
    """
    Return ``x`` evaluated in Maxima, then returned to Sage.

    This is used to evaluate several of these special functions.

    TEST::

        sage: from sage.functions.special import spherical_bessel_J
        sage: spherical_bessel_J(2.,3.)      # rel tol 1e-10
        0.2986374970757335
    """
    return maxima(x).sage()
コード例 #12
0
    def _evalf_(self, *args, **kwds):
        """
        Returns a numerical approximation of this function using
        Maxima.  Currently, this is limited to 53 bits of precision.

        EXAMPLES::

            sage: from sage.functions.special import MaximaFunction
            sage: f = MaximaFunction("jacobi_sn")
            sage: f(1/2, 1/2)
            jacobi_sn(1/2, 1/2)
            sage: f(1/2, 1/2).n()
            0.470750473655657
            sage: f(1/2, 1/2).n(20)
            0.47075
            sage: f(1, I).n()
            0.848379519751901 - 0.0742924572771414*I

        TESTS::

            sage: f(1/2, 1/2).n(150)
            Traceback (most recent call last):
            ...
            NotImplementedError: Maxima function jacobi_sn not implemented for Real Field with 150 bits of precision
            sage: f._evalf_(1/2, 1/2, parent=int)
            Traceback (most recent call last):
            ...
            NotImplementedError: Maxima function jacobi_sn not implemented for <type 'int'>
            sage: f._evalf_(1/2, 1/2, parent=complex)
            (0.4707504736556572+0j)
            sage: f._evalf_(1/2, 1/2, parent=RDF)
            0.4707504736556572
            sage: f._evalf_(1, I, parent=CDF)  # abs tol 1e-16
            0.8483795707591759 - 0.07429247342160791*I
            sage: f._evalf_(1, I, parent=RR)
            Traceback (most recent call last):
            ...
            TypeError: Unable to convert x (='0.848379570759176-0.0742924734216079*I') to real number.
        """
        parent = kwds['parent']
        # The result from maxima is a machine double, which corresponds
        # to RDF (or CDF). Therefore, before converting, we check that
        # we can actually coerce RDF into our parent.
        if parent is not float and parent is not complex:
            if not isinstance(parent,
                              Parent) or not parent.has_coerce_map_from(RDF):
                raise NotImplementedError(
                    "Maxima function %s not implemented for %r" %
                    (self.name(), parent))
        _init()
        return parent(maxima("%s, numer" % self._maxima_init_evaled_(*args)))
コード例 #13
0
ファイル: special.py プロジェクト: manguluka/sage
    def _eval_(self, n, m, theta, phi, **kwargs):
        r"""
        TESTS::

            sage: x, y = var('x y')
            sage: spherical_harmonic(1, 2, x, y)
            0
            sage: spherical_harmonic(1, -2, x, y)
            0
            sage: spherical_harmonic(1/2, 2, x, y)
            spherical_harmonic(1/2, 2, x, y)
            sage: spherical_harmonic(3, 2, x, y)
            15/4*sqrt(7/30)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi)
            sage: spherical_harmonic(3, 2, 1, 2)
            15/4*sqrt(7/30)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi)
            sage: spherical_harmonic(3 + I, 2., 1, 2)
            -0.351154337307488 - 0.415562233975369*I
        """
        if n in ZZ and m in ZZ and n > -1:
            if abs(m) > n:
                return ZZ(0)
            return meval("spherical_harmonic({},{},{},{})".format(
                ZZ(n), ZZ(m), maxima(theta), maxima(phi)))
コード例 #14
0
ファイル: special.py プロジェクト: Babyll/sage
    def _evalf_(self, *args, **kwds):
        """
        Returns a numerical approximation of this function using
        Maxima.  Currently, this is limited to 53 bits of precision.

        EXAMPLES::

            sage: from sage.functions.special import MaximaFunction
            sage: f = MaximaFunction("jacobi_sn")
            sage: f(1/2, 1/2)
            jacobi_sn(1/2, 1/2)
            sage: f(1/2, 1/2).n()
            0.470750473655657
            sage: f(1/2, 1/2).n(20)
            0.47075
            sage: f(1, I).n()
            0.848379519751901 - 0.0742924572771414*I

        TESTS::

            sage: f(1/2, 1/2).n(150)
            Traceback (most recent call last):
            ...
            NotImplementedError: Maxima function jacobi_sn not implemented for Real Field with 150 bits of precision
            sage: f._evalf_(1/2, 1/2, parent=int)
            Traceback (most recent call last):
            ...
            NotImplementedError: Maxima function jacobi_sn not implemented for <type 'int'>
            sage: f._evalf_(1/2, 1/2, parent=complex)
            (0.4707504736556572+0j)
            sage: f._evalf_(1/2, 1/2, parent=RDF)
            0.4707504736556572
            sage: f._evalf_(1, I, parent=CDF)  # abs tol 1e-16
            0.8483795707591759 - 0.07429247342160791*I
            sage: f._evalf_(1, I, parent=RR)
            Traceback (most recent call last):
            ...
            TypeError: unable to convert '0.848379570759176-0.0742924734216079*I' to a real number
        """
        parent = kwds['parent']
        # The result from maxima is a machine double, which corresponds
        # to RDF (or CDF). Therefore, before converting, we check that
        # we can actually coerce RDF into our parent.
        if parent is not float and parent is not complex:
            if not isinstance(parent, Parent) or not parent.has_coerce_map_from(RDF):
                raise NotImplementedError("Maxima function %s not implemented for %r"%(self.name(), parent))
        _init()
        return parent(maxima("%s, numer"%self._maxima_init_evaled_(*args)))
コード例 #15
0
ファイル: special.py プロジェクト: matsen/sage
    def _eval_(self, *args):
        """
        Try to evaluate this function at ``*args``, return ``None`` if
        Maxima did not compute a numerical evaluation.

        EXAMPLES::

            sage: from sage.functions.special import MaximaFunction
            sage: f = MaximaFunction("jacobi_sn")
            sage: f(1,1)
            tanh(1)

            sage: f._eval_(1,1)
            tanh(1)

        Here arccoth doesn't have 1 in its domain, so we just hold the expression:

            sage: elliptic_e(arccoth(1), x^2*e)
            elliptic_e(arccoth(1), x^2*e)

        Since Maxima works only with double precision, numerical
        results are in ``RDF``, no matter what the input precision is::

            sage: R = RealField(300)
            sage: r = elliptic_eu(R(1/2), R(1/8)); r
            0.4950737320232015
            sage: parent(r)
            Real Double Field
        """
        _init()
        try:
            s = maxima(self._maxima_init_evaled_(*args))
        except TypeError:
            return None

        if self.name() in s.__repr__():  # Avoid infinite recursion
            return None
        else:
            return s.sage()
コード例 #16
0
def solve(f, *args, **kwds):
    r"""
    Algebraically solve an equation or system of equations (over the
    complex numbers) for given variables. Inequalities and systems
    of inequalities are also supported.

    INPUT:

    -  ``f`` - equation or system of equations (given by a
       list or tuple)

    -  ``*args`` - variables to solve for.

    -  ``solution_dict`` - bool (default: False); if True or non-zero,
       return a list of dictionaries containing the solutions. If there
       are no solutions, return an empty list (rather than a list containing
       an empty dictionary). Likewise, if there's only a single solution,
       return a list containing one dictionary with that solution.

    There are a few optional keywords if you are trying to solve a single
    equation.  They may only be used in that context.

    -  ``multiplicities`` - bool (default: False); if True,
       return corresponding multiplicities.  This keyword is
       incompatible with ``to_poly_solve=True`` and does not make
       any sense when solving inequalities.

    -  ``explicit_solutions`` - bool (default: False); require that
       all roots be explicit rather than implicit. Not used
       when solving inequalities.

    -  ``to_poly_solve`` - bool (default: False) or string; use
       Maxima's ``to_poly_solver`` package to search for more possible
       solutions, but possibly encounter approximate solutions.
       This keyword is incompatible with ``multiplicities=True``
       and is not used when solving inequalities. Setting ``to_poly_solve``
       to 'force' (string) omits Maxima's solve command (useful when
       some solutions of trigonometric equations are lost).


    EXAMPLES::

        sage: x, y = var('x, y')
        sage: solve([x+y==6, x-y==4], x, y)
        [[x == 5, y == 1]]
        sage: solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
        [[x == -1/2*I*sqrt(3) - 1/2, y == -sqrt(-1/2*I*sqrt(3) + 3/2)],
         [x == -1/2*I*sqrt(3) - 1/2, y == sqrt(-1/2*I*sqrt(3) + 3/2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == -sqrt(1/2*I*sqrt(3) + 3/2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == sqrt(1/2*I*sqrt(3) + 3/2)],
         [x == 0, y == -1],
         [x == 0, y == 1]]
        sage: solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
        [[x == -5/2*I*sqrt(5) + 5, y == 5/2*I*sqrt(5) + 5], [x == 5/2*I*sqrt(5) + 5, y == -5/2*I*sqrt(5) + 5]]
        sage: solutions=solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
        sage: for solution in solutions: print("{} , {}".format(solution[x].n(digits=3), solution[y].n(digits=3)))
        -0.500 - 0.866*I , -1.27 + 0.341*I
        -0.500 - 0.866*I , 1.27 - 0.341*I
        -0.500 + 0.866*I , -1.27 - 0.341*I
        -0.500 + 0.866*I , 1.27 + 0.341*I
        0.000 , -1.00
        0.000 , 1.00

    Whenever possible, answers will be symbolic, but with systems of
    equations, at times approximations will be given, due to the
    underlying algorithm in Maxima::

        sage: sols = solve([x^3==y,y^2==x],[x,y]); sols[-1], sols[0]
        ([x == 0, y == 0], [x == (0.3090169943749475 + 0.9510565162951535*I), y == (-0.8090169943749475 - 0.5877852522924731*I)])
        sage: sols[0][0].rhs().pyobject().parent()
        Complex Double Field

    If ``f`` is only one equation or expression, we use the solve method
    for symbolic expressions, which defaults to exact answers only::

        sage: solve([y^6==y],y)
        [y == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, y == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, y == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, y == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, y == 1, y == 0]
        sage: solve( [y^6 == y], y)==solve( y^6 == y, y)
        True

    Here we demonstrate very basic use of the optional keywords for
    a single expression to be solved::

        sage: ((x^2-1)^2).solve(x)
        [x == -1, x == 1]
        sage: ((x^2-1)^2).solve(x,multiplicities=True)
        ([x == -1, x == 1], [2, 2])
        sage: solve(sin(x)==x,x)
        [x == sin(x)]
        sage: solve(sin(x)==x,x,explicit_solutions=True)
        []
        sage: solve(abs(1-abs(1-x)) == 10, x)
        [abs(abs(x - 1) - 1) == 10]
        sage: solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
        [x == -10, x == 12]

    .. note::

        For more details about solving a single equation, see
        the documentation for the single-expression
        :meth:`~sage.symbolic.expression.Expression.solve`.

    ::

        sage: from sage.symbolic.expression import Expression
        sage: Expression.solve(x^2==1,x)
        [x == -1, x == 1]

    We must solve with respect to actual variables::

        sage: z = 5
        sage: solve([8*z + y == 3, -z +7*y == 0],y,z)
        Traceback (most recent call last):
        ...
        TypeError: 5 is not a valid variable.

    If we ask for dictionaries containing the solutions, we get them::

        sage: solve([x^2-1],x,solution_dict=True)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-4*x+4],x,solution_dict=True)
        [{x: 2}]
        sage: res = solve([x^2 == y, y == 4],x,y,solution_dict=True)
        sage: for soln in res: print("x: %s, y: %s" % (soln[x], soln[y]))
        x: 2, y: 4
        x: -2, y: 4

    If there is a parameter in the answer, that will show up as
    a new variable.  In the following example, ``r1`` is a real free
    variable (because of the ``r``)::

        sage: solve([x+y == 3, 2*x+2*y == 6],x,y)
        [[x == -r1 + 3, y == r1]]

    Especially with trigonometric functions, the dummy variable may
    be implicitly an integer (hence the ``z``)::

        sage: solve([cos(x)*sin(x) == 1/2, x+y == 0],x,y)
        [[x == 1/4*pi + pi*z79, y == -1/4*pi - pi*z79]]

    Expressions which are not equations are assumed to be set equal
    to zero, as with `x` in the following example::

        sage: solve([x, y == 2],x,y)
        [[x == 0, y == 2]]

    If ``True`` appears in the list of equations it is
    ignored, and if ``False`` appears in the list then no
    solutions are returned. E.g., note that the first
    ``3==3`` evaluates to ``True``, not to a
    symbolic equation.

    ::

        sage: solve([3==3, 1.00000000000000*x^3 == 0], x)
        [x == 0]
        sage: solve([1.00000000000000*x^3 == 0], x)
        [x == 0]

    Here, the first equation evaluates to ``False``, so
    there are no solutions::

        sage: solve([1==3, 1.00000000000000*x^3 == 0], x)
        []

    Completely symbolic solutions are supported::

        sage: var('s,j,b,m,g')
        (s, j, b, m, g)
        sage: sys = [ m*(1-s) - b*s*j, b*s*j-g*j ];
        sage: solve(sys,s,j)
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,(s,j))
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,[s,j])
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]

    Inequalities can be also solved::

        sage: solve(x^2>8,x)
        [[x < -2*sqrt(2)], [x > 2*sqrt(2)]]

    We use ``use_grobner`` in Maxima if no solution is obtained from
    Maxima's ``to_poly_solve``::

       sage: x,y=var('x y'); c1(x,y)=(x-5)^2+y^2-16; c2(x,y)=(y-3)^2+x^2-9
       sage: solve([c1(x,y),c2(x,y)],[x,y])
       [[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(55) + 123/68], [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(55) + 123/68]]

    TESTS::

        sage: solve([sin(x)==x,y^2==x],x,y)
        [sin(x) == x, y^2 == x]
        sage: solve(0==1,x)
        Traceback (most recent call last):
        ...
        TypeError:  The first argument must be a symbolic expression or a list of symbolic expressions.

    Test if the empty list is returned, too, when (a list of)
    dictionaries (is) are requested (:trac:`8553`)::

        sage: solve([SR(0)==1],x)
        []
        sage: solve([SR(0)==1],x,solution_dict=True)
        []
        sage: solve([x==1,x==-1],x)
        []
        sage: solve([x==1,x==-1],x,solution_dict=True)
        []
        sage: solve((x==1,x==-1),x,solution_dict=0)
        []

    Relaxed form, suggested by Mike Hansen (:trac:`8553`)::

        sage: solve([x^2-1],x,solution_dict=-1)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-1],x,solution_dict=1)
        [{x: -1}, {x: 1}]
        sage: solve((x==1,x==-1),x,solution_dict=-1)
        []
        sage: solve((x==1,x==-1),x,solution_dict=1)
        []

    This inequality holds for any real ``x`` (:trac:`8078`)::

        sage: solve(x^4+2>0,x)
        [x < +Infinity]

    Test for user friendly input handling :trac:`13645`::

        sage: poly.<a,b> = PolynomialRing(RR)
        sage: solve([a+b+a*b == 1], a)
        Traceback (most recent call last):
        ...
        TypeError: The first argument to solve() should be a symbolic expression or a list of symbolic expressions, cannot handle <... 'bool'>
        sage: solve([a, b], (1, a))
        Traceback (most recent call last):
        ...
        TypeError: 1 is not a valid variable.
        sage: solve([x == 1], (1, a))
        Traceback (most recent call last):
        ...
        TypeError: (1, a) are not valid variables.

    Test that the original version of a system in the French Sage book
    now works (:trac:`14306`)::

        sage: var('y,z')
        (y, z)
        sage: solve([x^2 * y * z == 18, x * y^3 * z == 24, x * y * z^4 == 6], x, y, z)
        [[x == 3, y == 2, z == 1], [x == (1.337215067... - 2.685489874...*I), y == (-1.700434271... + 1.052864325...*I), z == (0.9324722294... - 0.3612416661...*I)], ...]
    """
    from sage.symbolic.expression import is_Expression
    if is_Expression(f):  # f is a single expression
        ans = f.solve(*args, **kwds)
        return ans

    if not isinstance(f, (list, tuple)):
        raise TypeError(
            "The first argument must be a symbolic expression or a list of symbolic expressions."
        )

    if len(f) == 1:
        # f is a list with a single element
        if is_Expression(f[0]):
            # if its a symbolic expression call solve method of this expression
            return f[0].solve(*args, **kwds)
        # otherwise complain
        raise TypeError("The first argument to solve() should be a symbolic "
                        "expression or a list of symbolic expressions, "
                        "cannot handle %s" % repr(type(f[0])))

    # f is a list of such expressions or equations
    from sage.symbolic.ring import is_SymbolicVariable

    if len(args) == 0:
        raise TypeError("Please input variables to solve for.")
    if is_SymbolicVariable(args[0]):
        variables = args
    else:
        variables = tuple(args[0])

    for v in variables:
        if not is_SymbolicVariable(v):
            raise TypeError("%s is not a valid variable." % repr(v))

    try:
        f = [s for s in f if s is not True]
    except TypeError:
        raise ValueError("Unable to solve %s for %s" % (f, args))

    if any(s is False for s in f):
        return []

    from sage.calculus.calculus import maxima
    m = maxima(f)

    try:
        s = m.solve(variables)
    except Exception:  # if Maxima gave an error, try its to_poly_solve
        try:
            s = m.to_poly_solve(variables)
        except TypeError as mess:  # if that gives an error, raise an error.
            if "Error executing code in Maxima" in str(mess):
                raise ValueError(
                    "Sage is unable to determine whether the system %s can be solved for %s"
                    % (f, args))
            else:
                raise

    if len(
            s
    ) == 0:  # if Maxima's solve gave no solutions, try its to_poly_solve
        try:
            s = m.to_poly_solve(variables)
        except Exception:  # if that gives an error, stick with no solutions
            s = []

    if len(s) == 0:  # if to_poly_solve gave no solutions, try use_grobner
        try:
            s = m.to_poly_solve(variables, 'use_grobner=true')
        except Exception:  # if that gives an error, stick with no solutions
            s = []

    sol_list = string_to_list_of_solutions(repr(s))

    # Relaxed form suggested by Mike Hansen (#8553):
    if kwds.get('solution_dict', False):
        if len(sol_list
               ) == 0:  # fixes IndexError on empty solution list (#8553)
            return []
        if isinstance(sol_list[0], list):
            sol_dict = [
                dict([[eq.left(), eq.right()] for eq in solution])
                for solution in sol_list
            ]
        else:
            sol_dict = [{eq.left(): eq.right()} for eq in sol_list]

        return sol_dict
    else:
        return sol_list
コード例 #17
0
def solve(f, *args, **kwds):
    r"""
    Algebraically solve an equation or system of equations (over the
    complex numbers) for given variables. Inequalities and systems 
    of inequalities are also supported.    
    
    INPUT:
    
    -  ``f`` - equation or system of equations (given by a
       list or tuple)
    
    -  ``*args`` - variables to solve for.
    
    -  ``solution_dict`` - bool (default: False); if True or non-zero, 
       return a list of dictionaries containing the solutions. If there
       are no solutions, return an empty list (rather than a list containing
       an empty dictionary). Likewise, if there's only a single solution,
       return a list containing one dictionary with that solution.
    
    EXAMPLES::
    
        sage: x, y = var('x, y')
        sage: solve([x+y==6, x-y==4], x, y)
        [[x == 5, y == 1]]
        sage: solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
        [[x == -1/2*I*sqrt(3) - 1/2, y == -1/2*sqrt(-I*sqrt(3) + 3)*sqrt(2)],
         [x == -1/2*I*sqrt(3) - 1/2, y == 1/2*sqrt(-I*sqrt(3) + 3)*sqrt(2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == -1/2*sqrt(I*sqrt(3) + 3)*sqrt(2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == 1/2*sqrt(I*sqrt(3) + 3)*sqrt(2)],
         [x == 0, y == -1],
         [x == 0, y == 1]]
        sage: solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
        [[x == -5/2*I*sqrt(5) + 5, y == 5/2*I*sqrt(5) + 5], [x == 5/2*I*sqrt(5) + 5, y == -5/2*I*sqrt(5) + 5]]
        sage: solutions=solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
        sage: for solution in solutions: print solution[x].n(digits=3), ",", solution[y].n(digits=3)
        -0.500 - 0.866*I , -1.27 + 0.341*I
        -0.500 - 0.866*I , 1.27 - 0.341*I
        -0.500 + 0.866*I , -1.27 - 0.341*I
        -0.500 + 0.866*I , 1.27 + 0.341*I
        0.000 , -1.00
        0.000 , 1.00

    Whenever possible, answers will be symbolic, but with systems of 
    equations, at times approximations will be given, due to the 
    underlying algorithm in Maxima::

        sage: sols = solve([x^3==y,y^2==x],[x,y]); sols[-1], sols[0]
        ([x == 0, y == 0], [x == (0.309016994375 + 0.951056516295*I),  y == (-0.809016994375 - 0.587785252292*I)])
        sage: sols[0][0].rhs().pyobject().parent()
        Complex Double Field

    If ``f`` is only one equation or expression, we use the solve method
    for symbolic expressions, which defaults to exact answers only::

        sage: solve([y^6==y],y)
        [y == e^(2/5*I*pi), y == e^(4/5*I*pi), y == e^(-4/5*I*pi), y == e^(-2/5*I*pi), y == 1, y == 0]
        sage: solve( [y^6 == y], y)==solve( y^6 == y, y)
        True

    .. note::

        For more details about solving a single equations, see
        the documentation for its solve.

    ::

        sage: from sage.symbolic.expression import Expression
        sage: Expression.solve(x^2==1,x)
        [x == -1, x == 1]

    We must solve with respect to actual variables::

        sage: z = 5
        sage: solve([8*z + y == 3, -z +7*y == 0],y,z)
        Traceback (most recent call last):
        ...
        TypeError: 5 is not a valid variable.

    If we ask for dictionaries containing the solutions, we get them::
    
        sage: solve([x^2-1],x,solution_dict=True)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-4*x+4],x,solution_dict=True)
        [{x: 2}]
        sage: res = solve([x^2 == y, y == 4],x,y,solution_dict=True)
        sage: for soln in res: print "x: %s, y: %s"%(soln[x], soln[y])
        x: 2, y: 4
        x: -2, y: 4

    If there is a parameter in the answer, that will show up as 
    a new variable.  In the following example, ``r1`` is a real free
    variable (because of the ``r``)::

        sage: solve([x+y == 3, 2*x+2*y == 6],x,y)
        [[x == -r1 + 3, y == r1]]

    Especially with trigonometric functions, the dummy variable may
    be implicitly an integer (hence the ``z``)::

        sage: solve([cos(x)*sin(x) == 1/2, x+y == 0],x,y)
        [[x == 1/4*pi + pi*z68, y == -1/4*pi - pi*z68]]

    Expressions which are not equations are assumed to be set equal
    to zero, as with `x` in the following example::

        sage: solve([x, y == 2],x,y)
        [[x == 0, y == 2]]

    If ``True`` appears in the list of equations it is
    ignored, and if ``False`` appears in the list then no
    solutions are returned. E.g., note that the first
    ``3==3`` evaluates to ``True``, not to a
    symbolic equation.
    
    ::
    
        sage: solve([3==3, 1.00000000000000*x^3 == 0], x)
        [x == 0]
        sage: solve([1.00000000000000*x^3 == 0], x)
        [x == 0]
    
    Here, the first equation evaluates to ``False``, so
    there are no solutions::
    
        sage: solve([1==3, 1.00000000000000*x^3 == 0], x)
        []
    
    Completely symbolic solutions are supported::
    
        sage: var('s,j,b,m,g')
        (s, j, b, m, g)
        sage: sys = [ m*(1-s) - b*s*j, b*s*j-g*j ];
        sage: solve(sys,s,j)
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,(s,j))
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,[s,j])
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]

    Inequalities can be also solved::

        sage: solve(x^2>8,x)
        [[x < -2*sqrt(2)], [x > 2*sqrt(2)]]

    Use use_grobner if no solution is obtained from to_poly_solve::

       sage: x,y=var('x y'); c1(x,y)=(x-5)^2+y^2-16; c2(x,y)=(y-3)^2+x^2-9
       sage: solve([c1(x,y),c2(x,y)],[x,y])                               
       [[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(5)*sqrt(11) + 123/68], [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(5)*sqrt(11) + 123/68]]
        
    TESTS::

        sage: solve([sin(x)==x,y^2==x],x,y)
        [sin(x) == x, y^2 == x]
        sage: solve(0==1,x)
        Traceback (most recent call last):
        ...
        TypeError:  The first argument must be a symbolic expression or a list of symbolic expressions.

    Test if the empty list is returned, too, when (a list of)
    dictionaries (is) are requested (#8553)::

        sage: solve([0==1],x)
        []
        sage: solve([0==1],x,solution_dict=True)
        []
        sage: solve([x==1,x==-1],x)
        []
        sage: solve([x==1,x==-1],x,solution_dict=True)
        []
        sage: solve((x==1,x==-1),x,solution_dict=0)
        []

    Relaxed form, suggested by Mike Hansen (#8553)::

        sage: solve([x^2-1],x,solution_dict=-1)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-1],x,solution_dict=1)
        [{x: -1}, {x: 1}]
        sage: solve((x==1,x==-1),x,solution_dict=-1)
        []
        sage: solve((x==1,x==-1),x,solution_dict=1)
        []

    This inequality holds for any real ``x`` (trac #8078)::

        sage: solve(x^4+2>0,x)
        [x < +Infinity]

    """
    from sage.symbolic.expression import is_Expression
    if is_Expression(f):  # f is a single expression
        ans = f.solve(*args, **kwds)
        return ans

    if not isinstance(f, (list, tuple)):
        raise TypeError(
            "The first argument must be a symbolic expression or a list of symbolic expressions."
        )

    if len(f) == 1 and is_Expression(f[0]):
        # f is a list with a single expression
        return f[0].solve(*args, **kwds)

    # f is a list of such expressions or equations
    from sage.symbolic.ring import is_SymbolicVariable

    if len(args) == 0:
        raise TypeError, "Please input variables to solve for."
    if is_SymbolicVariable(args[0]):
        variables = args
    else:
        variables = tuple(args[0])

    for v in variables:
        if not is_SymbolicVariable(v):
            raise TypeError, "%s is not a valid variable." % v

    try:
        f = [s for s in f if s is not True]
    except TypeError:
        raise ValueError, "Unable to solve %s for %s" % (f, args)

    if any(s is False for s in f):
        return []

    from sage.calculus.calculus import maxima
    m = maxima(f)

    try:
        s = m.solve(variables)
    except:  # if Maxima gave an error, try its to_poly_solve
        try:
            s = m.to_poly_solve(variables)
        except TypeError, mess:  # if that gives an error, raise an error.
            if "Error executing code in Maxima" in str(mess):
                raise ValueError, "Sage is unable to determine whether the system %s can be solved for %s" % (
                    f, args)
            else:
                raise
コード例 #18
0
ファイル: relation.py プロジェクト: novoselt/sage
def solve(f, *args, **kwds):
    r"""
    Algebraically solve an equation or system of equations (over the
    complex numbers) for given variables. Inequalities and systems
    of inequalities are also supported.

    INPUT:

    -  ``f`` - equation or system of equations (given by a
       list or tuple)

    -  ``*args`` - variables to solve for.

    -  ``solution_dict`` - bool (default: False); if True or non-zero,
       return a list of dictionaries containing the solutions. If there
       are no solutions, return an empty list (rather than a list containing
       an empty dictionary). Likewise, if there's only a single solution,
       return a list containing one dictionary with that solution.

    There are a few optional keywords if you are trying to solve a single
    equation.  They may only be used in that context.

    -  ``multiplicities`` - bool (default: False); if True,
       return corresponding multiplicities.  This keyword is
       incompatible with ``to_poly_solve=True`` and does not make
       any sense when solving inequalities.

    -  ``explicit_solutions`` - bool (default: False); require that
       all roots be explicit rather than implicit. Not used
       when solving inequalities.

    -  ``to_poly_solve`` - bool (default: False) or string; use
       Maxima's ``to_poly_solver`` package to search for more possible
       solutions, but possibly encounter approximate solutions.
       This keyword is incompatible with ``multiplicities=True``
       and is not used when solving inequalities. Setting ``to_poly_solve``
       to 'force' (string) omits Maxima's solve command (useful when
       some solutions of trigonometric equations are lost).


    EXAMPLES::

        sage: x, y = var('x, y')
        sage: solve([x+y==6, x-y==4], x, y)
        [[x == 5, y == 1]]
        sage: solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
        [[x == -1/2*I*sqrt(3) - 1/2, y == -sqrt(-1/2*I*sqrt(3) + 3/2)],
         [x == -1/2*I*sqrt(3) - 1/2, y == sqrt(-1/2*I*sqrt(3) + 3/2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == -sqrt(1/2*I*sqrt(3) + 3/2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == sqrt(1/2*I*sqrt(3) + 3/2)],
         [x == 0, y == -1],
         [x == 0, y == 1]]
        sage: solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
        [[x == -5/2*I*sqrt(5) + 5, y == 5/2*I*sqrt(5) + 5], [x == 5/2*I*sqrt(5) + 5, y == -5/2*I*sqrt(5) + 5]]
        sage: solutions=solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
        sage: for solution in solutions: print("{} , {}".format(solution[x].n(digits=3), solution[y].n(digits=3)))
        -0.500 - 0.866*I , -1.27 + 0.341*I
        -0.500 - 0.866*I , 1.27 - 0.341*I
        -0.500 + 0.866*I , -1.27 - 0.341*I
        -0.500 + 0.866*I , 1.27 + 0.341*I
        0.000 , -1.00
        0.000 , 1.00

    Whenever possible, answers will be symbolic, but with systems of
    equations, at times approximations will be given, due to the
    underlying algorithm in Maxima::

        sage: sols = solve([x^3==y,y^2==x],[x,y]); sols[-1], sols[0]
        ([x == 0, y == 0], [x == (0.3090169943749475 + 0.9510565162951535*I), y == (-0.8090169943749475 - 0.5877852522924731*I)])
        sage: sols[0][0].rhs().pyobject().parent()
        Complex Double Field

    If ``f`` is only one equation or expression, we use the solve method
    for symbolic expressions, which defaults to exact answers only::

        sage: solve([y^6==y],y)
        [y == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, y == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, y == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, y == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, y == 1, y == 0]
        sage: solve( [y^6 == y], y)==solve( y^6 == y, y)
        True

    Here we demonstrate very basic use of the optional keywords for
    a single expression to be solved::

        sage: ((x^2-1)^2).solve(x)
        [x == -1, x == 1]
        sage: ((x^2-1)^2).solve(x,multiplicities=True)
        ([x == -1, x == 1], [2, 2])
        sage: solve(sin(x)==x,x)
        [x == sin(x)]
        sage: solve(sin(x)==x,x,explicit_solutions=True)
        []
        sage: solve(abs(1-abs(1-x)) == 10, x)
        [abs(abs(x - 1) - 1) == 10]
        sage: solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
        [x == -10, x == 12]

    .. note::

        For more details about solving a single equation, see
        the documentation for the single-expression
        :meth:`~sage.symbolic.expression.Expression.solve`.

    ::

        sage: from sage.symbolic.expression import Expression
        sage: Expression.solve(x^2==1,x)
        [x == -1, x == 1]

    We must solve with respect to actual variables::

        sage: z = 5
        sage: solve([8*z + y == 3, -z +7*y == 0],y,z)
        Traceback (most recent call last):
        ...
        TypeError: 5 is not a valid variable.

    If we ask for dictionaries containing the solutions, we get them::

        sage: solve([x^2-1],x,solution_dict=True)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-4*x+4],x,solution_dict=True)
        [{x: 2}]
        sage: res = solve([x^2 == y, y == 4],x,y,solution_dict=True)
        sage: for soln in res: print("x: %s, y: %s" % (soln[x], soln[y]))
        x: 2, y: 4
        x: -2, y: 4

    If there is a parameter in the answer, that will show up as
    a new variable.  In the following example, ``r1`` is a real free
    variable (because of the ``r``)::

        sage: solve([x+y == 3, 2*x+2*y == 6],x,y)
        [[x == -r1 + 3, y == r1]]

    Especially with trigonometric functions, the dummy variable may
    be implicitly an integer (hence the ``z``)::

        sage: solve([cos(x)*sin(x) == 1/2, x+y == 0],x,y)
        [[x == 1/4*pi + pi*z79, y == -1/4*pi - pi*z79]]

    Expressions which are not equations are assumed to be set equal
    to zero, as with `x` in the following example::

        sage: solve([x, y == 2],x,y)
        [[x == 0, y == 2]]

    If ``True`` appears in the list of equations it is
    ignored, and if ``False`` appears in the list then no
    solutions are returned. E.g., note that the first
    ``3==3`` evaluates to ``True``, not to a
    symbolic equation.

    ::

        sage: solve([3==3, 1.00000000000000*x^3 == 0], x)
        [x == 0]
        sage: solve([1.00000000000000*x^3 == 0], x)
        [x == 0]

    Here, the first equation evaluates to ``False``, so
    there are no solutions::

        sage: solve([1==3, 1.00000000000000*x^3 == 0], x)
        []

    Completely symbolic solutions are supported::

        sage: var('s,j,b,m,g')
        (s, j, b, m, g)
        sage: sys = [ m*(1-s) - b*s*j, b*s*j-g*j ];
        sage: solve(sys,s,j)
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,(s,j))
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,[s,j])
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]

    Inequalities can be also solved::

        sage: solve(x^2>8,x)
        [[x < -2*sqrt(2)], [x > 2*sqrt(2)]]

    We use ``use_grobner`` in Maxima if no solution is obtained from
    Maxima's ``to_poly_solve``::

       sage: x,y=var('x y'); c1(x,y)=(x-5)^2+y^2-16; c2(x,y)=(y-3)^2+x^2-9
       sage: solve([c1(x,y),c2(x,y)],[x,y])
       [[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(11)*sqrt(5) + 123/68], [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(11)*sqrt(5) + 123/68]]

    TESTS::

        sage: solve([sin(x)==x,y^2==x],x,y)
        [sin(x) == x, y^2 == x]
        sage: solve(0==1,x)
        Traceback (most recent call last):
        ...
        TypeError:  The first argument must be a symbolic expression or a list of symbolic expressions.

    Test if the empty list is returned, too, when (a list of)
    dictionaries (is) are requested (#8553)::

        sage: solve([SR(0)==1],x)
        []
        sage: solve([SR(0)==1],x,solution_dict=True)
        []
        sage: solve([x==1,x==-1],x)
        []
        sage: solve([x==1,x==-1],x,solution_dict=True)
        []
        sage: solve((x==1,x==-1),x,solution_dict=0)
        []

    Relaxed form, suggested by Mike Hansen (#8553)::

        sage: solve([x^2-1],x,solution_dict=-1)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-1],x,solution_dict=1)
        [{x: -1}, {x: 1}]
        sage: solve((x==1,x==-1),x,solution_dict=-1)
        []
        sage: solve((x==1,x==-1),x,solution_dict=1)
        []

    This inequality holds for any real ``x`` (:trac:`8078`)::

        sage: solve(x^4+2>0,x)
        [x < +Infinity]

    Test for user friendly input handling :trac:`13645`::

        sage: poly.<a,b> = PolynomialRing(RR)
        sage: solve([a+b+a*b == 1], a)
        Traceback (most recent call last):
        ...
        TypeError: The first argument to solve() should be a symbolic expression or a list of symbolic expressions, cannot handle <type 'bool'>
        sage: solve([a, b], (1, a))
        Traceback (most recent call last):
        ...
        TypeError: 1 is not a valid variable.
        sage: solve([x == 1], (1, a))
        Traceback (most recent call last):
        ...
        TypeError: (1, a) are not valid variables.

    Test that the original version of a system in the French Sage book
    now works (:trac:`14306`)::

        sage: var('y,z')
        (y, z)
        sage: solve([x^2 * y * z == 18, x * y^3 * z == 24, x * y * z^4 == 6], x, y, z)
        [[x == 3, y == 2, z == 1], [x == (1.337215067... - 2.685489874...*I), y == (-1.700434271... + 1.052864325...*I), z == (0.9324722294... - 0.3612416661...*I)], ...]
    """
    from sage.symbolic.expression import is_Expression
    if is_Expression(f): # f is a single expression
        ans = f.solve(*args,**kwds)
        return ans

    if not isinstance(f, (list, tuple)):
        raise TypeError("The first argument must be a symbolic expression or a list of symbolic expressions.")

    if len(f)==1:
        # f is a list with a single element
        if is_Expression(f[0]):
            # if its a symbolic expression call solve method of this expression
            return f[0].solve(*args,**kwds)
        # otherwise complain
        raise TypeError("The first argument to solve() should be a symbolic "
                        "expression or a list of symbolic expressions, "
                        "cannot handle %s"%repr(type(f[0])))

    # f is a list of such expressions or equations
    from sage.symbolic.ring import is_SymbolicVariable

    if len(args)==0:
        raise TypeError("Please input variables to solve for.")
    if is_SymbolicVariable(args[0]):
        variables = args
    else:
        variables = tuple(args[0])

    for v in variables:
        if not is_SymbolicVariable(v):
            raise TypeError("%s is not a valid variable."%repr(v))

    try:
        f = [s for s in f if s is not True]
    except TypeError:
        raise ValueError("Unable to solve %s for %s"%(f, args))

    if any(s is False for s in f):
        return []

    from sage.calculus.calculus import maxima
    m = maxima(f)

    try:
        s = m.solve(variables)
    except Exception: # if Maxima gave an error, try its to_poly_solve
        try:
            s = m.to_poly_solve(variables)
        except TypeError as mess: # if that gives an error, raise an error.
            if "Error executing code in Maxima" in str(mess):
                raise ValueError("Sage is unable to determine whether the system %s can be solved for %s"%(f,args))
            else:
                raise

    if len(s)==0: # if Maxima's solve gave no solutions, try its to_poly_solve
        try:
            s = m.to_poly_solve(variables)
        except Exception: # if that gives an error, stick with no solutions
            s = []

    if len(s)==0: # if to_poly_solve gave no solutions, try use_grobner
        try:
            s = m.to_poly_solve(variables,'use_grobner=true')
        except Exception: # if that gives an error, stick with no solutions
            s = []

    sol_list = string_to_list_of_solutions(repr(s))

    # Relaxed form suggested by Mike Hansen (#8553):
    if kwds.get('solution_dict', False):
        if len(sol_list)==0: # fixes IndexError on empty solution list (#8553)
            return []
        if isinstance(sol_list[0], list):
            sol_dict=[dict([[eq.left(),eq.right()] for eq in solution])
                    for solution in sol_list]
        else:
            sol_dict=[{eq.left():eq.right()} for eq in sol_list]

        return sol_dict
    else:
        return sol_list
コード例 #19
0
ファイル: relation.py プロジェクト: jtmurphy89/sagelib
def solve(f, *args, **kwds):
    r"""
    Algebraically solve an equation or system of equations (over the
    complex numbers) for given variables. Inequalities and systems 
    of inequalities are also supported.    
    
    INPUT:
    
    -  ``f`` - equation or system of equations (given by a
       list or tuple)
    
    -  ``*args`` - variables to solve for.
    
    -  ``solution_dict`` - bool (default: False); if True or non-zero, 
       return a list of dictionaries containing the solutions. If there
       are no solutions, return an empty list (rather than a list containing
       an empty dictionary). Likewise, if there's only a single solution,
       return a list containing one dictionary with that solution.
    
    EXAMPLES::
    
        sage: x, y = var('x, y')
        sage: solve([x+y==6, x-y==4], x, y)
        [[x == 5, y == 1]]
        sage: solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
        [[x == -1/2*I*sqrt(3) - 1/2, y == -sqrt(-1/2*I*sqrt(3) + 3/2)],
         [x == -1/2*I*sqrt(3) - 1/2, y == sqrt(-1/2*I*sqrt(3) + 3/2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == -sqrt(1/2*I*sqrt(3) + 3/2)],
         [x == 1/2*I*sqrt(3) - 1/2, y == sqrt(1/2*I*sqrt(3) + 3/2)],
         [x == 0, y == -1],
         [x == 0, y == 1]]
        sage: solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
        [[x == -5/2*I*sqrt(5) + 5, y == 5/2*I*sqrt(5) + 5], [x == 5/2*I*sqrt(5) + 5, y == -5/2*I*sqrt(5) + 5]]
        sage: solutions=solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
        sage: for solution in solutions: print solution[x].n(digits=3), ",", solution[y].n(digits=3)
        -0.500 - 0.866*I , -1.27 + 0.341*I
        -0.500 - 0.866*I , 1.27 - 0.341*I
        -0.500 + 0.866*I , -1.27 - 0.341*I
        -0.500 + 0.866*I , 1.27 + 0.341*I
        0.000 , -1.00
        0.000 , 1.00

    Whenever possible, answers will be symbolic, but with systems of 
    equations, at times approximations will be given, due to the 
    underlying algorithm in Maxima::

        sage: sols = solve([x^3==y,y^2==x],[x,y]); sols[-1], sols[0]
        ([x == 0, y == 0], [x == (0.309016994375 + 0.951056516295*I),  y == (-0.809016994375 - 0.587785252292*I)])
        sage: sols[0][0].rhs().pyobject().parent()
        Complex Double Field

    If ``f`` is only one equation or expression, we use the solve method
    for symbolic expressions, which defaults to exact answers only::

        sage: solve([y^6==y],y)
        [y == e^(2/5*I*pi), y == e^(4/5*I*pi), y == e^(-4/5*I*pi), y == e^(-2/5*I*pi), y == 1, y == 0]
        sage: solve( [y^6 == y], y)==solve( y^6 == y, y)
        True

    .. note::

        For more details about solving a single equations, see
        the documentation for its solve.

    ::

        sage: from sage.symbolic.expression import Expression
        sage: Expression.solve(x^2==1,x)
        [x == -1, x == 1]

    We must solve with respect to actual variables::

        sage: z = 5
        sage: solve([8*z + y == 3, -z +7*y == 0],y,z)
        Traceback (most recent call last):
        ...
        TypeError: 5 is not a valid variable.

    If we ask for dictionaries containing the solutions, we get them::
    
        sage: solve([x^2-1],x,solution_dict=True)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-4*x+4],x,solution_dict=True)
        [{x: 2}]
        sage: res = solve([x^2 == y, y == 4],x,y,solution_dict=True)
        sage: for soln in res: print "x: %s, y: %s"%(soln[x], soln[y])
        x: 2, y: 4
        x: -2, y: 4

    If there is a parameter in the answer, that will show up as 
    a new variable.  In the following example, ``r1`` is a real free
    variable (because of the ``r``)::

        sage: solve([x+y == 3, 2*x+2*y == 6],x,y)
        [[x == -r1 + 3, y == r1]]

    Especially with trigonometric functions, the dummy variable may
    be implicitly an integer (hence the ``z``)::

        sage: solve([cos(x)*sin(x) == 1/2, x+y == 0],x,y)
        [[x == 1/4*pi + pi*z68, y == -1/4*pi - pi*z68]]

    Expressions which are not equations are assumed to be set equal
    to zero, as with `x` in the following example::

        sage: solve([x, y == 2],x,y)
        [[x == 0, y == 2]]

    If ``True`` appears in the list of equations it is
    ignored, and if ``False`` appears in the list then no
    solutions are returned. E.g., note that the first
    ``3==3`` evaluates to ``True``, not to a
    symbolic equation.
    
    ::
    
        sage: solve([3==3, 1.00000000000000*x^3 == 0], x)
        [x == 0]
        sage: solve([1.00000000000000*x^3 == 0], x)
        [x == 0]
    
    Here, the first equation evaluates to ``False``, so
    there are no solutions::
    
        sage: solve([1==3, 1.00000000000000*x^3 == 0], x)
        []
    
    Completely symbolic solutions are supported::
    
        sage: var('s,j,b,m,g')
        (s, j, b, m, g)
        sage: sys = [ m*(1-s) - b*s*j, b*s*j-g*j ];
        sage: solve(sys,s,j)
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,(s,j))
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
        sage: solve(sys,[s,j])
        [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]

    Inequalities can be also solved::

        sage: solve(x^2>8,x)
        [[x < -2*sqrt(2)], [x > 2*sqrt(2)]]

    Use use_grobner if no solution is obtained from to_poly_solve::

       sage: x,y=var('x y'); c1(x,y)=(x-5)^2+y^2-16; c2(x,y)=(y-3)^2+x^2-9
       sage: solve([c1(x,y),c2(x,y)],[x,y])                               
       [[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(5)*sqrt(11) + 123/68], [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(5)*sqrt(11) + 123/68]]
        
    TESTS::

        sage: solve([sin(x)==x,y^2==x],x,y)
        [sin(x) == x, y^2 == x]
        sage: solve(0==1,x)
        Traceback (most recent call last):
        ...
        TypeError:  The first argument must be a symbolic expression or a list of symbolic expressions.

    Test if the empty list is returned, too, when (a list of)
    dictionaries (is) are requested (#8553)::

        sage: solve([0==1],x)
        []
        sage: solve([0==1],x,solution_dict=True)
        []
        sage: solve([x==1,x==-1],x)
        []
        sage: solve([x==1,x==-1],x,solution_dict=True)
        []
        sage: solve((x==1,x==-1),x,solution_dict=0)
        []

    Relaxed form, suggested by Mike Hansen (#8553)::

        sage: solve([x^2-1],x,solution_dict=-1)
        [{x: -1}, {x: 1}]
        sage: solve([x^2-1],x,solution_dict=1)
        [{x: -1}, {x: 1}]
        sage: solve((x==1,x==-1),x,solution_dict=-1)
        []
        sage: solve((x==1,x==-1),x,solution_dict=1)
        []

    This inequality holds for any real ``x`` (trac #8078)::

        sage: solve(x^4+2>0,x)
        [x < +Infinity]

    """
    from sage.symbolic.expression import is_Expression
    if is_Expression(f): # f is a single expression
        ans = f.solve(*args,**kwds)
        return ans

    if not isinstance(f, (list, tuple)):
        raise TypeError("The first argument must be a symbolic expression or a list of symbolic expressions.")

    if len(f)==1 and is_Expression(f[0]):
        # f is a list with a single expression
        return f[0].solve(*args,**kwds)

    # f is a list of such expressions or equations
    from sage.symbolic.ring import is_SymbolicVariable

    if len(args)==0:
        raise TypeError, "Please input variables to solve for."
    if is_SymbolicVariable(args[0]):
        variables = args
    else:
        variables = tuple(args[0])
    
    for v in variables:
        if not is_SymbolicVariable(v):
            raise TypeError, "%s is not a valid variable."%v

    try:
        f = [s for s in f if s is not True]
    except TypeError:
        raise ValueError, "Unable to solve %s for %s"%(f, args)

    if any(s is False for s in f):
        return []

    from sage.calculus.calculus import maxima
    m = maxima(f)

    try:
        s = m.solve(variables)
    except: # if Maxima gave an error, try its to_poly_solve
        try:
            s = m.to_poly_solve(variables)
        except TypeError, mess: # if that gives an error, raise an error.
            if "Error executing code in Maxima" in str(mess):
                raise ValueError, "Sage is unable to determine whether the system %s can be solved for %s"%(f,args)
            else:
                raise