sage: H5.<a,b,c> = FractionField(PolynomialRing(ZZ, ['a', 'b', 'c']))
sage: S = set([1/(1-c)])
sage: (-1)/(c-1) in S
False
I know Sage doesn't promise that equal objects have equal hashes, but surely this should be valid for objects from *a single ring*?
I looked at the hash function implementation, and it's not straightforward to fix this, since it's the generic FractionField method. In particular, we can assume nothing about the ring on which the FractionField is based. I can come up with some examples of rings, and try to do something for them, but my imagination is kind of limited. Subclassing FractionField feels like overkill, but a long list of try... Except clauses inside __hash__ is bad too.
Thoughts?
--Stefan
Hi Robert, hi Stefan,
If I am not mistaken, containment in sets and dicts relies on cmp and
not on ==. Hence, in this case, I think the hash is not to blame.
But there is also a generically implemented method .reduce() for
fraction field elements (so, not necessarily needed to implement it in
subclasses). Of course, it is expensive and it may fail (if
the gcd is not defined). But *if* it works, then fraction f1 is equal to
fraction f2 if and only if numerator and denominator of f1.reduce() are
equal to those of f2.reduce(). Hence, this is the right thing to do for
the hash: Just insert self.reduce() at the beginning of self.__hash__().
I'd rather have a slow hash than a totally broken hash.
This is OK, because (x+1)^2 and x^2+2*x+1 do not compare equal, in terms
of cmp:
sage: cmp((x+1)^2, x^2 + 2*x + 1)
1
Hi Stefan,
On 2013-08-29, Stefan <stefan...@gmail.com> wrote:
> Actually, this is not quite true. reduce() is, by default, called
> automatically for elements of exact rings at creation time. It will
> correctly get rid of common factors, but it does not normalize the leading
> coefficients:
Bad. But of course, it is all only defined up to units.