Opened 6 years ago
Last modified 6 years ago
#17503 new defect
pickled symbolic function breaks maxima interface
Reported by: | wonder | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | sage-6.4 |
Component: | interfaces | Keywords: | pickle, maxima, symbolic, function, sr_to_max |
Cc: | Merged in: | ||
Authors: | Reviewers: | ||
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description
Like this:
$ sage ┌────────────────────────────────────────────────────────────────────┐ │ Sage Version 6.4.1, Release Date: 2014-11-23 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ sage: z = sage.symbolic.function_factory.function('z',nargs=1) sage: z_expr = solve( z(x) == x/(1-x), x )[0].rhs() sage: z_expr z(x)/(z(x) + 1) sage: limit(loads(dumps(z_expr)), x=0) limit(z(x)/(z(x) + 1), x, 0) sage: limit(z_expr, x=0) --------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) <ipython-input-5-a3b6f4b6aa26> in <module>() ----> 1 limit(z_expr, x=Integer(0)) /usr/local/sage/local/lib/python2.7/site-packages/sage/calculus/calculus.pyc in limit(ex, dir, taylor, algorithm, **argv) 1249 if algorithm == 'maxima': 1250 if dir is None: -> 1251 l = maxima.sr_limit(ex, v, a) 1252 elif dir in ['plus', '+', 'right', 'above']: 1253 if dir == 'above': /usr/local/sage/local/lib/python2.7/site-packages/sage/interfaces/maxima_lib.pyc in sr_limit(self, expr, v, a, dir) 937 """ 938 try: --> 939 L=[sr_to_max(SR(a)) for a in [expr,v,a]] 940 if dir == "plus": 941 L.append(max_plus) /usr/local/sage/local/lib/python2.7/site-packages/sage/interfaces/maxima_lib.pyc in sr_to_max(expr) 1606 max_op_dict[op_max]=op 1607 return EclObject(([sage_op_dict[op]], -> 1608 [sr_to_max(o) for o in expr.operands()])) 1609 elif expr.is_symbol() or expr.is_constant(): 1610 if not expr in sage_sym_dict: /usr/local/sage/local/lib/python2.7/site-packages/sage/interfaces/maxima_lib.pyc in sr_to_max(expr) 1606 max_op_dict[op_max]=op 1607 return EclObject(([sage_op_dict[op]], -> 1608 [sr_to_max(o) for o in expr.operands()])) 1609 elif expr.is_symbol() or expr.is_constant(): 1610 if not expr in sage_sym_dict: /usr/local/sage/local/lib/python2.7/site-packages/sage/interfaces/maxima_lib.pyc in sr_to_max(expr) 1606 max_op_dict[op_max]=op 1607 return EclObject(([sage_op_dict[op]], -> 1608 [sr_to_max(o) for o in expr.operands()])) 1609 elif expr.is_symbol() or expr.is_constant(): 1610 if not expr in sage_sym_dict: /usr/local/sage/local/lib/python2.7/site-packages/sage/interfaces/maxima_lib.pyc in sr_to_max(expr) 1602 op_max=maxima(op).ecl() 1603 if op_max in max_op_dict: -> 1604 raise RuntimeError("Encountered operator mismatch in sr-to-maxima translation") 1605 sage_op_dict[op]=op_max 1606 max_op_dict[op_max]=op RuntimeError: Encountered operator mismatch in sr-to-maxima translation sage:
I don't know the code well enough to diagnose, but from poking around in sr_to_max() it looks like we've got multiple operators with the same name 'z', causing a collision in the dictionaries it uses to translate between sage's names and the names it passes into maxima.
Change History (6)
comment:1 Changed 6 years ago by
- Milestone changed from sage-6.5 to sage-6.4
comment:2 Changed 6 years ago by
- Component changed from PLEASE CHANGE to interfaces
- Type changed from PLEASE CHANGE to defect
comment:3 Changed 6 years ago by
comment:4 Changed 6 years ago by
This hints at a problem:
sage: function('z') is function('z') False sage: function('z') == function('z') True sage: function('z') == loads(dumps(function('z'))) #as expected True sage: function('z')(x).operator() == function('z')(x).operator() True sage: function('z')(x).operator() == loads(dumps(function('z')(x))).operator() #this should also be true False
It seems to me that pynac expressions don't properly get pickled:
sage: explain_pickle(dumps(z)) pg_unpickle_function = unpickle_global('sage.symbolic.function_factory', 'unpickle_function') pg_unpickle_function('z', 0r, None, None, True, [None, None, None, None, None, None, None, None, None, None, None]) sage: explain_pickle(dumps(z(x))) pg_Expression = unpickle_global('sage.symbolic.expression', 'Expression') si = unpickle_newobj(pg_Expression, ()) unpickle_build(si, (0r, ['x'], 'GARC\x03\tfunction\x00class\x00symbol\x00x\x00name\x00seq\x00python\x00z\x00sage_ex\x00\x01\x08\x01\x02\x02\n\x02"\x03\x04\n\x00+\x001\x00"\x07')) si
As you can see, there doesn't seem to be a reference to "unpickle_function" which should really be triggered by pickling an expression that contains 'z'.
Pynac's fiddling with arity probably plays a role:
sage: from sage.symbolic.function_factory import function #to avoid unexpected globals insertions sage: z=function('z') sage: z(x)+z(x,x) z(x, x) + z(x) sage: z1=loads(dumps(z(x))).operator() sage: z2=loads(dumps(z(x,x))).operator() sage: z1(x,x) TypeError: Symbolic function z takes exactly 1 arguments (2 given) sage: z2(x) TypeError: Symbolic function z takes exactly 2 arguments (1 given) sage: z1 == z2 False sage: z1 == function('z',nargs=1) True sage: z2 == function('z',nargs=2) True
comment:5 Changed 6 years ago by
OK, this is a very nice example. It seems that expression pickling *forces* functions to have a fixed arity. On the other hand, calling solve goes through the maxima strings interface, so its resulting functions have undeclared arity. That's why in the example given, the "nargs=1" has no effect: After calling "solve" it's stripped. The following does not produce an error:
sage: from sage.symbolic.function_factory import function sage: z=function('z',nargs=1) sage: z1=loads(dumps(z(x))).operator() sage: z==z1 True sage: z is z1 False sage: limit(z(x),x=0) limit(z(x), x, 0) sage: limit(z1(x),x=0) limit(z(x), x, 0)
So there are two issues at play in this ticket:
- maxima's string interface doesn't deal with arity properly, see #17504
- pickling of expressions doesn't deal with arity properly in another way.
comment:6 Changed 6 years ago by
possibly related: #17558 (pickled function loses its args)
#17504 suggests this could be caused by
nargs=1
, but I've just retested it using the identical sequence except withz = sage.symbolic.function_factory.function('z')
, and it throws the same exception.