Formal modules generated by polyhedra

class sage.geometry.polyhedron.modules.formal_polyhedra_module.FormalPolyhedraModule(base_ring, dimension, basis, category)[source]

Bases: CombinatorialFreeModule

Class for formal modules generated by polyhedra.

It is formal because it is free – it does not know about linear relations of polyhedra.

A formal polyhedral module is graded by dimension.

INPUT:

  • base_ring – base ring of the module; unrelated to the base ring of the polyhedra

  • dimension – the ambient dimension of the polyhedra

  • basis – the basis

EXAMPLES:

sage: from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule
sage: def closed_interval(a, b): return Polyhedron(vertices=[[a], [b]])
>>> from sage.all import *
>>> from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule
>>> def closed_interval(a, b): return Polyhedron(vertices=[[a], [b]])

A three-dimensional vector space of polyhedra:

sage: I01 = closed_interval(0, 1); I01.rename('conv([0], [1])')
sage: I11 = closed_interval(1, 1); I11.rename('{[1]}')
sage: I12 = closed_interval(1, 2); I12.rename('conv([1], [2])')
sage: basis = [I01, I11, I12]
sage: M = FormalPolyhedraModule(QQ, 1, basis=basis); M
Free module generated by {conv([0], [1]), {[1]}, conv([1], [2])} over Rational Field
sage: M.get_order()
[conv([0], [1]), {[1]}, conv([1], [2])]
>>> from sage.all import *
>>> I01 = closed_interval(Integer(0), Integer(1)); I01.rename('conv([0], [1])')
>>> I11 = closed_interval(Integer(1), Integer(1)); I11.rename('{[1]}')
>>> I12 = closed_interval(Integer(1), Integer(2)); I12.rename('conv([1], [2])')
>>> basis = [I01, I11, I12]
>>> M = FormalPolyhedraModule(QQ, Integer(1), basis=basis); M
Free module generated by {conv([0], [1]), {[1]}, conv([1], [2])} over Rational Field
>>> M.get_order()
[conv([0], [1]), {[1]}, conv([1], [2])]

A one-dimensional subspace; bases of subspaces just use the indexing set \(0, \dots, d-1\), where \(d\) is the dimension:

sage: M_lower = M.submodule([M(I11)]); M_lower
Free module generated by {0} over Rational Field
sage: M_lower.print_options(prefix='S')
sage: M_lower.is_submodule(M)
True
sage: x = M(I01) - 2*M(I11) + M(I12)
sage: M_lower.reduce(x)
[conv([0], [1])] + [conv([1], [2])]
sage: M_lower.retract.domain() is M
True
sage: y = M_lower.retract(M(I11)); y
S[0]
sage: M_lower.lift(y)
[{[1]}]
>>> from sage.all import *
>>> M_lower = M.submodule([M(I11)]); M_lower
Free module generated by {0} over Rational Field
>>> M_lower.print_options(prefix='S')
>>> M_lower.is_submodule(M)
True
>>> x = M(I01) - Integer(2)*M(I11) + M(I12)
>>> M_lower.reduce(x)
[conv([0], [1])] + [conv([1], [2])]
>>> M_lower.retract.domain() is M
True
>>> y = M_lower.retract(M(I11)); y
S[0]
>>> M_lower.lift(y)
[{[1]}]

Quotient space; bases of quotient space are families indexed by elements of the ambient space:

sage: M_mod_lower = M.quotient_module(M_lower); M_mod_lower
Free module generated by {conv([0], [1]), conv([1], [2])} over Rational Field
sage: M_mod_lower.print_options(prefix='Q')
sage: M_mod_lower.retract(x)
Q[conv([0], [1])] + Q[conv([1], [2])]
sage: M_mod_lower.retract(M(I01) - 2*M(I11) + M(I12)) ==  M_mod_lower.retract(M(I01) + M(I12))
True
>>> from sage.all import *
>>> M_mod_lower = M.quotient_module(M_lower); M_mod_lower
Free module generated by {conv([0], [1]), conv([1], [2])} over Rational Field
>>> M_mod_lower.print_options(prefix='Q')
>>> M_mod_lower.retract(x)
Q[conv([0], [1])] + Q[conv([1], [2])]
>>> M_mod_lower.retract(M(I01) - Integer(2)*M(I11) + M(I12)) ==  M_mod_lower.retract(M(I01) + M(I12))
True
degree_on_basis(m)[source]

The degree of an element of the basis is defined as the dimension of the polyhedron.

INPUT:

  • m – an element of the basis (a polyhedron)

EXAMPLES:

sage: from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule
sage: def closed_interval(a, b): return Polyhedron(vertices=[[a], [b]])
sage: I01 = closed_interval(0, 1); I01.rename('conv([0], [1])')
sage: I11 = closed_interval(1, 1); I11.rename('{[1]}')
sage: I12 = closed_interval(1, 2); I12.rename('conv([1], [2])')
sage: I02 = closed_interval(0, 2); I02.rename('conv([0], [2])')
sage: M = FormalPolyhedraModule(QQ, 1, basis=[I01, I11, I12, I02])
>>> from sage.all import *
>>> from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule
>>> def closed_interval(a, b): return Polyhedron(vertices=[[a], [b]])
>>> I01 = closed_interval(Integer(0), Integer(1)); I01.rename('conv([0], [1])')
>>> I11 = closed_interval(Integer(1), Integer(1)); I11.rename('{[1]}')
>>> I12 = closed_interval(Integer(1), Integer(2)); I12.rename('conv([1], [2])')
>>> I02 = closed_interval(Integer(0), Integer(2)); I02.rename('conv([0], [2])')
>>> M = FormalPolyhedraModule(QQ, Integer(1), basis=[I01, I11, I12, I02])

We can extract homogeneous components:

sage: O = M(I01) + M(I11) + M(I12)
sage: O.homogeneous_component(0)
[{[1]}]
sage: O.homogeneous_component(1)
[conv([0], [1])] + [conv([1], [2])]
>>> from sage.all import *
>>> O = M(I01) + M(I11) + M(I12)
>>> O.homogeneous_component(Integer(0))
[{[1]}]
>>> O.homogeneous_component(Integer(1))
[conv([0], [1])] + [conv([1], [2])]

We note that modulo the linear relations of polyhedra, this would only be a filtration, not a grading, as the following example shows:

sage: X = M(I01) + M(I12) - M(I02)
sage: X.degree()
1

sage: Y = M(I11)
sage: Y.degree()
0
>>> from sage.all import *
>>> X = M(I01) + M(I12) - M(I02)
>>> X.degree()
1

>>> Y = M(I11)
>>> Y.degree()
0