Ticket #7661: trac_7661-maxima_convert_back.patch
File trac_7661-maxima_convert_back.patch, 18.4 KB (added by , 11 years ago) |
---|
-
sage/calculus/calculus.py
# HG changeset patch # User Burcin Erocal <burcin@erocal.org> # Date 1270567756 -7200 # Node ID f9802ac07a5f4e86e665ae204970f443f133aa61 # Parent 9a0352bfc599c00978cec836a84c0f284ad055bd trac 7661: fix problems with conversion of maxima elements to symbolic expressions diff --git a/sage/calculus/calculus.py b/sage/calculus/calculus.py
a b 292 292 x |--> 1/2 293 293 """ 294 294 295 import weakref296 295 import re 297 from sage.rings.all import (CommutativeRing, RealField, is_Polynomial, 298 is_MPolynomial, is_MPolynomialRing, is_FractionFieldElement, 299 is_RealNumber, is_ComplexNumber, RR, is_NumberFieldElement, 300 Integer, Rational, CC, QQ, CDF, ZZ, 301 PolynomialRing, ComplexField, RealDoubleElement, 302 algdep, Integer, RealNumber, RealIntervalField) 303 296 from sage.rings.all import RR, Integer, CC, QQ, RealDoubleElement, algdep 304 297 from sage.rings.real_mpfr import create_RealNumber 305 298 306 from sage.structure.element import RingElement, is_Element307 from sage.structure.parent_base import ParentWithBase308 309 import operator310 299 from sage.misc.latex import latex, latex_variable_name 311 from sage.misc.misc import uniq as unique312 from sage.structure.sage_object import SageObject313 314 300 from sage.interfaces.maxima import Maxima 315 316 import sage.numerical.optimize317 318 301 from sage.misc.parser import Parser 319 302 320 import math321 322 import sage.ext.fast_eval as fast_float323 324 303 from sage.symbolic.ring import var, SR, is_SymbolicVariable 325 304 from sage.symbolic.expression import Expression 326 305 from sage.symbolic.function import Function 327 306 from sage.symbolic.function_factory import function_factory, function 328 307 from sage.symbolic.integration.integral import indefinite_integral, \ 329 308 definite_integral 330 331 arc_functions = ['asin', 'acos', 'atan', 'asinh', 'acosh', 'atanh', 'acoth', 'asech', 'acsch', 'acot', 'acsc', 'asec'] 309 import sage.symbolic.pynac 332 310 333 311 maxima = Maxima(init_code = ['display2d:false', 'domain: complex', 'keepfloat: true', 'load(to_poly_solver)', 'load(simplify_sum)'], 334 312 script_subdirectory=None) … … 1033 1011 else: 1034 1012 raise NotImplementedError, "sympy does not support one-sided limits" 1035 1013 1014 return l.sage() 1036 1015 return ex.parent()(l) 1037 1016 1038 1017 lim = limit … … 1438 1417 'li[2]':'polylog2', 'li[3]':'polylog3'} 1439 1418 1440 1419 from sage.misc.multireplace import multiple_replace 1441 1442 1420 import re 1443 1421 1444 1445 1422 maxima_tick = re.compile("'[a-z|A-Z|0-9|_]*") 1446 1423 1447 1424 maxima_qp = re.compile("\?\%[a-z|A-Z|0-9|_]*") # e.g., ?%jacobi_cd … … 1457 1434 1458 1435 INPUT: 1459 1436 1460 1461 1437 - ``x`` - a string 1462 1438 1463 1439 - ``equals_sub`` - (default: False) if True, replace … … 1480 1456 sage: a.sage() 1481 1457 x != 0 1482 1458 """ 1483 global _syms 1484 _syms = sage.symbolic.pynac.symbol_table.get('maxima', {}) 1485 syms = dict(_syms) 1459 syms = sage.symbolic.pynac.symbol_table.get('maxima', {}).copy() 1486 1460 1487 1461 if len(x) == 0: 1488 1462 raise RuntimeError, "invalid symbolic expression -- ''" … … 1560 1534 is_simplified = False 1561 1535 1562 1536 1563 # External access used by restore1564 from sage.symbolic.pynac import symbol_table1565 _syms = syms_cur = symbol_table.get('maxima', {})1566 syms_default = dict(syms_cur)1567 1568 1537 # Comma format options for Maxima 1569 1538 def mapped_opts(v): 1570 1539 """ … … 1573 1542 1574 1543 INPUT: 1575 1544 1576 1577 1545 - ``v`` - an object 1578 1546 1579 1580 1547 OUTPUT: a string. 1581 1548 1582 1549 The main use of this is to turn Python bools into lower case … … 1609 1576 1610 1577 # Parser for symbolic ring elements 1611 1578 1579 # We keep two dictionaries syms_cur and syms_default to keep the current symbol 1580 # table and the state of the table at startup respectively. These are used by 1581 # the restore() function (see sage.misc.reset). 1582 # 1583 # The dictionary _syms is used as a lookup table for the system function 1584 # registry by _find_func() below. It gets updated by 1585 # symbolic_expression_from_string() before calling the parser. 1586 from sage.symbolic.pynac import symbol_table 1587 _syms = syms_cur = symbol_table.get('functions', {}) 1588 syms_default = dict(syms_cur) 1589 1590 # This dictionary is used to pass a lookup table other than the system registry 1591 # to the parser. A global variable is necessary since the parser calls the 1592 # _find_var() and _find_func() functions below without extra arguments. 1612 1593 _augmented_syms = {} 1613 1594 1595 from sage.symbolic.ring import pynac_symbol_registry 1596 1614 1597 def _find_var(name): 1615 1598 """ 1616 1599 Function to pass to Parser for constructing … … 1625 1608 I 1626 1609 """ 1627 1610 try: 1628 return (_augmented_syms or _syms)[name] 1611 res = _augmented_syms.get(name) 1612 if res is None: 1613 return pynac_symbol_registry[name] 1614 # _augmented_syms might contain entries pointing to functions if 1615 # previous computations polluted the maxima workspace 1616 if not isinstance(res, Function): 1617 return res 1629 1618 except KeyError: 1630 1619 pass 1620 1621 # try to find the name in the global namespace 1622 # needed for identifiers like 'e', etc. 1631 1623 try: 1632 1624 return SR(sage.all.__dict__[name]) 1633 1625 except (KeyError, TypeError): … … 1652 1644 0 1653 1645 """ 1654 1646 try: 1655 func = _ syms.get(name)1647 func = _augmented_syms.get(name) 1656 1648 if func is None: 1657 func = _ augmented_syms[name]1649 func = _syms[name] 1658 1650 if not isinstance(func, Expression): 1659 1651 return func 1660 1652 except KeyError: … … 1666 1658 except (KeyError, TypeError): 1667 1659 return function_factory(name) 1668 1660 1669 SR_parser = Parser(make_int = lambda x: SR(Integer(x)), 1661 SR_parser = Parser(make_int = lambda x: SR(Integer(x)), 1670 1662 make_float = lambda x: SR(RealDoubleElement(x)), 1671 1663 make_var = _find_var, 1672 1664 make_function = _find_func) … … 1679 1671 1680 1672 INPUT: 1681 1673 1682 1683 1674 - ``s`` - a string 1684 1675 1685 1676 - ``syms`` - (default: None) dictionary of … … 1695 1686 sage: sage.calculus.calculus.symbolic_expression_from_string('[sin(0)*x^2,3*spam+e^pi]',syms={'spam':y},accept_sequence=True) 1696 1687 [0, 3*y + e^pi] 1697 1688 """ 1698 # from sage.functions.constants import I # can't import this at the top, but need it now1699 # _syms['i'] = _syms['I'] = I1689 global _syms 1690 _syms = sage.symbolic.pynac.symbol_table['functions'].copy() 1700 1691 parse_func = SR_parser.parse_sequence if accept_sequence else SR_parser.parse_expression 1701 1692 if syms is None: 1702 1693 return parse_func(s) … … 1707 1698 return parse_func(s) 1708 1699 finally: 1709 1700 _augmented_syms = {} 1710 1711 def symbolic_expression_from_maxima_element(x, maxima=maxima):1712 """1713 Given an element of the calculus copy of the Maxima interface,1714 create the corresponding Sage symbolic expression.1715 1716 EXAMPLES::1717 1718 sage: a = sage.calculus.calculus.maxima('x^(sqrt(y)+%pi) + sin(%e + %pi)')1719 sage: sage.calculus.calculus.symbolic_expression_from_maxima_element(a)1720 x^(pi + sqrt(y)) - sin(e)1721 sage: var('x, y')1722 (x, y)1723 sage: v = sage.calculus.calculus.maxima.vandermonde_matrix([x, y, 1/2])1724 sage: sage.calculus.calculus.symbolic_expression_from_maxima_element(v)1725 [ 1 x x^2]1726 [ 1 y y^2]1727 [ 1 1/2 1/4]1728 """1729 return symbolic_expression_from_maxima_string(x.name(), maxima=maxima) -
sage/functions/other.py
diff --git a/sage/functions/other.py b/sage/functions/other.py
a b 3 3 """ 4 4 from sage.symbolic.function import GinacFunction, BuiltinFunction 5 5 from sage.symbolic.expression import Expression 6 from sage.symbolic.pynac import register_symbol, symbol_table 6 7 from sage.libs.pari.gen import pari 7 8 from sage.symbolic.all import SR 8 9 from sage.rings.all import Integer, Rational, RealField, CC, RR, \ … … 48 49 Traceback (most recent call last): 49 50 ... 50 51 TypeError: unable to simplify to complex approximation 52 53 TESTS: 54 55 Check if conversion from maxima elements work:: 56 57 sage: merf = maxima(erf(x)).sage().operator() 58 sage: merf == erf 59 True 51 60 """ 52 61 BuiltinFunction.__init__(self, "erf", latex_name=r"\text{erf}") 53 62 … … 690 699 raise TypeError, "Symbolic function gamma takes at most 2 arguments (%s given)"%(len(args)+1) 691 700 return incomplete_gamma(a,args[0],**kwds) 692 701 702 # We have to add the wrapper function manually to the symbol_table when we have 703 # two functions with different number of arguments and the same name 704 symbol_table['functions']['gamma'] = gamma 705 693 706 class Function_psi1(GinacFunction): 694 707 def __init__(self): 695 708 r""" … … 836 849 raise TypeError, "Symbolic function psi takes at most 2 arguments (%s given)"%(len(args)+1) 837 850 return psi2(x,args[0],**kwds) 838 851 852 # We have to add the wrapper function manually to the symbol_table when we have 853 # two functions with different number of arguments and the same name 854 symbol_table['functions']['psi'] = psi 839 855 840 856 class Function_factorial(GinacFunction): 841 857 def __init__(self): … … 1116 1132 pass 1117 1133 return _do_sqrt(x, *args, **kwds) 1118 1134 1119 # register sqrt in pynac symbol_table for conversion back from maxima1120 from sage.symbolic.pynac import register_symbol#, symbol_table 1121 register_symbol(sqrt, dict(maxima='sqrt', mathematica='Sqrt', maple='sqrt')) 1135 # register sqrt in pynac symbol_table for conversion back from other systems 1136 register_symbol(sqrt, dict(mathematica='Sqrt')) 1137 symbol_table['functions']['sqrt'] = sqrt 1122 1138 1123 1139 Function_sqrt = type('deprecated_sqrt', (), 1124 1140 {'__call__': staticmethod(sqrt), -
sage/functions/special.py
diff --git a/sage/functions/special.py b/sage/functions/special.py
a b 394 394 import sage.rings.ring as ring 395 395 from sage.functions.other import real, imag 396 396 from sage.symbolic.function import BuiltinFunction 397 from sage.calculus.calculus import maxima , symbolic_expression_from_maxima_element397 from sage.calculus.calculus import maxima 398 398 399 399 def meval(x): 400 from sage.calculus.calculus import symbolic_expression_from_maxima_element 401 return symbolic_expression_from_maxima_element(maxima(x), maxima) 400 return maxima(x).sage() 402 401 403 402 _done = False 404 403 def _init(): … … 513 512 if self.name() in repr(s): 514 513 return None 515 514 else: 516 return symbolic_expression_from_maxima_element(s)515 return s.sage() 517 516 518 517 from sage.misc.cachefunc import cached_function 519 518 -
sage/interfaces/maxima.py
diff --git a/sage/interfaces/maxima.py b/sage/interfaces/maxima.py
a b 1769 1769 sqrt(2) + sqrt(3) + 2.5 1770 1770 sage: type(d) 1771 1771 <type 'sage.symbolic.expression.Expression'> 1772 1773 sage: a = sage.calculus.calculus.maxima('x^(sqrt(y)+%pi) + sin(%e + %pi)') 1774 sage: a._sage_() 1775 x^(pi + sqrt(y)) - sin(e) 1776 sage: var('x, y') 1777 (x, y) 1778 sage: v = sage.calculus.calculus.maxima.vandermonde_matrix([x, y, 1/2]) 1779 sage: v._sage_() 1780 [ 1 x x^2] 1781 [ 1 y y^2] 1782 [ 1 1/2 1/4] 1783 1784 Check if #7661 is fixed:: 1785 1786 sage: var('delta') 1787 delta 1788 sage: (2*delta).simplify() 1789 2*delta 1772 1790 """ 1773 from sage.calculus.calculus import symbolic_expression_from_maxima_string1774 #return symbolic_expression_from_maxima_string(self.name(), maxima=self.parent())1775 return symbolic_expression_from_maxima_string(repr(self))1791 import sage.calculus.calculus as calculus 1792 return calculus.symbolic_expression_from_maxima_string(self.name(), 1793 maxima=self.parent()) 1776 1794 1777 1795 def _symbolic_(self, R): 1778 1796 """ -
sage/symbolic/expression.pyx
diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
a b 6514 6514 [x == 1/2*pi] 6515 6515 sage: solve(cos(x)==0,x,to_poly_solve=True) 6516 6516 [x == 1/2*pi] 6517 sage: from sage.calculus.calculus import maxima , symbolic_expression_from_maxima_element6517 sage: from sage.calculus.calculus import maxima 6518 6518 sage: sol = maxima(cos(x)==0).to_poly_solve(x) 6519 sage: s ymbolic_expression_from_maxima_element(sol)6519 sage: sol.sage() 6520 6520 [[x == -1/2*pi + 2*pi*z57], [x == 1/2*pi + 2*pi*z59]] 6521 6521 6522 6522 If a returned unsolved expression has a denominator, but the … … 6524 6524 6525 6525 sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True) 6526 6526 [sin(x) == 1/2/cos(x)] 6527 sage: from sage.calculus.calculus import maxima , symbolic_expression_from_maxima_element6527 sage: from sage.calculus.calculus import maxima 6528 6528 sage: sol = maxima(cos(x) * sin(x) == 1/2).to_poly_solve(x) 6529 sage: s ymbolic_expression_from_maxima_element(sol)6529 sage: sol.sage() 6530 6530 [[x == 1/4*pi + pi*z73]] 6531 6531 6532 6532 Some basic inequalities can be also solved:: … … 6646 6646 # but also allows for the possibility of approximate # 6647 6647 # solutions being returned. # 6648 6648 ######################################################## 6649 if to_poly_solve and not multiplicities: 6649 if to_poly_solve and not multiplicities: 6650 6650 if len(X)==0: # if Maxima's solve gave no solutions, only try it 6651 6651 try: 6652 6652 s = m.to_poly_solve(x) … … 6656 6656 X = [] 6657 6657 6658 6658 for eq in X: 6659 if repr(x) in map(repr, eq.rhs().variables()) or repr(x) in repr(eq.lhs()): # If the RHS of one solution also has the variable, or if the LHS is not the variable, try another way to get solutions 6660 from sage.calculus.calculus import symbolic_expression_from_maxima_element 6659 # If the RHS of one solution also has the variable, or if 6660 # the LHS is not the variable, try another way to get solutions 6661 if repr(x) in map(repr, eq.rhs().variables()) or \ 6662 repr(x) in repr(eq.lhs()): 6661 6663 try: 6662 Y = symbolic_expression_from_maxima_element((eq._maxima_()).to_poly_solve(x)) # try to solve it using to_poly_solve 6663 X.remove(eq) 6664 X.extend([y[0] for y in Y]) # replace with the new solutions 6664 # try to solve it using to_poly_solve 6665 Y = eq._maxima_().to_poly_solve(x).sage() 6666 X.remove(eq) 6667 # replace with the new solutions 6668 X.extend([y[0] for y in Y]) 6665 6669 except TypeError, mess: 6666 if "Error executing code in Maxima" in str(mess) or "unable to make sense of Maxima expression" in str(mess): 6670 if "Error executing code in Maxima" in str(mess) or \ 6671 "unable to make sense of Maxima expression" in\ 6672 str(mess): 6667 6673 if explicit_solutions: 6668 6674 X.remove(eq) # this removes an implicit solution 6669 6675 else: -
sage/symbolic/random_tests.py
diff --git a/sage/symbolic/random_tests.py b/sage/symbolic/random_tests.py
a b 15 15 # For creating expressions with the full power of Pynac's simple expression 16 16 # subset (with no quantifiers/operators; that is, no derivatives, integrals, 17 17 # etc.) 18 19 18 full_binary = [(0.3, operator.add), (0.1, operator.sub), (0.3, operator.mul), (0.2, operator.div), (0.1, operator.pow)] 20 19 full_unary = [(0.8, operator.neg), (0.2, operator.inv)] 21 full_functions = [(1.0, f, f.number_of_arguments()) for f in sage.symbolic.pynac.symbol_table['functions'].values() if f.number_of_arguments() > 0 and 'elliptic' not in str(f) and 'dickman_rho' not in str(f)] 22 full_nullary = [(1.0, c) for c in [pi, e]] + [(0.05, c) for c in [golden_ratio, log2, euler_gamma, catalan, khinchin, twinprime, mertens, brun]] 23 full_internal = [(0.6, full_binary, 2), (0.2, full_unary, 1), (0.2, full_functions)] 20 full_functions = [(1.0, f, f.number_of_arguments()) 21 for f in sage.symbolic.pynac.symbol_table['functions'].values() 22 if hasattr(f, 'number_of_arguments') and 23 f.number_of_arguments() > 0 ] 24 full_nullary = [(1.0, c) for c in [pi, e]] + [(0.05, c) for c in 25 [golden_ratio, log2, euler_gamma, catalan, khinchin, twinprime, 26 mertens, brun]] 27 full_internal = [(0.6, full_binary, 2), (0.2, full_unary, 1), 28 (0.2, full_functions)] 24 29 25 30 def normalize_prob_list(pl, extra=()): 26 31 r""" … … 202 207 203 208 sage: from sage.symbolic.random_tests import * 204 209 sage: random_expr(50, nvars=3, coeff_generator=CDF.random_element) 205 sinh( sinh((-0.314177274493 + 0.144437996366*I)/csc(-v1^2*e/v3) + erf((-0.708874026302 - 0.954135400334*I)*v3) + 0.0275857401668 - 0.479027260657*I))^(-cosh(-polylog((v2^2 + (0.067987275089 + 1.08529153495*I)*v3)^(-v1 - v3), (5.29385548262 + 2.57440711353*I)*e/cosh((-0.436810529675 + 0.736945423566*I)*arccot(pi)))))210 sinh(elliptic_kc(-1/csc(-((2.62756608636 + 1.20798164491*I)*v3 + (2.62756608636 + 1.20798164491*I)*e)*pi*v1) + erf((-0.708874026302 - 0.954135400334*I)*v3) - elliptic_pi(0.520184609653 - 0.734276246499*I, v3, pi)))^(-elliptic_f((v2^2 + (0.067987275089 + 1.08529153495*I)*v3)^(-v1 - v3), (5.29385548262 + 2.57440711353*I)*e/arccoth(v2*arccot(0.812302592816 - 0.302973871736*I)))) 206 211 sage: random_expr(5, verbose=True) 207 About to apply <built-in function add> to [v1, v1]208 About to apply <built-in function mul> to [v1, -1/2]209 About to apply <built-in function mul> to [2*v1, -1/2*v1]210 -v1^2 212 About to apply <built-in function mul> to [v1, v1] 213 About to apply <built-in function add> to [v1^2, v1] 214 About to apply <built-in function neg> to [v1^2 + v1] 215 -v1^2 - v1 211 216 """ 212 217 vars = [(1.0, sage.calculus.calculus.var('v%d' % (n+1))) for n in range(nvars)] 213 218 if ncoeffs is None: -
sage/symbolic/ring.pyx
diff --git a/sage/symbolic/ring.pyx b/sage/symbolic/ring.pyx
a b 35 35 36 36 from sage.rings.all import RR, CC 37 37 38 cdef dictpynac_symbol_registry = {}38 pynac_symbol_registry = {} 39 39 40 40 cdef class SymbolicRing(CommutativeRing): 41 41 """