Opened 4 years ago

# Not all empty schemes are created equal

Reported by: Owned by: kedlaya major sage-7.2 algebraic geometry schemes, empty Kiran Kedlaya N/A u/kedlaya/not_all_empty_schemes_are_created_equal (Commits) 8b00ed9ce22c6ca4641a09cfc0bc8ece2bdb66f0 #21297

### Description

In this example, both schemes are empty, so they should be equal as subschemes of P2. However...

```sage: P2.<x,y,z> = ProjectiveSpace(2, QQ)
sage: P2.subscheme([x,y^2,z]) == P2.subscheme([x,y,z])
False
```

While I'm at it, an `is_empty` method would be nice. It could be defined as follows:

```def self.is_empty():
return (len(self.irreducible_components() == 0)
```

### comment:1 follow-up: ↓ 2 Changed 4 years ago by nbruin

Projective scheme comparison should compare ideals saturated with respect to the irrelevant ideal:

```sage: U=P2.subscheme([x,y,z])
sage: V=P2.subscheme([x,y^2,z])
sage: J=U.defining_ideal()
sage: U.defining_ideal().saturation(J)[0] == V.defining_ideal().saturation(J)[0]
True
```

Similarly, the `is_empty` should do:

```sage: one_ideal= J^0 #just get the ideal generated by 1
sage: U.defining_ideal().saturation(J)[0] == one_ideal
```

decomposing in irreducible components is a more expensive operation.

### comment:2 in reply to: ↑ 1 Changed 4 years ago by kedlaya

Projective scheme comparison should compare ideals saturated with respect to the irrelevant ideal:

```sage: U=P2.subscheme([x,y,z])
sage: V=P2.subscheme([x,y^2,z])
sage: J=U.defining_ideal()
sage: U.defining_ideal().saturation(J)[0] == V.defining_ideal().saturation(J)[0]
True
```

Agreed. I guess we don't want to transform the generating set at creation, so we can recover the generators as specified, but maybe we want to cache the saturation?

Similarly, the `is_empty` should do:

```sage: one_ideal= J^0 #just get the ideal generated by 1
sage: U.defining_ideal().saturation(J)[0] == one_ideal
```

decomposing in irreducible components is a more expensive operation.

Agreed again.

### comment:3 Changed 4 years ago by nbruin

Also note that if we change equality we also have to change the hash, i.e., the hash should be the hash of the generators of the groebner basis of the saturation of the defining ideal. That'll probably shake out another few bugs out of the doctests.

### comment:4 Changed 4 years ago by kedlaya

• Authors set to Kiran Kedlaya
• Branch set to u/kedlaya/not_all_empty_schemes_are_created_equal
• Commit set to 433a479a3d98d1fe0916d9ab3bcb06053004551e

Speaking of shaking out bugs, here is a first attempt (minus the hash), which already runs into something further afield:

```sage -t --warn-long 237.1 src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py
**********************************************************************
Failed example:
HK.coleman_integral(w,S,P)
Exception raised:
Traceback (most recent call last):
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/doctest/forker.py", line 495, in _run
self.compile_and_execute(example, compiler, test.globs)
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/doctest/forker.py", line 858, in compile_and_execute
exec(compiled, globs)
HK.coleman_integral(w,S,P)
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py", line 837, in coleman_integral
basis_values = self.coleman_integrals_on_basis(P, Q, algorithm)
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py", line 621, in coleman_integrals_on_basis
M_frob, forms = self._frob_calc = monsky_washnitzer.matrix_of_frobenius_hyperelliptic(self)
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py", line 1799, in matrix_of_frobenius_hyperelliptic
S = SpecialHyperellipticQuotientRing(Q, extra_prec_ring, True)
File "sage/misc/classcall_metaclass.pyx", line 330, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ (/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/src/build/cythonized/sage/misc/classcall_m
etaclass.c:1251)
return cls.classcall(cls, *args, **kwds)
File "sage/misc/cachefunc.pyx", line 1057, in sage.misc.cachefunc.CachedFunction.__call__ (/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/src/build/cythonized/sage/misc/cachefunc.c:5558)
return self.cache[k]
File "sage/misc/weak_dict.pyx", line 874, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ (/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/src/build/cythonized/sage/misc/weak_dict.c:3905)
cdef PyObject* wr = PyDict_GetItemWithError(self, k)
File "sage/misc/weak_dict.pyx", line 150, in sage.misc.weak_dict.PyDict_GetItemWithError (/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/src/build/cythonized/sage/misc/weak_dict.c:1259)
ep = mp.ma_lookup(mp, <PyObject*><void*>key, PyObject_Hash(key))
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/schemes/generic/algebraic_scheme.py", line 2299, in __eq__
return(self.saturated_defining_ideal() == other.saturated_defining_ideal())
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/schemes/generic/algebraic_scheme.py", line 2280, in saturated_defining_ideal
I3 = I1.saturation(I2)[0]
File "/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/local/lib/python2.7/site-packages/sage/rings/polynomial/multi_polynomial_ideal.py", line 2083, in saturation
ideal, expo = sat(self, other)
File "sage/libs/singular/function.pyx", line 1319, in sage.libs.singular.function.SingularFunction.__call__ (/projects/b8cc019c-1204-44b1-bea9-eb81c119388e/sage/src/build/cythonized/sage/libs/singular/functio
n.cpp:14767)
raise TypeError("Cannot call Singular function '%s' with ring parameter of type '%s'"%(self._name,type(ring)))
TypeError: Cannot call Singular function 'sat' with ring parameter of type '<class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_domain_with_category'>'
**********************************************************************
```

So it seems that there is something wrong with the definition of `saturation` in `sage/rings/polynomial/multi_polynomial_ideal.py`.

New commits:

 ​433a479 `Correct equality testing for projective schemes`

### comment:5 Changed 4 years ago by kedlaya

• Dependencies set to #21297

It might be that dealing with hashing will help with this. But hashing ideals itself need to be fixed; see #21297 (which itself has dependencies on hashing for polynomials).

### comment:6 Changed 4 years ago by git

• Commit changed from 433a479a3d98d1fe0916d9ab3bcb06053004551e to 8b00ed9ce22c6ca4641a09cfc0bc8ece2bdb66f0

Branch pushed to git repo; I updated commit sha1. New commits:

 ​8b00ed9 `Extra commit, not sure why`
Note: See TracTickets for help on using tickets.