Opened 9 years ago
Last modified 9 months ago
#14608 new defect
Symbolic functions break the __hash__ contract
Reported by: | vbraun | Owned by: | burcin |
---|---|---|---|
Priority: | major | Milestone: | sage-6.4 |
Component: | symbolics | Keywords: | |
Cc: | Merged in: | ||
Authors: | Reviewers: | ||
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description
Equal objects must have the same hash if they are hashable (http://docs.python.org/2/reference/datamodel.html#object.__hash):
sage: my_func = function('func',nargs=1) sage: f = my_func(0) sage: bool(f == f.simplify()) True sage: hash(f) == hash(f.simplify()) False
As reported on http://ask.sagemath.org/question/2587/simplify-shenanigans, hash lookup errors then leads to undesirable behavior:
sage: ex = my_func(0) + my_func(1) sage: ex.subs(my_func(0)==1) func(1) + 1 sage: ex.simplify().subs(my_func(0)==1) func(0) + func(1)
Change History (11)
comment:1 follow-up: ↓ 2 Changed 9 years ago by
comment:2 in reply to: ↑ 1 Changed 9 years ago by
comment:3 Changed 9 years ago by
(cc me)
comment:4 Changed 8 years ago by
- Milestone changed from sage-5.11 to sage-5.12
comment:5 Changed 8 years ago by
- Milestone changed from sage-6.1 to sage-6.2
comment:6 Changed 8 years ago by
- Milestone changed from sage-6.2 to sage-6.3
comment:7 Changed 7 years ago by
- Milestone changed from sage-6.3 to sage-6.4
comment:8 Changed 6 years ago by
See also #18092.
The problem with simplify+substitute is probably another symptom of NewSymbolicFunction
s not being preserved when going through Maxima and, if so, is restricted to user-defined functions. See e.g.
sage: ex = sin(x)+exp(pi) sage: ex.subs(sin(x)==1) e^pi + 1 sage: ex.simplify().subs(sin(x)==1) e^pi + 1
comment:9 follow-up: ↓ 10 Changed 6 years ago by
Now that we've decided to sacrifice readability for reducing the chance of name collisions with variables in conversion from SR to maxima:
sage: x._maxima_() _SAGE_VAR_x
we could ensure that name translation for functions from SR to maxima is injective as well. Theoretically, we could have
sage: function('f')._maxima_() _SAGE_FUNC_NAME_f sage: function('f',nargs=1)._maxima_() _SAGE_FUNC_NARGS_1_NAME_f
or something similar. Since LISP uses interned strings for symbols, it wouldn't even be inefficient in the "enhanced" interface to maxima_lib: once the dictionaries are seeded, the strings wouldn't be parsed. The strings-based interface would of course have a bit of a penalty, because it does all kind of regex stuff, so string length actually affects performance (but you'd probably have to work very hard to notice it)
Note that this issue came up again on ask sagemath.
comment:10 in reply to: ↑ 9 Changed 2 years ago by
Replying to nbruin:
Note that this issue came up again on ask sagemath.
There is a recent discussion of this issue on sage-devel.
comment:11 Changed 9 months ago by
It seems to me that the hash issue mentioned in the ticket description has been fixed since at least Sage 9.1. In particular, in Sage 9.1 and Sage 9.3.beta8, we have
sage: my_func = function('func',nargs=1) sage: f = my_func(0) sage: bool(f == f.simplify()) True sage: hash(f) == hash(f.simplify()) True sage: ex = my_func(0) + my_func(1) sage: ex.simplify().subs(my_func(0)==1) func(1) + 1
Shall we close this ticket?
Within Sage it is impossible to satisfy "equal objects must have the same hash if they are hashable" because equality is too laxist.
Or
You can not hope to solve this problem with one ticket (because the Symbolic ring contains all Sage objects) !