Ticket #1189: sympy2.patch

File sympy2.patch, 4.7 KB (added by certik, 3 years ago)
  • sage/calculus/calculus.py

    # HG changeset patch
    # User Ondrej Certik <ondrej@certik.cz>
    # Date 1196036139 28800
    # Node ID d902e2401fc6b05795605a4c98f38c36c80a4d1d
    # Parent  59c0c1153bbe0cd5172cdc45e8ffb07d902d12f4
    SymPy and SAGE objects can now be mixed
    
    diff -r 59c0c1153bbe -r d902e2401fc6 sage/calculus/calculus.py
    a b  
    363363            sage: x.subs(x=y0/y1) 
    364364            y0/y1 
    365365        """ 
     366        import sympy 
    366367        if isinstance(x, CallableSymbolicExpression): 
    367368            return x._expr 
    368369        elif isinstance(x, SymbolicExpression): 
    369370            return x 
    370371        elif isinstance(x, MaximaElement): 
    371372            return symbolic_expression_from_maxima_element(x) 
     373        elif isinstance(x, sympy.Basic): 
     374        #elif hasattr(x, "_sage_"): 
     375            # if "x" implements the _sage_() method, let's use it to convert 
     376            # the expression to a SAGE expression (for example SymPy provides 
     377            # _sage_() methods, some other libraries can too) 
     378            # 
     379            # unfortunately, the hasattr() above doesn't work (infinite 
     380            # recursion), so we check for SymPy directly. 
     381 
     382            return self(x._sage_()) 
    372383        elif is_Polynomial(x) or is_MPolynomial(x): 
    373384            if x.base_ring() != self:  # would want coercion to go the other way 
    374385                return SymbolicPolynomial(x) 
     
    32713282                             infixops[self._operator], 
    32723283                             ops[1]._maxima_init_()) 
    32733284 
     3285    def _sympy_(self): 
     3286        """Converts any expression to SymPy.""" 
     3287 
     3288        # Current implementation is fragile - it first converts the expression 
     3289        # to string, then preparses it, then gets rid of "Integer" and then 
     3290        # sympifies this string. 
     3291 
     3292        # In order to make this robust, one would have to implement _sympy_ 
     3293        # recursively in all expressions. But we want something now, instead of 
     3294        # tomorrow, so the following one-liner does the job for now. 
     3295        # Also all ugly things are concentrated in this line, everything else 
     3296        # (sympy.sympify, sage.all.SR, ...) is clean and robust. 
     3297        import sympy 
     3298        from sage.all import preparse 
     3299        s = sympy.sympify(preparse(repr(self)).replace("Integer","")) 
     3300        return s 
     3301 
    32743302    def _sys_init_(self, system): 
    32753303        ops = self._operands 
    32763304        if self._operator is operator.neg: 
  • sage/calculus/test_sympy.py

    diff -r 59c0c1153bbe -r d902e2401fc6 sage/calculus/test_sympy.py
    a b  
    123123sage: f._sage_() 
    1241248651*x^8/13440 + 241*x^6/240 + 11*x^4/8 + 3*x^2/2 + 1 
    125125 
     126 
     127 
     128Mixing SymPy with SAGE: 
     129sage: import sympy 
     130sage: sympy.sympify(var("y"))+sympy.Symbol("x") 
     131x + y 
     132sage: o = var("omega") 
     133sage: s = sympy.Symbol("x") 
     134sage: t1 = s + o 
     135sage: t2 = o + s 
     136sage: print type(t1) 
     137<class 'sympy.core.add.Add'> 
     138sage: print type(t2) 
     139<class 'sage.calculus.calculus.SymbolicArithmetic'> 
     140sage: print t1, t2 
     141omega + x                                    x + omega 
     142sage: e=sympy.sin(var("y"))+sage.all.cos(Symbol("x")) 
     143sage: print type(e) 
     144<class 'sympy.core.add.Add'> 
     145sage: print e 
     146cos(x) + sin(y) 
     147sage: e=e._sage_() 
     148sage: print type(e) 
     149<class 'sage.calculus.calculus.SymbolicArithmetic'> 
     150sage: print e 
     151                                sin(y) + cos(x) 
     152sage: e = sage.all.cos(var("y")**3)**4+var("x")**2 
     153sage: e = e._sympy_() 
     154sage: print e 
     155    x**2 + cos(y**3)**4 
    126156""" 
  • sage/structure/coerce.pyx

    diff -r 59c0c1153bbe -r d902e2401fc6 sage/structure/coerce.pyx
    a b  
    327327                return x, y             
    328328            return _verify_canonical_coercion_c(x,y) 
    329329             
     330        if PY_TYPE_CHECK(xp, type) or PY_TYPE_CHECK(yp, type): 
     331            if hasattr(x, "_sage_") and hasattr(y, "_sage_"): 
     332                x = x._sage_() 
     333                y = y._sage_() 
     334                try: 
     335                    return _verify_canonical_coercion_c(x,y) 
     336                except RuntimeError: 
     337                    # well, the coercion failed or there is some other error, 
     338                    # and we should leave it as is (errors should never pass 
     339                    # silently, unless explicitly silenced), but SAGE needs to 
     340                    # return a TypeError, raised below, so we silence it... 
     341                    pass 
     342 
    330343        raise TypeError, "no common canonical parent for objects with parents: '%s' and '%s'"%(xp, yp) 
    331344         
    332345