Skip to content

Commit

Permalink
Implement equality for toric varieties (#4509)
Browse files Browse the repository at this point in the history
[ToricVarieties] Implement equality for toric varieties

---------
Co-authored-by: Benjamin Lorenz <[email protected]>
  • Loading branch information
paemurru authored Feb 1, 2025
1 parent eb35e0e commit c4ec0a9
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 32 deletions.
32 changes: 7 additions & 25 deletions docs/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,13 @@ the affine and non-affine case:

## Equality of Normal Toric Varieties

!!! warning
Equality `==` of normal toric varieties currently checks equality of
memory locations. We recommend using `===`, which always checks
equality of memory locations in OSCAR.

To check that the fans considered as sets of cones are equal, you may use the method below:

```julia
function slow_equal(tv1::NormalToricVariety, tv2::NormalToricVariety)
tv1 === tv2 && return true
ambient_dim(tv1) == ambient_dim(tv2) || return false
f_vector(tv1) == f_vector(tv2) || return false
return Set(maximal_cones(tv1)) == Set(maximal_cones(tv2))
end
```

Polyhedral fans can be stored in Polymake using either rays or
hyperplanes. In the former case, cones are stored as sets of indices of
rays, corresponding to polyhedral hulls, while in the latter case, cones
are stored as sets of indices of hyperplanes, corresponding to
intersections of hyperplanes. Converting between these two formats can
be expensive. In the case where the polyhedral fans of two normal toric
varieties are both stored using rays, the above method `slow_equal` has
computational complexity $O(n \log n)$, where $n$ is the number of
cones.
Equality `==` of normal toric varieties checks equality of the
corresponding polyhedral fans as sets of cones.
This computes the rays of both of the toric varieties, which can be
expensive if they are not already computed, meaning if
`"RAYS" in Polymake.list_properties(Oscar.pm_object(polyhedral_fan(X)))`
is false for one of the varieties.
Triple-equality `===` always checks equality of memory locations in OSCAR.


## Constructors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,16 +181,74 @@ end
# Equality
######################

function Base.:(==)(tv1::NormalToricVariety, tv2::NormalToricVariety)
tv1 === tv2 && return true
error("Equality of normal toric varieties is computationally very demanding. More details in the documentation.")
end
@doc raw"""
(==)(X::NormalToricVariety, Y::NormalToricVariety) -> Bool
Checks equality of the polyhedral fans as sets of cones.
# Examples
```jldoctest
julia> H = hirzebruch_surface(NormalToricVariety, 0)
Normal toric variety
function Base.hash(tv::NormalToricVariety, h::UInt)
return hash(objectid(tv), h)
julia> P1 = projective_space(NormalToricVariety, 1)
Normal toric variety
julia> H == P1 * P1
true
```
"""
function Base.:(==)(X::NormalToricVariety, Y::NormalToricVariety)
X === Y && return true
ambient_dim(X) == ambient_dim(Y) || return false
n_rays(X) == n_rays(Y) || return false

# p is a permutation such that the i-th ray of X is the p(i)-th ray of Y
p = inv(perm(sortperm(rays(X)))) * perm(sortperm(rays(Y)))

for i in 1:n_rays(X)
rays(X)[i] == rays(Y)[p(i)] || return false
end
@inline rows(Z) = [
row(maximal_cones(IncidenceMatrix, Z), i) for i in 1:n_maximal_cones(Z)
]
return Set(map(r -> Set(p.(r)), rows(X))) == Set(rows(Y))
end

@doc raw"""
_id(X::NormalToricVariety)
-> Tuple{Vector{Vector{QQFieldElem}}, Vector{Vector{Int64}}}
Given a toric variety `X`, returns a pair `Oscar._id(X)` with the
following property: two toric varieties `X` and `Y` have equal
polyhedral fans, taken as sets of cones, if and only if
`Oscar._id(X) == Oscar._id(Y)`.
# Examples
```jldoctest
julia> H = hirzebruch_surface(NormalToricVariety, 0)
Normal toric variety
julia> P1 = projective_space(NormalToricVariety, 1)
Normal toric variety
julia> Oscar._id(H) == Oscar._id(P1 * P1)
true
```
"""
function _id(X::NormalToricVariety)
p = inv(perm(sortperm(rays(X))))
sorted_rays = Vector.(permuted(collect(rays(X)), p))
@inline rows(Z) = [
row(maximal_cones(IncidenceMatrix, Z), i) for i in 1:n_maximal_cones(Z)
]
sorted_maximal_cones = sort(map(r -> sort(Vector(p.(r))), rows(X)))
return (sorted_rays, sorted_maximal_cones)
end

function Base.hash(X::NormalToricVariety, h::UInt)
return hash(_id(X), h)
end

######################
# Display
Expand Down
39 changes: 38 additions & 1 deletion test/AlgebraicGeometry/ToricVarieties/normal_toric_varieties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,43 @@
@testset "Equality of normal toric varieties" begin
@test (p2 === f2) == false
@test p2 === p2
@test_throws ErrorException("Equality of normal toric varieties is computationally very demanding. More details in the documentation.") p2 == f2
@test p2 != f2

X = projective_space(NormalToricVariety, 2)
X = domain(blow_up(X, [3, 4]))
X = domain(blow_up(X, [-2, -3]))
Y = weighted_projective_space(NormalToricVariety, [1, 2, 3])
Y = domain(blow_up(Y, [-1, -1]))
Y = domain(blow_up(Y, [3, 4]))
@test X == Y

Z = projective_space(NormalToricVariety, 2)
X = domain(blow_up(Z, [1, 1]))
Y = domain(blow_up(Z, [1, 2]))
@test X != Y

H = hirzebruch_surface(NormalToricVariety, 0)
P1 = projective_space(NormalToricVariety, 1)
ray_generators = [[1, 1], [1, 2]]
max_cones = incidence_matrix([[1, 2]])
X = normal_toric_variety(max_cones, ray_generators)
@test length(Set([H, P1 * P1, X])) == 2

@testset "Speed test hash (at most 0.5 seconds)" begin
success = false
ntv5 = normal_toric_variety(polarize(polyhedron(Polymake.polytope.rand_sphere(5, 60; seed=42))))
hash(ntv5)
for i in 1:5
stats = @timed hash(ntv5)
duration = stats.time - stats.gctime
if duration < 0.5
success = true
break
else
@warn "Hash took $duration > 0.5 seconds (i=$i)"
end
end
@test success == true
end
end
end

0 comments on commit c4ec0a9

Please sign in to comment.