Open a46d73b2-c70f-469a-b7c4-f2ca845e72d5 opened 9 years ago
nargs=1
, but I've just retested it using the identical sequence except with z = sage.symbolic.function_factory.function('z')
, and it throws the same exception.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
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:
possibly related: #17558 (pickled function loses its args)
Like this:
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.
Component: interfaces
Keywords: pickle, maxima, symbolic, function, sr_to_max
Issue created by migration from https://trac.sagemath.org/ticket/17503