AffineMonoid Class

class stdpairs.AffineMonoid(genset, is_normaliz=False)

Bases: object

A class representing an affine semigroup. An affine semigroup is a semigroup generated by a finite subset of a free abelian group \(\mathbb{Z}^{n}\) for some integer \(n\). The finite subset used for construction is represented as a matrix over \(\mathbb{Z}\) and called the generating matrix.

INPUT:

  • genset – A NumPy.ndarray object with 2-dimensional shape and integer elements or a sage.matrix.matrix_integer_dense object.

  • is_normaliz – A bool object. Default is False. If it is True, generate corresponding polyhedron using PyNormaliz package.

OUTPUT:

  • An AffineMonoid object whose generating set is genset.

EXAMPLE:

sage: #Using ``NumPy``
sage: from stdpairs import AffineMonoid
sage: import numpy
sage: A = numpy.array([[1,2],[0,2]])
sage: A
array([[1, 2],
       [0, 2]])
sage: Q = AffineMonoid(A)
sage: Q
An affine semigroup whose generating set is
[[1 2]
 [0 2]]
sage: #Using ``sage.matrix.matrix_integer_dense``
sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ,[[1,2],[0,2]])
sage: Q = AffineMonoid(A)
sage: Q
An affine semigroup whose generating set is
[[1 2]
 [0 2]]
sage: #Turn on Normaliz and execute its method.
sage: # Be careful that Normaliz does not distinguish
sage: # non-normal semigroup from its saturated one.
sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ,[[1,2],[0,2]])
sage: Q = AffineMonoid(A, True)
sage: Q
An affine semigroup whose generating set is
[[1 2]
 [0 2]]
sage: Q.poly().hilbert_series([1,0])
1/(t^2 - 2*t + 1)
sage: A = matrix(ZZ,[[1,1],[0,1]])
sage: Q = AffineMonoid(A, True)
sage: Q.poly().hilbert_series([1,0])
1/(t^2 - 2*t + 1)

TESTS:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ,[[0,1,1,0],[0,0,1,1],[1,1,1,1]])
sage: Q = AffineMonoid(A)
face(index)

returns a set of generators of the given face represented by a tuple consisting of column indices of the generating matrix.

INPUT:

  • index – A tuple object containing column indices of the generating matrix which consists a face.

OUTPUT:

  • A NumPy.ndarray object representing a face.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.face((0,))
array([[1],
       [0]])
sage: Q.face((1,))
array([[2],
       [2]])
sage: Q.face((0,1,2))
array([[1, 2, 7],
       [0, 2, 4]])
face_lattice()

returns a finite lattice of of tuples representing faces ordered by inclusion. Notes that \((-1,)\) is the least element for every affine monoid, denoting (-1)-dimesional face. This is not the same as \(()\), the 0-dimensional face, which exists only in a pointed affine monoid. See Finite lattice and semilattices for details to use the object.

OUTPUT:

  • face_lattice – A sage.combinat.posets.lattices.FiniteLatticePoset_with_category object.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.face_lattice()
Finite lattice containing 5 elements
sage: list(Q.face_lattice())
[(-1,), (), (0,), (1,), (0, 1, 2)]
gens()

returns the generating set of the given affine monoid as an NumPy.ndarray object with 2-dimensional shape. This may not be the minimal generating set. In case of the pointed affine monoid, use self.mingens() to get the minimal generating set.

OUTPUT:

  • genset – A NumPy.ndarray object with 2-dimensional shape.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.gens()
array([[1, 2, 7],
       [0, 2, 4]])
index_of_face(face_genset)

returns a tuple denoting set of generators of the given face represented by the input face_genset, a matrix consisting of columns representing a face.

INPUT:

  • face_genset – A NumPy 2D-array with integer elements or sage.matrix.matrix_integer_dense object.

OUTPUT:

  • A tuple object representing the generating matrix of a face of the affine semigroup.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: F = matrix(ZZ,[[1],[0]])
sage: Q.index_of_face(F)
(0,)
index_to_face()

returns a dictionary whose keys are tuple denoting column indices of the generating set and whose values are corresponding face of real polyhedron as sage.geometry.polyhedron.face.PolyhedronFace object.

OUTPUT:

  • index_to_facedictionary object.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.index_to_face()
{(): A 0-dimensional face of a Polyhedron in ZZ^2 defined as the convex hull of 1 vertex,
 (-1,): A -1-dimensional face of a Polyhedron in ZZ^2,
 (0,): A 1-dimensional face of a Polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 1 ray,
 (0,
  1,
  2): A 2-dimensional face of a Polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 2 rays,
 (1,): A 1-dimensional face of a Polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 1 ray}
integral_support_vectors()

returns a dictionary whose keys are tuple denoting face as column indices of the generating set, and whose values are an integer inner normal vector of the face. See [MY2020] for details about integral support function.

OUTPUT:

  • integral support vectors – A dictionary object.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.integral_support_vectors()
{(): array([[ 1, -1],
        [ 0,  1]]),
 (0,): array([[0, 1]]),
 (0, 1, 2): array([], dtype=int64),
 (1,): array([[ 1, -1]])}
is_element(col_vector)

Suppose \(A\) is the generating matrix and \(b\) is a vector given by the input col_vector. Then this function returns a sage.matrix.matrix_integer_dense object whose row \(u\) satisfying \(A \cdot u^{t}=b\). In other words, if the input is an element of the given affine semigroup, it returns non-empty matrix whose rows show how to generated the input using the generators of the affine monoid. Otherwise, if the input is not the element of the given affine monoid, it returns the empty matrix.

INPUT:

  • col_vector – A NumPy.ndarray object with 2-dimensional shape with integer coefficients or sage.matrix.matrix_integer_dense object with one column. In other words, this argument should be a vector.

OUTPUT:

  • A sage.matrix.matrix_integer_dense object whose row \(u\) is the solution of the equation \(A \cdot u^{t}=b\).

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.is_element(matrix(ZZ,[[7],[4]]))
[0 0 1]
[3 2 0]
sage: Q.is_element(matrix(ZZ,[[-1],[0]]))
[]
is_empty()

returns True iff it is an empty set as an affine monoid .

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.is_empty()
False
sage: R = AffineMonoid(matrix(ZZ,0))
sage: R.is_empty()
True
is_pointed()

returns True iff the given affine monoid is pointed, i.e., no units except 0.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.is_pointed()
True
sage: R = AffineMonoid(matrix(ZZ,[[1,2,7,-1],[0,2,4,0]]))
sage: R.is_pointed()
False
mingens()

returns the minimal generating set of the given affine monoid as an NumPy.ndarray object with 2-dimensional shape if self is pointed affine monoid. If self is not pointed, then return the generating set with warning message.

OUTPUT:

  • genset – A NumPy.ndarray object with 2-dimensional shape.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.mingens()
array([[1, 2],
       [0, 2]])
poly()

returns a polyhedron in \(\mathbb{Q}^{n}\) generated by the given affine monoid. Notes that even the affine monoid non-normal, this returns only the normal rational cone, i.e., consisting of all lattice points of a rational polyhedron. See Polyhedra for details to use the object returned.

OUTPUT:

  • poly – A sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category object.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.poly()
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 2 rays
sage: B = matrix(ZZ, [[1,1],[0,1]])
sage: R = AffineMonoid(B)
sage: Q.poly() == R.poly()
True
sage: # They are differ as a polyhedron over ZZ, but the same as an object in SageMath.

Especially, if you turn on Normaliz option by construction of your affine semigroup, then you can use all methods in normaliz. For example,

sage: A = matrix(ZZ,[[1,1],[0,1]])
sage: Q = AffineMonoid(A, True)
sage: Q.poly().hilbert_series([1,0])
1/(t^2 - 2*t + 1)

Be careful that Normaliz does not distinguish a non-normal affine semigroup with its saturated one.

save(path_of_file)

saves the given AffineMonoid object as sobj file. See Object Persistence for detail.

INPUT:

  • path_of_file – a string object denoting the path which the object self will be saved as a binary file.

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: from pathlib import Path
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q == loads(dumps(Q))
True
save_txt()

returns strings containing information about the given affine monoid. One can recover it using a global function txt_to_affinemonoid().

EXAMPLE:

sage: from stdpairs import AffineMonoid
sage: from stdpairs import txt_to_affinemonoid
sage: A = matrix(ZZ, [[1,2,7],[0,2,4]])
sage: Q = AffineMonoid(A)
sage: Q.save_txt()
'Q\n1,2,7|0,2,4\n'
sage: R=txt_to_affinemonoid(Q.save_txt())
sage: R == Q
True