Quotients of modules with basis¶
- class sage.modules.with_basis.subquotient.QuotientModuleWithBasis(submodule, category, *args, **opts)[source]¶
- Bases: - CombinatorialFreeModule- A class for quotients of a module with basis by a submodule. - INPUT: - submodule– a submodule of- self
- category– a category (default:- ModulesWithBasis(submodule.base_ring()))
 - submoduleshould be a free submodule admitting a basis in unitriangular echelon form. Typically- submoduleis a- SubmoduleWithBasisas returned by- Modules.WithBasis.ParentMethods.submodule().- The - liftmethod should have a method- .cokernel_basis_indicesthat computes the indexing set of a subset \(B\) of the basis of- selfthat spans some supplementary of- submodulein- self(typically the non characteristic columns of the aforementioned echelon form).- submoduleshould further implement a- submodule.reduce(x)method that returns the unique element in the span of \(B\) which is equivalent to \(x\) modulo- submodule.- This is meant to be constructed via - Modules.WithBasis.FiniteDimensional.ParentMethods.quotient_module()- This differs from - sage.rings.quotient_ring.QuotientRingin the following ways:- submoduleneeds not be an ideal. If it is, the transportation of the ring structure is taken care of by the- Subquotientscategories.
- Thanks to - .cokernel_basis_indices, we know the indices of a basis of the quotient, and elements are represented directly in the free module spanned by those indices rather than by wrapping elements of the ambient space.
 - There is room for sharing more code between those two implementations and generalizing them. See Issue #18204. - See also - Modules.WithBasis.ParentMethods.submodule()
- Modules.WithBasis.FiniteDimensional.ParentMethods.quotient_module()
- sage.rings.quotient_ring.QuotientRing
 - ambient()[source]¶
- Return the ambient space of - self.- EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x'); x = X.basis() sage: Y = X.quotient_module((x[0]-x[1], x[1]-x[2])) sage: Y.ambient() is X True - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(3)), prefix='x'); x = X.basis() >>> Y = X.quotient_module((x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)])) >>> Y.ambient() is X True 
 - lift(x)[source]¶
- Lift - xto the ambient space of- self.- INPUT: - x– an element of- self
 - EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x'); x = X.basis() sage: Y = X.quotient_module((x[0]-x[1], x[1]-x[2])); y = Y.basis() sage: Y.lift(y[2]) x[2] - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(3)), prefix='x'); x = X.basis() >>> Y = X.quotient_module((x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)])); y = Y.basis() >>> Y.lift(y[Integer(2)]) x[2] 
 - retract(x)[source]¶
- Retract an element of the ambient space by projecting it back to - self.- INPUT: - x– an element of the ambient space of- self
 - EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x'); x = X.basis() sage: Y = X.quotient_module((x[0]-x[1], x[1]-x[2])); y = Y.basis() sage: Y.print_options(prefix='y') sage: Y.retract(x[0]) y[2] sage: Y.retract(x[1]) y[2] sage: Y.retract(x[2]) y[2] - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(3)), prefix='x'); x = X.basis() >>> Y = X.quotient_module((x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)])); y = Y.basis() >>> Y.print_options(prefix='y') >>> Y.retract(x[Integer(0)]) y[2] >>> Y.retract(x[Integer(1)]) y[2] >>> Y.retract(x[Integer(2)]) y[2] 
 
- class sage.modules.with_basis.subquotient.SubmoduleWithBasis(basis, support_order, ambient, unitriangular, category, *args, **opts)[source]¶
- Bases: - CombinatorialFreeModule- A base class for submodules of a ModuleWithBasis spanned by a (possibly infinite) basis in echelon form. - INPUT: - basis– a family of elements in echelon form in some- module with basis\(V\), or data that can be converted into such a family
- support_order– an ordering of the support of- basisexpressed in- ambientgiven as a list
- unitriangular– if the lift morphism is unitriangular
- ambient– the ambient space \(V\)
- category– a category
 - Further arguments are passed down to - CombinatorialFreeModule.- This is meant to be constructed via - Modules.WithBasis.ParentMethods.submodule().- See also - Modules.WithBasis.ParentMethods.submodule()
 - ambient()[source]¶
- Return the ambient space of - self.- EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(3)); x = X.basis() sage: Y = X.submodule((x[0]-x[1], x[1]-x[2])) sage: Y.ambient() is X True - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(3))); x = X.basis() >>> Y = X.submodule((x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)])) >>> Y.ambient() is X True 
 - intersection(other)[source]¶
- Return the intersection of - selfand- other.- EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(4)); x = X.basis() sage: F = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]]) sage: G = X.submodule([x[0]-x[2]]) sage: H = X.submodule([x[0]-x[1], x[2]]) sage: FG = F & G; FG Free module generated by {0} over Rational Field sage: [FG.lift(b) for b in FG.basis()] [B[0] - B[2]] sage: FH = F & H; FH Free module generated by {0} over Rational Field sage: [FH.lift(b) for b in FH.basis()] [B[0] - B[1]] sage: GH = G & H; GH Free module generated by {} over Rational Field sage: [GH.lift(b) for b in GH.basis()] [] sage: F.intersection(X) is F True - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(4))); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]]) >>> G = X.submodule([x[Integer(0)]-x[Integer(2)]]) >>> H = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(2)]]) >>> FG = F & G; FG Free module generated by {0} over Rational Field >>> [FG.lift(b) for b in FG.basis()] [B[0] - B[2]] >>> FH = F & H; FH Free module generated by {0} over Rational Field >>> [FH.lift(b) for b in FH.basis()] [B[0] - B[1]] >>> GH = G & H; GH Free module generated by {} over Rational Field >>> [GH.lift(b) for b in GH.basis()] [] >>> F.intersection(X) is F True 
 - is_equal_subspace(other)[source]¶
- Return whether - selfis an equal submodule to- other.- Note - This is the mathematical notion of equality (as sets that are isomorphic as vector spaces), which is weaker than the \(==\) which takes into account things like the support order. - INPUT: - other– another submodule of the same ambient module or the ambient module itself
 - EXAMPLES: - sage: R.<z> = LaurentPolynomialRing(QQ) sage: X = CombinatorialFreeModule(R, range(4)); x = X.basis() sage: F = X.submodule([x[0]-x[1], z*x[1]-z*x[2], z^2*x[2]-z^2*x[3]]) sage: G = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]]) sage: H = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]], support_order=(3,2,1,0)) sage: F.is_equal_subspace(F) True sage: F == G False sage: F.is_equal_subspace(G) True sage: F.is_equal_subspace(H) True sage: G == H # different support orders False sage: G.is_equal_subspace(H) True - >>> from sage.all import * >>> R = LaurentPolynomialRing(QQ, names=('z',)); (z,) = R._first_ngens(1) >>> X = CombinatorialFreeModule(R, range(Integer(4))); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], z*x[Integer(1)]-z*x[Integer(2)], z**Integer(2)*x[Integer(2)]-z**Integer(2)*x[Integer(3)]]) >>> G = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]]) >>> H = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]], support_order=(Integer(3),Integer(2),Integer(1),Integer(0))) >>> F.is_equal_subspace(F) True >>> F == G False >>> F.is_equal_subspace(G) True >>> F.is_equal_subspace(H) True >>> G == H # different support orders False >>> G.is_equal_subspace(H) True - sage: X = CombinatorialFreeModule(QQ, ZZ); x = X.basis() sage: F = X.submodule([x[0]-x[1], x[1]-x[3]]) sage: G = X.submodule([x[0]-x[1], x[2]]) sage: H = X.submodule([x[0]+x[1], x[1]+3*x[2]]) sage: Hp = X.submodule([x[0]+x[1], x[1]+3*x[2]], prefix='Hp') sage: F.is_equal_subspace(X) False sage: F.is_equal_subspace(G) False sage: G.is_equal_subspace(H) False sage: H == Hp False sage: H.is_equal_subspace(Hp) True - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, ZZ); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(3)]]) >>> G = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(2)]]) >>> H = X.submodule([x[Integer(0)]+x[Integer(1)], x[Integer(1)]+Integer(3)*x[Integer(2)]]) >>> Hp = X.submodule([x[Integer(0)]+x[Integer(1)], x[Integer(1)]+Integer(3)*x[Integer(2)]], prefix='Hp') >>> F.is_equal_subspace(X) False >>> F.is_equal_subspace(G) False >>> G.is_equal_subspace(H) False >>> H == Hp False >>> H.is_equal_subspace(Hp) True 
 - is_submodule(other)[source]¶
- Return whether - selfis a submodule of- other.- INPUT: - other– another submodule of the same ambient module or the ambient module itself
 - EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(4)); x = X.basis() sage: F = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]]) sage: G = X.submodule([x[0]-x[2]]) sage: H = X.submodule([x[0]-x[1], x[2]]) sage: F.is_submodule(X) True sage: G.is_submodule(F) True sage: H.is_submodule(F) False sage: H.is_submodule(G) False - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(4))); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]]) >>> G = X.submodule([x[Integer(0)]-x[Integer(2)]]) >>> H = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(2)]]) >>> F.is_submodule(X) True >>> G.is_submodule(F) True >>> H.is_submodule(F) False >>> H.is_submodule(G) False - Infinite dimensional examples: - sage: X = CombinatorialFreeModule(QQ, ZZ); x = X.basis() sage: F = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]]) sage: G = X.submodule([x[0]-x[2]]) sage: H = X.submodule([x[0]-x[1]]) sage: F.is_submodule(X) True sage: G.is_submodule(F) True sage: H.is_submodule(F) True sage: H.is_submodule(G) False - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, ZZ); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]]) >>> G = X.submodule([x[Integer(0)]-x[Integer(2)]]) >>> H = X.submodule([x[Integer(0)]-x[Integer(1)]]) >>> F.is_submodule(X) True >>> G.is_submodule(F) True >>> H.is_submodule(F) True >>> H.is_submodule(G) False - Different ambient spaces: - sage: X = CombinatorialFreeModule(QQ, range(4)); x = X.basis() sage: F = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]]) sage: Y = CombinatorialFreeModule(QQ, range(6)); y = Y.basis() sage: G = Y.submodule([y[0]-y[1], y[1]-y[2], y[2]-y[3]]) sage: F.is_submodule(G) False - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(4))); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]]) >>> Y = CombinatorialFreeModule(QQ, range(Integer(6))); y = Y.basis() >>> G = Y.submodule([y[Integer(0)]-y[Integer(1)], y[Integer(1)]-y[Integer(2)], y[Integer(2)]-y[Integer(3)]]) >>> F.is_submodule(G) False 
 - lift()[source]¶
- The lift (embedding) map from - selfto the ambient space.- EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x'); x = X.basis() sage: Y = X.submodule((x[0]-x[1], x[1]-x[2]), already_echelonized=True); y = Y.basis() sage: Y.lift Generic morphism: From: Free module generated by {0, 1} over Rational Field To: Free module generated by {0, 1, 2} over Rational Field sage: [ Y.lift(u) for u in y ] [x[0] - x[1], x[1] - x[2]] sage: (y[0] + y[1]).lift() x[0] - x[2] - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(3)), prefix='x'); x = X.basis() >>> Y = X.submodule((x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)]), already_echelonized=True); y = Y.basis() >>> Y.lift Generic morphism: From: Free module generated by {0, 1} over Rational Field To: Free module generated by {0, 1, 2} over Rational Field >>> [ Y.lift(u) for u in y ] [x[0] - x[1], x[1] - x[2]] >>> (y[Integer(0)] + y[Integer(1)]).lift() x[0] - x[2] 
 - reduce()[source]¶
- The reduce map. - This map reduces elements of the ambient space modulo this submodule. - EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x'); x = X.basis() sage: Y = X.submodule((x[0]-x[1], x[1]-x[2]), already_echelonized=True) sage: Y.reduce Generic endomorphism of Free module generated by {0, 1, 2} over Rational Field sage: Y.reduce(x[1]) x[2] sage: Y.reduce(2*x[0] + x[1]) 3*x[2] - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(3)), prefix='x'); x = X.basis() >>> Y = X.submodule((x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)]), already_echelonized=True) >>> Y.reduce Generic endomorphism of Free module generated by {0, 1, 2} over Rational Field >>> Y.reduce(x[Integer(1)]) x[2] >>> Y.reduce(Integer(2)*x[Integer(0)] + x[Integer(1)]) 3*x[2] 
 - retract()[source]¶
- The retract map from the ambient space. - EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x'); x = X.basis() sage: Y = X.submodule((x[0]-x[1], x[1]-x[2]), already_echelonized=True) sage: Y.print_options(prefix='y') sage: Y.retract Generic morphism: From: Free module generated by {0, 1, 2} over Rational Field To: Free module generated by {0, 1} over Rational Field sage: Y.retract(x[0] - x[2]) y[0] + y[1] - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(3)), prefix='x'); x = X.basis() >>> Y = X.submodule((x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)]), already_echelonized=True) >>> Y.print_options(prefix='y') >>> Y.retract Generic morphism: From: Free module generated by {0, 1, 2} over Rational Field To: Free module generated by {0, 1} over Rational Field >>> Y.retract(x[Integer(0)] - x[Integer(2)]) y[0] + y[1] 
 - subspace(gens, *args, **opts)[source]¶
- The submodule of the ambient space spanned by a finite set of generators - gens(as a submodule).- INPUT: - gens– list or family of elements of- self
 - For additional optional arguments, see - ModulesWithBasis.ParentMethods.submodule().- EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(4), prefix='X'); x = X.basis() sage: F = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]], prefix='F'); f = F.basis() sage: U = F.submodule([f[0] + 2*f[1] - 5*f[2], f[1] + 2*f[2]]); U Free module generated by {0, 1} over Rational Field sage: [U.lift(u) for u in U.basis()] [F[0] - 9*F[2], F[1] + 2*F[2]] sage: V = F.subspace([f[0] + 2*f[1] - 5*f[2], f[1] + 2*f[2]]); V Free module generated by {0, 1} over Rational Field sage: [V.lift(u) for u in V.basis()] [X[0] - 9*X[2] + 8*X[3], X[1] + 2*X[2] - 3*X[3]] - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(4)), prefix='X'); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]], prefix='F'); f = F.basis() >>> U = F.submodule([f[Integer(0)] + Integer(2)*f[Integer(1)] - Integer(5)*f[Integer(2)], f[Integer(1)] + Integer(2)*f[Integer(2)]]); U Free module generated by {0, 1} over Rational Field >>> [U.lift(u) for u in U.basis()] [F[0] - 9*F[2], F[1] + 2*F[2]] >>> V = F.subspace([f[Integer(0)] + Integer(2)*f[Integer(1)] - Integer(5)*f[Integer(2)], f[Integer(1)] + Integer(2)*f[Integer(2)]]); V Free module generated by {0, 1} over Rational Field >>> [V.lift(u) for u in V.basis()] [X[0] - 9*X[2] + 8*X[3], X[1] + 2*X[2] - 3*X[3]] 
 - subspace_sum(other)[source]¶
- Return the sum of - selfand- other.- EXAMPLES: - sage: X = CombinatorialFreeModule(QQ, range(4)); x = X.basis() sage: F = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]]) sage: G = X.submodule([x[0]-x[2]]) sage: H = X.submodule([x[0]-x[1], x[2]]) sage: FG = F + G; FG Free module generated by {0, 1, 2} over Rational Field sage: [FG.lift(b) for b in FG.basis()] [B[0] - B[3], B[1] - B[3], B[2] - B[3]] sage: FH = F + H; FH Free module generated by {0, 1, 2, 3} over Rational Field sage: [FH.lift(b) for b in FH.basis()] [B[0], B[1], B[2], B[3]] sage: GH = G + H; GH Free module generated by {0, 1, 2} over Rational Field sage: [GH.lift(b) for b in GH.basis()] [B[0], B[1], B[2]] - >>> from sage.all import * >>> X = CombinatorialFreeModule(QQ, range(Integer(4))); x = X.basis() >>> F = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(1)]-x[Integer(2)], x[Integer(2)]-x[Integer(3)]]) >>> G = X.submodule([x[Integer(0)]-x[Integer(2)]]) >>> H = X.submodule([x[Integer(0)]-x[Integer(1)], x[Integer(2)]]) >>> FG = F + G; FG Free module generated by {0, 1, 2} over Rational Field >>> [FG.lift(b) for b in FG.basis()] [B[0] - B[3], B[1] - B[3], B[2] - B[3]] >>> FH = F + H; FH Free module generated by {0, 1, 2, 3} over Rational Field >>> [FH.lift(b) for b in FH.basis()] [B[0], B[1], B[2], B[3]] >>> GH = G + H; GH Free module generated by {0, 1, 2} over Rational Field >>> [GH.lift(b) for b in GH.basis()] [B[0], B[1], B[2]]