I would think that the method `__hash__` of FractionFieldElement in fraction_field_element.pyx is broken, since
sage: f1 = x/y sage: f2 = (2*x)/(2*y) sage: f1 == f2 True sage: hash(f1) -284264079394034550 sage: hash(f2) -284264773958195866 In `__hash__`, we do the following: if self._parent.is_exact(): ... self.reduce() # Same algorithm as for elements of QQ n = hash(self._numerator) d = hash(self._denominator) if d == 1: return n else: return n ^ d The problem is that `self.reduce()` doesn't have any effect: it divides out the gcd of numerator and denominator, which is 1, since QQ is a field. (Over ZZ it is 2, which is the reason why it works) I don't know how to fix this properly. Can we define a sensible hash generically for FractionFieldElement at all? Partially, this might also be my fault from https://github.com/sagemath/sage/pull/38924 There are other tickets that thought about this, e.g., https://github.com/sagemath/sage/issues/16268 :-( Martin On Wednesday, 16 April 2025 at 17:48:47 UTC+2 Nils Bruin wrote: > On Wednesday, 16 April 2025 at 04:55:39 UTC-7 Peter Mueller wrote: > > The following code > > K.<x, y> = QQ[] > K = K.fraction_field() > print(len({x/y, (2*x)/(2*y)})) > > gives the answer 2, even though the two elements of course are the same! > Is this a bug or a feature for a reason I cannot guess? Same on the > SageMath Cell. > > > I don't think it's a feature but it might be that you're hitting general > code that can't do much more than it does. In that case we should probably > have a specialization that deals with that particular situation. > > In your case, we can just force the denominator to be monic. It can make > for less nice representations because it might cause fractional > coefficients in the numerator and denominator: > > > f.numerator()/(c:=f.denominator().leading_coefficient())/(f.denominator()/c) > > For this standardization, we need that there's a monomial ordering (which > would generally be met) and that the leading coefficient is a unit (true > over a field). It's the last one that is generally problematic. In > ZZ["x,y"].fraction_field(), you'd already need a different approach and > over domains with more complicated unit groups and/or without unique > factorization, normalizing the denominator is going to be very expensive. > Note that it doesn't affect the ability to compute in the field of > fractions: equality testing is still easy. It's just the normal form that's > hard (and which is necessary to get to a well-defined hash). > > Funniliy enough: > > K.<x, y> = ZZ[] > > K = K.fraction_field() > print(len({x/y, (2*x)/(2*y)})) > > so it seems that the extra work was already done in that case. And that's > also the representation in which you'll avoid denominators in the > denominator! So probably it's better to switch to that representation. If > you need polynomials you can use > > QQ['x,y'](f) > > when the denominator has degree 0. > > -- You received this message because you are subscribed to the Google Groups "sage-support" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-support+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/sage-support/4f1e5977-b0c0-40cc-acb2-1edd94bcc771n%40googlegroups.com.