Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement equality for toric varieties #4509

Merged
merged 10 commits into from
Feb 1, 2025
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
paemurru marked this conversation as resolved.
Show resolved Hide resolved

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
Loading