Toric lattices¶
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:
 Andrey Novoseltsev (20100527): initial version.
 Andrey Novoseltsev (20100730): sublattices and quotients.
EXAMPLES:
The simplest way to create a toric lattice is to specify its dimension only:
sage: N = ToricLattice(3)
sage: N
3d 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
3d 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())
(3d lattice N, 3d 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()
3d 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 +:
'3d lattice N' and '3d 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 3d 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)

class
sage.geometry.toric_lattice.
ToricLatticeFactory
¶ Bases:
sage.structure.factory.UniqueFactory
Create a lattice for toric geometry objects.
INPUT:
rank
– nonnegative integer, the only mandatory parameter;name
– string;dual_name
– string;latex_name
– string;latex_dual_name
– string.
OUTPUT:
 lattice.
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”:
 If no names were given at all, then this lattice will be called “N” and the dual one “M”. These are the standard choices in toric geometry.
 If
name
was given anddual_name
was not, thendual_name
will bename
followed by “*”.  If LaTeX names were not given, they will coincide with the “usual”
names, but if
dual_name
was constructed automatically, the trailing star will be typeset as a superscript.
EXAMPLES:
Let’s start with no names at all and see how automatic names are given:
sage: L1 = ToricLattice(3) sage: L1 3d lattice N sage: L1.dual() 3d lattice M
If we give the name “N” explicitly, the dual lattice will be called “N*”:
sage: L2 = ToricLattice(3, "N") sage: L2 3d lattice N sage: L2.dual() 3d lattice N*
However, we can give an explicit name for it too:
sage: L3 = ToricLattice(3, "N", "M") sage: L3 3d lattice N sage: L3.dual() 3d 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
andL4
have different names either for dual lattices or for LaTeX typesetting.
create_key
(rank, name=None, dual_name=None, latex_name=None, latex_dual_name=None)¶ Create a key that uniquely identifies this toric lattice.
See
ToricLattice
for documentation.Warning
You probably should not use this function directly.

create_object
(version, key)¶ Create the toric lattice described by
key
.See
ToricLattice
for documentation.Warning
You probably should not use this function directly.

class
sage.geometry.toric_lattice.
ToricLattice_ambient
(rank, name, dual_name, latex_name, latex_dual_name)¶ 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.
Element
¶ alias of
sage.geometry.toric_lattice_element.ToricLatticeElement

ambient_module
()¶ 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() 3d lattice N sage: N.ambient_module() is N True

dual
()¶ Return the lattice dual to
self
.OUTPUT:
EXAMPLES:
sage: N = ToricLattice(3) sage: N 3d lattice N sage: M = N.dual() sage: M 3d 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
(**options)¶ Plot
self
.INPUT:
 any options for toric plots (see
toric_plotter.options
), none are mandatory.
OUTPUT:
 a plot.
EXAMPLES:
sage: N = ToricLattice(3) sage: N.plot() Graphics3d Object
 any options for toric plots (see


class
sage.geometry.toric_lattice.
ToricLattice_generic
(base_ring, rank, degree, sparse=False, coordinate_ring=None)¶ Bases:
sage.modules.free_module.FreeModule_generic_pid
Abstract base class for toric lattices.

Element
¶ alias of
sage.geometry.toric_lattice_element.ToricLatticeElement

construction
()¶ Return the functorial construction of
self
.OUTPUT:
None
, we do not think of toric lattices as constructed from simpler objects since we do not want to perform arithmetic involving different lattices.

direct_sum
(other)¶ Return the direct sum with
other
.INPUT:
other
– a toric lattice or more general module.
OUTPUT:
The direct sum of
self
andother
as \(\ZZ\)modules. Ifother
is aToricLattice
, another toric lattice will be returned.EXAMPLES:
sage: K = ToricLattice(3, 'K') sage: L = ToricLattice(3, 'L') sage: N = K.direct_sum(L); N 6d lattice K+L sage: N, N.dual(), latex(N), latex(N.dual()) (6d lattice K+L, 6d 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()) (5d lattice N+N, 5d lattice M+M, N \oplus N, M \oplus M)
If
other
is not aToricLattice
, 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]

intersection
(other)¶ Return the intersection of
self
andother
.INPUT:
other
 a toric (sub)lattice.dual
OUTPUT:
 a toric (sub)lattice.
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

quotient
(sub, check=True, positive_point=None, positive_dual_point=None)¶ Return the quotient of
self
by the given sublatticesub
.INPUT:
sub
– sublattice of self;check
– (default: True) whether or not to check thatsub
is a valid sublattice.
If the quotient is onedimensional 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:
positive_point
– a lattice point ofself
not in the sublatticesub
(that is, not zero in the quotient lattice). The quotient generator will be in the same direction aspositive_point
.positive_dual_point
– a dual lattice point. The quotient generator will be chosen such that its lift has a positive product withpositive_dual_point
. Note: ifpositive_dual_point
is not zero on the sublatticesub
, then the notion of positivity will depend on the choice of lift!
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 3d lattice N by Sublattice <N(1, 8, 0), N(0, 12, 0)>
Attempting to quotient one lattice by a sublattice of another will result in a
ValueError
:sage: N = ToricLattice(3) sage: M = ToricLattice(3, name='M') sage: Ms = M.submodule([M(2,4,0), M(9,12,0)]) sage: N.quotient(Ms) Traceback (most recent call last): ... ValueError: M(1, 8, 0) can not generate a sublattice of 3d lattice N
However, if we forget the sublattice structure, then it is possible to quotient by vector spaces or modules constructed from any sublattice:
sage: N = ToricLattice(3) sage: M = ToricLattice(3, name='M') sage: Ms = M.submodule([M(2,4,0), M(9,12,0)]) sage: N.quotient(Ms.vector_space()) Quotient with torsion of 3d lattice N by Sublattice <N(1, 8, 0), N(0, 12, 0)> sage: N.quotient(Ms.sparse_module()) Quotient with torsion of 3d lattice N by Sublattice <N(1, 8, 0), N(0, 12, 0)>
See
ToricLattice_quotient
for more examples.

saturation
()¶ 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

span
(gens, base_ring=Integer Ring, *args, **kwds)¶ Return the span of the given generators.
INPUT:
gens
– list of elements of the ambient vector space ofself
.base_ring
– (default: \(\ZZ\)) base ring for the generated module.
OUTPUT:
 submodule spanned by
gens
.
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()
, andsubmodule_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.

span_of_basis
(basis, base_ring=Integer Ring, *args, **kwds)¶ Return the submodule with the given
basis
.INPUT:
basis
– list of elements of the ambient vector space ofself
.base_ring
– (default: \(\ZZ\)) base ring for the generated module.
OUTPUT:
 submodule spanned by
basis
.
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()
, andsubmodule_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.


class
sage.geometry.toric_lattice.
ToricLattice_quotient
(V, W, check=True, positive_point=None, positive_dual_point=None)¶ Bases:
sage.modules.fg_pid.fgp_module.FGP_Module_class
Construct the quotient of a toric lattice
V
by its sublatticeW
.INPUT:
V
– ambient toric lattice;W
– sublattice ofV
;check
– (default:True
) whether to check correctness of input or not.
If the quotient is onedimensional 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:
positive_point
– a lattice point ofself
not in the sublatticesub
(that is, not zero in the quotient lattice). The quotient generator will be in the same direction aspositive_point
.positive_dual_point
– a dual lattice point. The quotient generator will be chosen such that its lift has a positive product withpositive_dual_point
. Note: ifpositive_dual_point
is not zero on the sublatticesub
, then the notion of positivity will depend on the choice of lift!
OUTPUT:
 quotient of
V
byW
.
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 1d lattice, quotient of 3d 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 inN
. 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 1d lattice, quotient of 3d 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 1d lattice, quotient of 3d lattice N by Sublattice <N(1, 0, 1), N(0, 1, 1)> sage: Q.gens() (N[0, 0, 1],)

Element
¶ alias of
ToricLattice_quotient_element

base_extend
(R)¶ Return the base change of
self
to the ringR
.INPUT:
R
– either \(\ZZ\) or \(\QQ\).
OUTPUT:
self
if \(R=\ZZ\), quotient of the base extension of the ambient lattice by the base extension of the sublattice if \(R=\QQ\).
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]

coordinate_vector
(x, reduce=False)¶ Return coordinates of x with respect to the optimized representation of self.
INPUT:
x
– element ofself
or convertable toself
.reduce
– (default: False); if True, reduce coefficients modulo invariants.
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)

dimension
()¶ 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

dual
()¶ 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)>

gens
()¶ 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],)

is_torsion_free
()¶ Check if
self
is torsionfree.OUTPUT:
True
isself
has no torsion andFalse
otherwise.
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

rank
()¶ 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

class
sage.geometry.toric_lattice.
ToricLattice_quotient_element
(parent, x, check=True)¶ 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:
 same as for
FGP_Element
.
OUTPUT:
 element of a toric lattice quotient.

set_immutable
()¶ Make
self
immutable.OUTPUT:
 none.
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()
 same as for

class
sage.geometry.toric_lattice.
ToricLattice_sublattice
(ambient, gens, check=True, already_echelonized=False)¶ Bases:
sage.geometry.toric_lattice.ToricLattice_sublattice_with_basis
,sage.modules.free_module.FreeModule_submodule_pid
Construct the sublattice of
ambient
toric lattice generated bygens
.INPUT (same as for
FreeModule_submodule_pid
):ambient
– ambienttoric lattice
for this sublattice;gens
– list of elements ofambient
generating the constructed sublattice; see the base class for other available options.
OUTPUT:
 sublattice of a toric lattice with an automatically chosen basis.
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 userspecified basis, the basis obtained above is the same as the “standard” one:
sage: sublattice.echelonized_basis() [ N(1, 0, 1), N(0, 1, 1) ]

class
sage.geometry.toric_lattice.
ToricLattice_sublattice_with_basis
(ambient, basis, check=True, echelonize=False, echelonized_basis=None, already_echelonized=False)¶ Bases:
sage.geometry.toric_lattice.ToricLattice_generic
,sage.modules.free_module.FreeModule_submodule_with_basis_pid
Construct the sublattice of
ambient
toric lattice with givenbasis
.INPUT (same as for
FreeModule_submodule_with_basis_pid
):ambient
– ambienttoric lattice
for this sublattice;basis
– list of linearly independent elements ofambient
, these elements will be used as the default basis of the constructed sublattice; see the base class for other available options.
OUTPUT:
 sublattice of a toric lattice with a userspecified basis.
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) ]

dual
()¶ 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() 2d lattice, quotient of 3d lattice M by Sublattice <M(1, 1, 1)>

plot
(**options)¶ Plot
self
.INPUT:
 any options for toric plots (see
toric_plotter.options
), none are mandatory.
OUTPUT:
 a plot.
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
 any options for toric plots (see

sage.geometry.toric_lattice.
is_ToricLattice
(x)¶ Check if
x
is a toric lattice.INPUT:
x
– anything.
OUTPUT:
True
ifx
is a toric lattice andFalse
otherwise.
EXAMPLES:
sage: from sage.geometry.toric_lattice import ( ....: is_ToricLattice) sage: is_ToricLattice(1) False sage: N = ToricLattice(3) sage: N 3d lattice N sage: is_ToricLattice(N) True

sage.geometry.toric_lattice.
is_ToricLatticeQuotient
(x)¶ Check if
x
is a toric lattice quotient.INPUT:
x
– anything.
OUTPUT:
True
ifx
is a toric lattice quotient andFalse
otherwise.
EXAMPLES:
sage: from sage.geometry.toric_lattice import ( ....: is_ToricLatticeQuotient) sage: is_ToricLatticeQuotient(1) False sage: N = ToricLattice(3) sage: N 3d lattice N sage: is_ToricLatticeQuotient(N) False sage: Q = N / N.submodule([(1,2,3), (3,2,1)]) sage: Q Quotient with torsion of 3d lattice N by Sublattice <N(1, 2, 3), N(0, 4, 8)> sage: is_ToricLatticeQuotient(Q) True