This module was designed as a part of the framework for toric varieties (variety, fano_variety).
All toric lattices are isomorphic to \(\ZZ^n\) for some \(n\), but will prevent you from doing “wrong” operations with objects from different lattices.
AUTHORS:
EXAMPLES:
The simplest way to create a toric lattice is to specify its dimension only:
sage: N = ToricLattice(3)
sage: N
3-d lattice N
While our lattice N is called exactly “N” it is a coincidence: all lattices are called “N” by default:
sage: another_name = ToricLattice(3)
sage: another_name
3-d lattice N
If fact, the above lattice is exactly the same as before as an object in memory:
sage: N is another_name
True
There are actually four names associated to a toric lattice and they all must be the same for two lattices to coincide:
sage: N, N.dual(), latex(N), latex(N.dual())
(3-d lattice N, 3-d lattice M, N, M)
Notice that the lattice dual to N is called “M” which is standard in toric geometry. This happens only if you allow completely automatic handling of names:
sage: another_N = ToricLattice(3, "N")
sage: another_N.dual()
3-d lattice N*
sage: N is another_N
False
What can you do with toric lattices? Well, their main purpose is to allow creation of elements of toric lattices:
sage: n = N([1,2,3])
sage: n
N(1, 2, 3)
sage: M = N.dual()
sage: m = M(1,2,3)
sage: m
M(1, 2, 3)
Dual lattices can act on each other:
sage: n * m
14
sage: m * n
14
You can also add elements of the same lattice or scale them:
sage: 2 * n
N(2, 4, 6)
sage: n * 2
N(2, 4, 6)
sage: n + n
N(2, 4, 6)
However, you cannot “mix wrong lattices” in your expressions:
sage: n + m
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for '+':
'3-d lattice N' and '3-d lattice M'
sage: n * n
Traceback (most recent call last):
...
TypeError: elements of the same toric lattice cannot be multiplied!
sage: n == m
False
Note that n and m are not equal to each other even though they are both “just (1,2,3).” Moreover, you cannot easily convert elements between toric lattices:
sage: M(n)
Traceback (most recent call last):
...
TypeError: N(1, 2, 3) cannot be converted to 3-d lattice M!
If you really need to consider elements of one lattice as elements of another, you can either use intermediate conversion to “just a vector”:
sage: ZZ3 = ZZ^3
sage: n_in_M = M(ZZ3(n))
sage: n_in_M
M(1, 2, 3)
sage: n == n_in_M
False
sage: n_in_M == m
True
Or you can create a homomorphism from one lattice to any other:
sage: h = N.hom(identity_matrix(3), M)
sage: h(n)
M(1, 2, 3)
Warning
While integer vectors (elements of \(\ZZ^n\)) are printed as (1,2,3), in the code (1,2,3) is a tuple, which has nothing to do neither with vectors, nor with toric lattices, so the following is probably not what you want while working with toric geometry objects:
sage: (1,2,3) + (1,2,3)
(1, 2, 3, 1, 2, 3)
Instead, use syntax like
sage: N(1,2,3) + N(1,2,3)
N(2, 4, 6)
Bases: sage.structure.factory.UniqueFactory
Create a lattice for toric geometry objects.
INPUT:
OUTPUT:
A toric lattice is uniquely determined by its rank and associated names. There are four such “associated names” whose meaning should be clear from the names of the corresponding parameters, but the choice of default values is a little bit involved. So here is the full description of the “naming algorithm”:
EXAMPLES:
Let’s start with no names at all and see how automatic names are given:
sage: L1 = ToricLattice(3)
sage: L1
3-d lattice N
sage: L1.dual()
3-d lattice M
If we give the name “N” explicitly, the dual lattice will be called “N*”:
sage: L2 = ToricLattice(3, "N")
sage: L2
3-d lattice N
sage: L2.dual()
3-d lattice N*
However, we can give an explicit name for it too:
sage: L3 = ToricLattice(3, "N", "M")
sage: L3
3-d lattice N
sage: L3.dual()
3-d lattice M
If you want, you may also give explicit LaTeX names:
sage: L4 = ToricLattice(3, "N", "M", r"\mathbb{N}", r"\mathbb{M}")
sage: latex(L4)
\mathbb{N}
sage: latex(L4.dual())
\mathbb{M}
While all four lattices above are called “N”, only two of them are equal (and are actually the same):
sage: L1 == L2
False
sage: L1 == L3
True
sage: L1 is L3
True
sage: L1 == L4
False
The reason for this is that L2 and L4 have different names either for dual lattices or for LaTeX typesetting.
Create a key that uniquely identifies this toric lattice.
See ToricLattice for documentation.
Warning
You probably should not use this function directly.
TESTS:
sage: ToricLattice.create_key(3)
(3, 'N', 'M', 'N', 'M')
sage: N = ToricLattice(3)
sage: loads(dumps(N)) is N
True
sage: TestSuite(N).run()
Create the toric lattice described by key.
See ToricLattice for documentation.
Warning
You probably should not use this function directly.
TESTS:
sage: key = ToricLattice.create_key(3)
sage: ToricLattice.create_object(1, key)
3-d lattice N
Bases: sage.geometry.toric_lattice.ToricLattice_generic, sage.modules.free_module.FreeModule_ambient_pid
Create a toric lattice.
See ToricLattice for documentation.
Warning
There should be only one toric lattice with the given rank and associated names. Using this class directly to create toric lattices may lead to unexpected results. Please, use ToricLattice to create toric lattices.
TESTS:
sage: N = ToricLattice(3, "N", "M", "N", "M")
sage: N
3-d lattice N
sage: TestSuite(N).run()
Return the ambient module of self.
OUTPUT:
Note
For any ambient toric lattice its ambient module is the lattice itself.
EXAMPLES:
sage: N = ToricLattice(3)
sage: N.ambient_module()
3-d lattice N
sage: N.ambient_module() is N
True
Return the lattice dual to self.
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: N
3-d lattice N
sage: M = N.dual()
sage: M
3-d lattice M
sage: M.dual() is N
True
Elements of dual lattices can act on each other:
sage: n = N(1,2,3)
sage: m = M(4,5,6)
sage: n * m
32
sage: m * n
32
Plot self.
INPUT:
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: N.plot()
Graphics3d Object
Bases: sage.modules.free_module.FreeModule_generic_pid
Abstract base class for toric lattices.
Return the functorial construction of self.
OUTPUT:
TESTS:
sage: print ToricLattice(3).construction()
None
Return the direct sum with other.
INPUT:
OUTPUT:
The direct sum of self and other as \(\ZZ\)-modules. If other is a ToricLattice, another toric lattice will be returned.
EXAMPLES:
sage: K = ToricLattice(3, 'K')
sage: L = ToricLattice(3, 'L')
sage: N = K.direct_sum(L); N
6-d lattice K+L
sage: N, N.dual(), latex(N), latex(N.dual())
(6-d lattice K+L, 6-d lattice K*+L*, K \oplus L, K^* \oplus L^*)
With default names:
sage: N = ToricLattice(3).direct_sum(ToricLattice(2))
sage: N, N.dual(), latex(N), latex(N.dual())
(5-d lattice N+N, 5-d lattice M+M, N \oplus N, M \oplus M)
If other is not a ToricLattice, fall back to sum of modules:
sage: ToricLattice(3).direct_sum(ZZ^2)
Free module of degree 5 and rank 5 over Integer Ring
Echelon basis matrix:
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
Return the intersection of self and other.
INPUT:
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns1 = N.submodule([N(2,4,0), N(9,12,0)])
sage: Ns2 = N.submodule([N(1,4,9), N(9,2,0)])
sage: Ns1.intersection(Ns2)
Sublattice <N(54, 12, 0)>
Note that if one of the intersecting sublattices is a sublattice of another, no new lattices will be constructed:
sage: N.intersection(N) is N
True
sage: Ns1.intersection(N) is Ns1
True
sage: N.intersection(Ns1) is Ns1
True
Return the quotient of self by the given sublattice sub.
INPUT:
If the quotient is one-dimensional and torsion free, the following two mutually exclusive keyword arguments are also allowed. They decide the sign choice for the (single) generator of the quotient lattice:
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
sage: Q = N/Ns
sage: Q
Quotient with torsion of 3-d lattice N
by Sublattice <N(1, 8, 0), N(0, 12, 0)>
See ToricLattice_quotient for more examples.
Return the saturation of self.
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([(1,2,3), (4,5,6)])
sage: Ns
Sublattice <N(1, 2, 3), N(0, 3, 6)>
sage: Ns_sat = Ns.saturation()
sage: Ns_sat
Sublattice <N(1, 0, -1), N(0, 1, 2)>
sage: Ns_sat is Ns_sat.saturation()
True
Return the span of the given generators.
INPUT:
OUTPUT:
Note
The output need not be a submodule of self, nor even of the ambient space. It must, however, be contained in the ambient vector space.
See also span_of_basis(), submodule(), and submodule_with_basis(),
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([N.gen(0)])
sage: Ns.span([N.gen(1)])
Sublattice <N(0, 1, 0)>
sage: Ns.submodule([N.gen(1)])
Traceback (most recent call last):
...
ArithmeticError: Argument gens (= [N(0, 1, 0)])
does not generate a submodule of self.
Return the submodule with the given basis.
INPUT:
OUTPUT:
Note
The output need not be a submodule of self, nor even of the ambient space. It must, however, be contained in the ambient vector space.
See also span(), submodule(), and submodule_with_basis(),
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.span_of_basis([(1,2,3)])
sage: Ns.span_of_basis([(2,4,0)])
Sublattice <N(2, 4, 0)>
sage: Ns.span_of_basis([(1/5,2/5,0), (1/7,1/7,0)])
Free module of degree 3 and rank 2 over Integer Ring
User basis matrix:
[1/5 2/5 0]
[1/7 1/7 0]
Of course the input basis vectors must be linearly independent:
sage: Ns.span_of_basis([(1,2,0), (2,4,0)])
Traceback (most recent call last):
...
ValueError: The given basis vectors must be linearly independent.
Bases: sage.modules.fg_pid.fgp_module.FGP_Module_class
Construct the quotient of a toric lattice V by its sublattice W.
INPUT:
If the quotient is one-dimensional and torsion free, the following two mutually exclusive keyword arguments are also allowed. They decide the sign choice for the (single) generator of the quotient lattice:
OUTPUT:
EXAMPLES:
The intended way to get objects of this class is to use quotient() method of toric lattices:
sage: N = ToricLattice(3)
sage: sublattice = N.submodule([(1,1,0), (3,2,1)])
sage: Q = N/sublattice
sage: Q
1-d lattice, quotient of 3-d lattice N by Sublattice <N(1, 0, 1), N(0, 1, -1)>
sage: Q.gens()
(N[0, 0, 1],)
Here, sublattice happens to be of codimension one in N. If you want to prescribe the sign of the quotient generator, you can do either:
sage: Q = N.quotient(sublattice, positive_point=N(0,0,-1)); Q
1-d lattice, quotient of 3-d lattice N by Sublattice <N(1, 0, 1), N(0, 1, -1)>
sage: Q.gens()
(N[0, 0, -1],)
or:
sage: M = N.dual()
sage: Q = N.quotient(sublattice, positive_dual_point=M(0,0,-1)); Q
1-d lattice, quotient of 3-d lattice N by Sublattice <N(1, 0, 1), N(0, 1, -1)>
sage: Q.gens()
(N[0, 0, -1],)
TESTS:
sage: loads(dumps(Q)) == Q
True
sage: loads(dumps(Q)).gens() == Q.gens()
True
alias of ToricLattice_quotient_element
Return the base change of self to the ring R.
INPUT:
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
sage: Q = N/Ns
sage: Q.base_extend(ZZ) is Q
True
sage: Q.base_extend(QQ)
Vector space quotient V/W of dimension 1 over Rational Field where
V: Vector space of dimension 3 over Rational Field
W: Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:
[1 0 0]
[0 1 0]
Return coordinates of x with respect to the optimized representation of self.
INPUT:
OUTPUT:
The coordinates as a vector.
EXAMPLES:
sage: N = ToricLattice(3)
sage: Q = N.quotient(N.span([N(1,2,3), N(0,2,1)]), positive_point=N(0,-1,0))
sage: q = Q.gen(0); q
N[0, -1, 0]
sage: q.vector() # indirect test
(1)
sage: Q.coordinate_vector(q)
(1)
Return the rank of self.
OUTPUT:
Integer. The dimension of the free part of the quotient.
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
sage: Q = N/Ns
sage: Q.ngens()
2
sage: Q.rank()
1
sage: Ns = N.submodule([N(1,4,0)])
sage: Q = N/Ns
sage: Q.ngens()
2
sage: Q.rank()
2
Return the lattice dual to self.
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([(1, -1, -1)])
sage: Q = N / Ns
sage: Q.dual()
Sublattice <M(1, 0, 1), M(0, 1, -1)>
Return the generators of the quotient.
OUTPUT:
A tuple of ToricLattice_quotient_element generating the quotient.
EXAMPLES:
sage: N = ToricLattice(3)
sage: Q = N.quotient(N.span([N(1,2,3), N(0,2,1)]), positive_point=N(0,-1,0))
sage: Q.gens()
(N[0, -1, 0],)
Check if self is torsion-free.
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
sage: Q = N/Ns
sage: Q.is_torsion_free()
False
sage: Ns = N.submodule([N(1,4,0)])
sage: Q = N/Ns
sage: Q.is_torsion_free()
True
Return the rank of self.
OUTPUT:
Integer. The dimension of the free part of the quotient.
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
sage: Q = N/Ns
sage: Q.ngens()
2
sage: Q.rank()
1
sage: Ns = N.submodule([N(1,4,0)])
sage: Q = N/Ns
sage: Q.ngens()
2
sage: Q.rank()
2
Bases: sage.modules.fg_pid.fgp_element.FGP_Element
Create an element of a toric lattice quotient.
Warning
You probably should not construct such elements explicitly.
INPUT:
OUTPUT:
TESTS:
sage: N = ToricLattice(3)
sage: sublattice = N.submodule([(1,1,0), (3,2,1)])
sage: Q = N/sublattice
sage: e = Q(1,2,3)
sage: e
N[1, 2, 3]
sage: e2 = Q(N(2,3,3))
sage: e2
N[2, 3, 3]
sage: e == e2
True
sage: e.vector()
(4)
sage: e2.vector()
(4)
Make self immutable.
OUTPUT:
Note
Elements of toric lattice quotients are always immutable, so this method does nothing, it is introduced for compatibility purposes only.
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
sage: Q = N/Ns
sage: Q.0.set_immutable()
Bases: sage.geometry.toric_lattice.ToricLattice_sublattice_with_basis, sage.modules.free_module.FreeModule_submodule_pid
Construct the sublattice of ambient toric lattice generated by gens.
INPUT (same as for FreeModule_submodule_pid):
OUTPUT:
See also ToricLattice_sublattice_with_basis if you want to specify an explicit basis.
EXAMPLES:
The intended way to get objects of this class is to use submodule() method of toric lattices:
sage: N = ToricLattice(3)
sage: sublattice = N.submodule([(1,1,0), (3,2,1)])
sage: sublattice.has_user_basis()
False
sage: sublattice.basis()
[
N(1, 0, 1),
N(0, 1, -1)
]
For sublattices without user-specified basis, the basis obtained above is the same as the “standard” one:
sage: sublattice.echelonized_basis()
[
N(1, 0, 1),
N(0, 1, -1)
]
Bases: sage.geometry.toric_lattice.ToricLattice_generic, sage.modules.free_module.FreeModule_submodule_with_basis_pid
Construct the sublattice of ambient toric lattice with given basis.
INPUT (same as for FreeModule_submodule_with_basis_pid):
OUTPUT:
See also ToricLattice_sublattice if you do not want to specify an explicit basis.
EXAMPLES:
The intended way to get objects of this class is to use submodule_with_basis() method of toric lattices:
sage: N = ToricLattice(3)
sage: sublattice = N.submodule_with_basis([(1,1,0), (3,2,1)])
sage: sublattice.has_user_basis()
True
sage: sublattice.basis()
[
N(1, 1, 0),
N(3, 2, 1)
]
Even if you have provided your own basis, you still can access the “standard” one:
sage: sublattice.echelonized_basis()
[
N(1, 0, 1),
N(0, 1, -1)
]
Return the lattice dual to self.
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: Ns = N.submodule([(1,1,0), (3,2,1)])
sage: Ns.dual()
2-d lattice, quotient of 3-d lattice M by Sublattice <M(1, -1, -1)>
Plot self.
INPUT:
OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3)
sage: sublattice = N.submodule_with_basis([(1,1,0), (3,2,1)])
sage: sublattice.plot()
Graphics3d Object
Now we plot both the ambient lattice and its sublattice:
sage: N.plot() + sublattice.plot(point_color="red")
Graphics3d Object
Check if x is a toric lattice.
INPUT:
OUTPUT:
EXAMPLES:
sage: from sage.geometry.toric_lattice import (
... is_ToricLattice)
sage: is_ToricLattice(1)
False
sage: N = ToricLattice(3)
sage: N
3-d lattice N
sage: is_ToricLattice(N)
True
Check if x is a toric lattice quotient.
INPUT:
OUTPUT:
EXAMPLES:
sage: from sage.geometry.toric_lattice import (
... is_ToricLatticeQuotient)
sage: is_ToricLatticeQuotient(1)
False
sage: N = ToricLattice(3)
sage: N
3-d lattice N
sage: is_ToricLatticeQuotient(N)
False
sage: Q = N / N.submodule([(1,2,3), (3,2,1)])
sage: Q
Quotient with torsion of 3-d lattice N
by Sublattice <N(1, 2, 3), N(0, 4, 8)>
sage: is_ToricLatticeQuotient(Q)
True