教程:实现代数结构

本教程将涵盖四个概念:

  • 赋予自由模和向量空间附加的代数结构

  • 定义态射

  • 定义强制和转换

  • 用几种实现实现代数结构

在本教程结束时,读者应该能够自己重新实现代数的示例,并实现以下几个实现:

sage: Sets().WithRealizations().example()
The subset algebra of {1, 2, 3} over Rational Field

也就是说,我们考虑一个代数 A(S) 其基由子集索引 s 给定集的 SA(S) 它有三个天然的基础: FInOut 在第一个基础上,乘积由索引集的并集给出。这个 In 基数和 Out 基数分别由以下各项定义:

\[In_s = \sum_{t\subset s} F_t \qquad F_s = \sum_{t\supset s} Out_t\]

每个这样的基础都给出了一个实现 A ,其中元素由它们在此基础上的扩展表示。在跑步练习中,我们将逐步实现这个代数及其三个实现,其中包括强制运算和混合算术。

本教程严重依赖于 sage.modules.tutorial_free_modules 。您可能还想阅读不太专业的主题教程 How to implement new algebraic structures

对自由模块进行子类化并包含类别信息

作为预热,我们实现了加法群的群代数 ZZ/5ZZ 。当然,这完全是出于教学目的;群代数已经实现(请参见 ZMod(5).algebra(ZZ) )。回想一下,一个功能齐全的 ZZ -可以使用简单的命令创建此组上的模块::

sage: A = CombinatorialFreeModule(ZZ, Zmod(5), prefix='a')

我们复制相同的,但通过派生一个子类 CombinatorialFreeModule **

sage: class MyCyclicGroupModule(CombinatorialFreeModule):
....:     """An absolutely minimal implementation of a module whose basis is a cyclic group"""
....:     def __init__(self, R, n, *args, **kwargs):
....:         CombinatorialFreeModule.__init__(self, R, Zmod(n), *args, **kwargs)

sage: A = MyCyclicGroupModule(QQ, 6, prefix='a') # or 4 or 5 or 11     ...
sage: a = A.basis()
sage: A.an_element()
2*a[0] + 2*a[1] + 3*a[2]

我们现在想要捐赠给 A 以其自然的乘积结构,得到理想的群代数。要定义乘法,我们应该属于乘法有意义的类别,但情况还不是这样:

sage: A.category()
Category of finite dimensional vector spaces with basis over Rational Field

我们可以查看可用的 Categories 从参考手册的文档中选择,或者我们可以使用自检来查看类别列表,以选择我们需要的类别:

sage: sage.categories.<tab>                   # not tested

一旦我们选择了适当的类别(此处 AlgebrasWithBasis ),可以看一个例子::

sage: E = AlgebrasWithBasis(QQ).example(); E
An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field
sage: e = E.an_element(); e
B[word: ] + 2*B[word: a] + 3*B[word: b] + B[word: bab]

并浏览其代码::

sage: E??                                     # not tested

此代码用作实现新代数的模板。特别是,该模板建议我们需要实现这些方法 product_on_basisone_basis_repr_algebra_generators 。获取此方法列表的另一种方法是询问类别(TODO:找到一个更巧妙的习惯用法)::

sage: from sage.misc.abstract_method import abstract_methods_of_class
sage: abstract_methods_of_class(AlgebrasWithBasis(QQ).element_class)
{'optional': ['_add_', '_mul_'],
 'required': ['__bool__', 'monomial_coefficients']}
sage: abstract_methods_of_class(AlgebrasWithBasis(QQ).parent_class)
{'optional': ['one_basis', 'product_on_basis'], 'required': ['__contains__']}

警告

上面的结果还不一定是完整的;类别中的许多必需方法还没有标记为 abstract_methods() 。我们还建议您浏览此类别的文档: AlgebrasWithBasis

加上这些方法,下面是群代数的最小实现:

sage: class MyCyclicGroupAlgebra(CombinatorialFreeModule):
....:
....:     def __init__(self, R, n, **keywords):
....:         self._group = Zmod(n)
....:         CombinatorialFreeModule.__init__(self, R, self._group,
....:             category=AlgebrasWithBasis(R), **keywords)
....:
....:     def product_on_basis(self, left, right):
....:         return self.monomial( left + right )
....:
....:     def one_basis(self):
....:         return self._group.zero()
....:
....:     def algebra_generators(self):
....:         return Family( [self.monomial( self._group(1) ) ] )
....:
....:     def _repr_(self):
....:         return "Jason's group algebra of %s over %s"%(self._group, self.base_ring())

有关此实施的一些注意事项:

  • 或者,我们可以定义 product 而不是 product_on_basis **

    ....:     # def product(self, left, right):
    ....:     #     return ## something ##
    
  • 为了提高本教程的可读性,我们去掉了所有的文档字符串。当然,所有这些都应该出现在 E

  • 目的 **keywords 就是传递一些选项,比如 prefixCombinatorialFreeModules

让我们来做一些计算:

sage: A = MyCyclicGroupAlgebra(QQ, 2, prefix='a') # or 4 or 5 or 11     ...
sage: a = A.basis();
sage: f = A.an_element();
sage: A, f
(Jason's group algebra of Ring of integers modulo 2 over Rational Field, 2*a[0] + 2*a[1])
sage: f * f
8*a[0] + 8*a[1]
sage: f.<tab>                                 # not tested
sage: f.is_idempotent()
False
sage: A.one()
a[0]
sage: x = A.algebra_generators().first() # Typically x,y,    ... = A.algebra_generators()
sage: [x^i for i in range(4)]
[a[0], a[1], a[0], a[1]]
sage: g = 2*a[1]; (f + g)*f == f*f + g*f
True

这似乎工作得很好,但我们希望将更多的重点放在我们的实现上,以消除潜在的错误。为此,我们将使用 TestSuite ,这是一个为我们的代数执行许多例行测试的工具。

因为我们以交互方式定义类,而不是在一个Python模块中定义类,所以这些测试将会抱怨“pickling”。我们可以通过让SAGE认为类是在模块中定义的来消除这个错误。我们也可以暂时忽略那些失败的测试,或者调用 TestSuite 带着这样的论点 skip='_test_pickling') **

sage: import __main__
sage: __main__.MyCyclicGroupAlgebra = MyCyclicGroupAlgebra

好的,让我们运行测试::

sage: TestSuite(A).run(verbose=True)
running ._test_additive_associativity() . . . pass
running ._test_an_element() . . . pass
running ._test_associativity() . . . pass
running ._test_cardinality() . . . pass
running ._test_category() . . . pass
running ._test_characteristic() . . . pass
running ._test_construction() . . . pass
running ._test_distributivity() . . . pass
running ._test_elements() . . .
  Running the test suite of self.an_element()
  running ._test_category() . . . pass
  running ._test_eq() . . . pass
  running ._test_new() . . . pass
  running ._test_nonzero_equal() . . . pass
  running ._test_not_implemented_methods() . . . pass
  running ._test_pickling() . . . pass
  pass
running ._test_elements_eq_reflexive() . . . pass
running ._test_elements_eq_symmetric() . . . pass
running ._test_elements_eq_transitive() . . . pass
running ._test_elements_neq() . . . pass
running ._test_eq() . . . pass
running ._test_new() . . . pass
running ._test_not_implemented_methods() . . . pass
running ._test_one() . . . pass
running ._test_pickling() . . . pass
running ._test_prod() . . . pass
running ._test_some_elements() . . . pass
running ._test_zero() . . . pass

有关类别的详细信息,请参阅 sage.categories.primer **

sage: sage.categories.primer?                 # not tested

回顾

我们想实现一个代数,所以我们:

  1. 使用以下工具创建基础向量空间 CombinatorialFreeModule

  2. 看了看 sage.categories.<tab> 找到合适的类别

  3. 加载了该类别的示例,并使用 sage.misc.abstract_method.abstract_methods_of_class() ,以查看我们需要编写哪些方法

  4. 将类别信息和其他必要的方法添加到我们的类中

  5. TestSuite 找出潜在的差异

习题

  1. 对…做一点小小的修改 product_on_basis 在“MyCyclicGroupAlgebra”中实现 dual 循环群的群代数而不是它的群代数(所以乘积现在由下式给出 b_fb_g=delta_{f,g}b_f )。

    运行 TestSuite 测试(您可以忽略“pickling”错误)。你注意到什么了吗?

    修复的实施 one 并检查是否 TestSuite 测试现在通过了。

    添加Hopf代数结构。提示:请看下面的示例:

    sage: C = HopfAlgebrasWithBasis(QQ).example()
    
  2. 给定一组 S ,表示::

    sage: S = Set([1,2,3,4,5])
    

    和一个底环,比如::

    sage: R = QQ
    

    实施一个 R -代数::

    sage: F = SubsetAlgebraOnFundamentalBasis(S, R)   # todo: not implemented
    

    有根据的 (b_s)_{s\subset S} 按的子集进行索引 S **

    sage: Subsets(S)
    Subsets of {1, 2, 3, 4, 5}
    

    以及产品定义的位置 b_s b_t = b_{scup t}

态射

为了更好地理解代数空间之间的关系,人们想要考虑它们之间的态射:

sage: A.module_morphism?                      # not tested
sage: A = MyCyclicGroupAlgebra(QQ, 2, prefix='a')
sage: B = MyCyclicGroupAlgebra(QQ, 6, prefix='b')
sage: A, B
(Jason's group algebra of Ring of integers modulo 2 over Rational Field, Jason's group algebra of Ring of integers modulo 6 over Rational Field)
sage: def func_on_basis(g):
....:     r"""
....:     This function is the 'brain' of a (linear) morphism
....:     from A --> B.
....:     The input is the index of basis element of the domain (A).
....:     The output is an element of the codomain (B).
....:     """
....:     if g==1: return B.monomial(Zmod(6)(3))# g==1 in the range A
....:     else:    return B.one()

现在我们可以定义一个态射,它将该函数扩展到 A 按线性度:

sage: phi = A.module_morphism(func_on_basis, codomain=B)
sage: f = A.an_element()
sage: f
2*a[0] + 2*a[1]
sage: phi(f)
2*b[0] + 2*b[3]

锻炼

定义一个新的自由模块 In 其基由以下子集索引 S ,和一个态射 phi 从… InF 定义者

\[\Phi(In_S)=\sum_{t\子集S}F_t\]

对角态射和三角态射

现在我们在此基础上说明如何指定一个给定的态射关于某个阶是对角的或三角形的,这意味着该态射是可逆的,并且Sage能够自动计算逆态射。目前,此功能要求域和协域具有相同的索引集(正在进行中...)。

sage: X = CombinatorialFreeModule(QQ, Partitions(), prefix='x'); x = X.basis();
sage: Y = CombinatorialFreeModule(QQ, Partitions(), prefix='y'); y = Y.basis();

对角线模态射以函数作为自变量,其输入是域的基本元素的索引,其输出是上域的相应基本元素的系数::

sage: def diag_func(p):
....:     if len(p)==0: return 1
....:     else: return p[0]
....:
....:
sage: diag_func(Partition([3,2,1]))
3
sage: X_to_Y = X.module_morphism(diagonal=diag_func, codomain=Y)
sage: f = X.an_element();
sage: f
2*x[[]] + 2*x[[1]] + 3*x[[2]]
sage: X_to_Y(f)
2*y[[]] + 2*y[[1]] + 6*y[[2]]

Python 有趣的事实: ~ 是倒数运算符(但要小心使用int!)::

sage: ~2
1/2
sage: ~(int(2)) # in python this is the bitwise complement: ~x = -x-1
-3

对角线模态射是可逆的::

sage: Y_to_X = ~X_to_Y
sage: f = y[Partition([3])] - 2*y[Partition([2,1])]
sage: f
-2*y[[2, 1]] + y[[3]]
sage: Y_to_X(f)
-x[[2, 1]] + 1/3*x[[3]]
sage: X_to_Y(Y_to_X(f))
-2*y[[2, 1]] + y[[3]]

对于三角态射,就像普通的态射一样,我们需要一个函数,它接受区域的基本元素的索引作为输入,并返回上区域的元素。我们将此函数视为表示线性变换的矩阵的列:

sage: def triang_on_basis(p):
....:     return Y.sum_of_monomials(mu for mu in Partitions(sum(p)) if mu >= p)
....:
sage: triang_on_basis([3,2])
y[[3, 2]] + y[[4, 1]] + y[[5]]
sage: X_to_Y = X.module_morphism(triang_on_basis, triangular='lower', unitriangular=True, codomain=Y)
sage: f = x[Partition([1,1,1])] + 2*x[Partition([3,2])];
sage: f
x[[1, 1, 1]] + 2*x[[3, 2]]
sage: X_to_Y(f)
y[[1, 1, 1]] + y[[2, 1]] + y[[3]] + 2*y[[3, 2]] + 2*y[[4, 1]] + 2*y[[5]]

三角模_态射也是可逆的,即使 XY 都是无限维的::

sage: Y_to_X = ~X_to_Y
sage: f
x[[1, 1, 1]] + 2*x[[3, 2]]
sage: Y_to_X(X_to_Y(f))
x[[1, 1, 1]] + 2*x[[3, 2]]

有关详情,请参阅 ModulesWithBasis.ParentMethods.module_morphism() (并且还 sage.categories.modules_with_basis.TriangularModuleMorphism ):

sage: A.module_morphism?                      # not tested

锻炼

重新定义态射 phi 从前面的练习作为态射,即关于子集的包含是三角形的,并定义逆态射。您可能希望使用以下比较键作为 key 参数为 modules_morphism **

sage: def subset_key(s):
....:     """
....:     A comparison key on sets that gives a linear extension
....:     of the inclusion order.
....:
....:     INPUT:
....:
....:      - ``s`` -- set
....:
....:     EXAMPLES::
....:
....:         sage: sorted(Subsets([1,2,3]), key=subset_key)
....:         [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}]
....:     """
....:     return (len(s), list(s))

胁迫

一旦我们从定义了态射 X to Y ,我们可以将其登记为胁迫。这将允许Sage在我们组合以下元素时自动应用态射 XY 在一起。有关详细信息,请参阅http://sagemath.com/doc/reference/coercion.html。作为训练步骤,让我们首先定义一个态射 XY ,并将其登记为胁迫::

sage: def triang_on_basis(p):
....:     return Y.sum_of_monomials(mu for mu in Partitions(sum(p)) if mu >= p)

sage: triang_on_basis([3,2])
y[[3, 2]] + y[[4, 1]] + y[[5]]
sage: X_to_Y = X.module_morphism(triang_on_basis, triangular='lower', unitriangular=True, codomain=Y)
sage: X_to_Y.<tab>                            # not tested
sage: X_to_Y.register_as_coercion()

现在,我们不仅可以将元素从 XY ,但我们也可以使用以下元素进行混合算术::

sage: Y(x[Partition([3,2])])
y[[3, 2]] + y[[4, 1]] + y[[5]]
sage: Y([2,2,1]) + x[Partition([2,2,1])]
2*y[[2, 2, 1]] + y[[3, 1, 1]] + y[[3, 2]] + y[[4, 1]] + y[[5]]

锻炼

使用的倒数 phi 从实现反向强制 FIn 。重新实施 In 作为一种代数,用乘积方法使它使用 phi 反之亦然。

题外话:对称函数的新基和商

作为应用程序,我们将展示如何结合我们所学的知识来实现对称函数代数的一个新的基和一个商:

sage: SF = SymmetricFunctions(QQ);  # A graded Hopf algebra
sage: h  = SF.homogeneous()         # A particular basis, indexed by partitions (with some additional magic)

所以, h 是一个分次代数,它的基是由划分索引的。更详细地说, h([i]) 是所有次数单项式的总和 i **

sage: h([2]).expand(4)
x0^2 + x0*x1 + x1^2 + x0*x2 + x1*x2 + x2^2 + x0*x3 + x1*x3 + x2*x3 + x3^2

h(mu) = prod( h(p) for p in mu ) **

sage: h([3,2,2,1]) == h([3]) * h([2]) * h([2]) * h([1])
True

Here we define a new basis (X_lambda)_lambda by triangularity with respect to h; namely, we set X_lambda = sum_{mugeq lambda, |mu|=|nu|} h_mu:

sage: class MySFBasis(CombinatorialFreeModule):
....:     r"""
....:     Note: We would typically use SymmetricFunctionAlgebra_generic
....:     for this. This is as an example only.
....:     """
....:
....:     def __init__(self, R, *args, **kwargs):
....:         """ TODO: Informative doc-string and examples """
....:         CombinatorialFreeModule.__init__(self, R, Partitions(), category=AlgebrasWithBasis(R), *args, **kwargs)
....:         self._h = SymmetricFunctions(R).homogeneous()
....:         self._to_h = self.module_morphism( self._to_h_on_basis, triangular='lower', unitriangular=True, codomain=self._h)
....:         self._from_h = ~(self._to_h)
....:         self._to_h.register_as_coercion()
....:         self._from_h.register_as_coercion()
....:
....:     def _to_h_on_basis(self, la):
....:         return self._h.sum_of_monomials(mu for mu in Partitions(sum(la)) if mu >= la)
....:
....:     def product(self, left, right):
....:         return self( self._h(left) * self._h(right) )
....:
....:     def _repr_(self):
....:         return "Jason's basis for symmetric functions over %s"%self.base_ring()
....:
....:     @cached_method
....:     def one_basis(self):
....:         r""" Returns the index of the basis element that is equal to '1'."""
....:         return Partition([])
sage: X = MySFBasis(QQ, prefix='x'); x = X.basis(); h = SymmetricFunctions(QQ).homogeneous()
sage: f = X(h([2,1,1]) - 2*h([2,2]))  # Note the capital X
sage: f
x[[2, 1, 1]] - 3*x[[2, 2]] + 2*x[[3, 1]]
sage: h(f)
h[2, 1, 1] - 2*h[2, 2]
sage: f*f*f
x[[2, 2, 2, 1, 1, 1, 1, 1, 1]] - 7*x[[2, 2, 2, 2, 1, 1, 1, 1]] + 18*x[[2, 2, 2, 2, 2, 1, 1]]
- 20*x[[2, 2, 2, 2, 2, 2]] + 8*x[[3, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
sage: h(f*f)
h[2, 2, 1, 1, 1, 1] - 4*h[2, 2, 2, 1, 1] + 4*h[2, 2, 2, 2]

现在,我们实现通过杀死任何单项对称函数而得到的对称函数的代数的一个商 m_lambda 这样,第一部分的 lambda 大于 k 。看见 Sets.SubcategoryMethods.Subquotients() 有关实施商的更多详细信息,请访问:

sage: class MySFQuotient(CombinatorialFreeModule):
....:     r"""
....:     The quotient of the ring of symmetric functions by the ideal generated
....:     by those monomial symmetric functions whose part is larger than some fixed
....:     number ``k``.
....:     """
....:     def __init__(self, R, k, prefix=None, *args, **kwargs):
....:         CombinatorialFreeModule.__init__(self, R,
....:             Partitions(NonNegativeIntegers(), max_part=k),
....:             prefix = 'mm',
....:             category = Algebras(R).Graded().WithBasis().Quotients(), *args, **kwargs)
....:
....:         self._k = k
....:         self._m = SymmetricFunctions(R).monomial()
....:
....:         self.lift = self.module_morphism(self._m.monomial)
....:         self.retract = self._m.module_morphism(self._retract_on_basis, codomain=self)
....:
....:         self.lift.register_as_coercion()
....:         self.retract.register_as_coercion()
....:
....:     def ambient(self):
....:         return self._m
....:
....:     def _retract_on_basis(self, mu):
....:         r"""
....:         Takes the index of a basis element of a monomial
....:         symmetric function, and returns the projection of that
....:         element to the quotient.
....:         """
....:         if len(mu) > 0 and mu[0] > self._k:
....:             return self.zero()
....:         return self.monomial(mu)
....:
sage: MM = MySFQuotient(QQ, 3)
sage: mm = MM.basis()
sage: m = SymmetricFunctions(QQ).monomial()
sage: P = Partition
sage: g = m[P([3,2,1])] + 2*m[P([3,3])] + m[P([4,2])]; g
m[3, 2, 1] + 2*m[3, 3] + m[4, 2]
sage: f = MM(g); f
mm[[3, 2, 1]] + 2*mm[[3, 3]]
sage: m(f)
m[3, 2, 1] + 2*m[3, 3]

sage: (m(f))^2
8*m[3, 3, 2, 2, 1, 1] + 12*m[3, 3, 2, 2, 2] + 24*m[3, 3, 3, 2, 1] + 48*m[3, 3, 3, 3]
+ 4*m[4, 3, 2, 2, 1] + 4*m[4, 3, 3, 1, 1] + 14*m[4, 3, 3, 2] + 4*m[4, 4, 2, 2]
+ 4*m[4, 4, 3, 1] + 6*m[4, 4, 4] + 4*m[5, 3, 2, 1, 1] + 4*m[5, 3, 2, 2]
+ 12*m[5, 3, 3, 1] + 2*m[5, 4, 2, 1] + 6*m[5, 4, 3] + 4*m[5, 5, 1, 1] + 2*m[5, 5, 2]
+ 4*m[6, 2, 2, 1, 1] + 6*m[6, 2, 2, 2] + 6*m[6, 3, 2, 1] + 10*m[6, 3, 3] + 2*m[6, 4, 1, 1] + 5*m[6, 4, 2] + 4*m[6, 5, 1] + 4*m[6, 6]

sage: f^2
8*mm[[3, 3, 2, 2, 1, 1]] + 12*mm[[3, 3, 2, 2, 2]] + 24*mm[[3, 3, 3, 2, 1]] + 48*mm[[3, 3, 3, 3]]

sage: (m(f))^2 - m(f^2)
4*m[4, 3, 2, 2, 1] + 4*m[4, 3, 3, 1, 1] + 14*m[4, 3, 3, 2] + 4*m[4, 4, 2, 2] + 4*m[4, 4, 3, 1] + 6*m[4, 4, 4] + 4*m[5, 3, 2, 1, 1] + 4*m[5, 3, 2, 2] + 12*m[5, 3, 3, 1] + 2*m[5, 4, 2, 1] + 6*m[5, 4, 3] + 4*m[5, 5, 1, 1] + 2*m[5, 5, 2] + 4*m[6, 2, 2, 1, 1] + 6*m[6, 2, 2, 2] + 6*m[6, 3, 2, 1] + 10*m[6, 3, 3] + 2*m[6, 4, 1, 1] + 5*m[6, 4, 2] + 4*m[6, 5, 1] + 4*m[6, 6]

sage: MM( (m(f))^2 - m(f^2) )
0

用几种实现实现代数结构

现在我们回到子集代数,并用它作为一个例子来说明如何在不同的基之间实现自动强制的代数的几个不同的基。我们已经为这个代数实现了三个基数: FIn ,以及 Out 基地,以及他们之间的胁迫。在实际计算中,通过实现一个对象将这些父级绑定在一起是很方便的 A 这就是抽象代数本身的模型。然后,这对父母 FInOut 将会是 realizationsA ,而 A 将会是一个 parent with realizations 。看见 Sets().WithRealizations 有关预期的用户界面和基本原理的更多信息。

以下是一个简短的模板,突出了整体结构:

class MyAlgebra(Parent, UniqueRepresentation):
    def __init__(self, R, ...):
        category = Algebras(R).Commutative()
        Parent.__init__(self, category=category.WithRealizations())
        # attribute initialization, construction of the morphisms
        # between the bases, ...

    class Bases(Category_realization_of_parent):
        def super_categories(self):
            A = self.base()
            category = Algebras(A.base_ring()).Commutative()
            return [A.Realizations(), category.Realizations().WithBasis()]

        class ParentMethods:
            r"""Code that is common to all bases of the algebra"""

        class ElementMethods:
            r"""Code that is common to elements of all bases of the algebra"""

    class FirstBasis(CombinatorialFreeModule, BindableClass):
        def __init__(self, A):
            CombinatorialFreeModule.__init__(self, ..., category=A.Bases())

        # implementation of the multiplication, the unit, ...

    class SecondBasis(CombinatorialFreeModule, BindableClass):
        def __init__(self, A):
            CombinatorialFreeModule.__init__(self, ..., category=A.Bases())

        # implementation of the multiplication, the unit, ...

这个班级 MyAlgebra 实现交换代数 A 有几个实现,我们在 MyAlgebra 。两个基地班 MyAlgebra.FirstBasisMyAlgebra.SecondBasis 实施不同的实现 A 与元素展开所基于的区别基础相对应的。它们在类别中初始化 MyAlgebra.Bases 在所有的基地中 A ,其作用是找出它们的共同特征。具体地说,这个结构说它们是:

  • 的实现 A

  • 具有特殊基的交换代数的实现

备注

这里有一些冗余:考虑到 A 知道它是一个有实现的交换代数,基础结构原则上可以确定它的实现是交换代数。如果这样做了,那么就有可能实现 Bases.super_categories 通过返回::

[A.Realizations().WithBasis()]

然而,这一点尚未实施。

备注

继承自 BindableCass 只是提供了语法上的糖:它使 MyAlgebras().FirstBasis() 一种简写的 MyAlgebras.FirstBasis(MyAlgebras().FirstBasis()) (绑定行为)。这个班级 Bases 从继承此绑定行为 Category_realization_of_parent ,这就是为什么我们可以写 MyAlgebras().Bases 而不是 MyAlgebras.Bases(MyAlgebras())

备注

通常情况下,所有碱基的构造函数都非常相似,如果不是完全相同的话;所以我们想要将其分解出来。恼人的是,将构造函数放入 Bases.ParentMethods 不起作用,因为这是一个抽象类,而构造函数处理数据结构的具体实现。同样,如果只需要指定基类继承一次就更好了,但这不能进入代码 Bases 出于同样的原因。

当前推荐的解决方案是有一个额外的类 Basis 这就排除了不同基地的共同具体特征:

...

class Basis(CombinatorialFreeModule, BindableClass):
    def __init__(self, A):
        CombinatorialFreeModule.__init__(self, ..., category=A.Bases())

class FirstBasis(Basis):
    ...

class SecondBasis(Basis):
    ...

该解决方案有效但并不是最优的,因为要在两个基本代码之间共享特征,代码需要进入两个位置, BasisBases ,分别取决于它们是具体的还是抽象的。

我们现在建议读者浏览以下示例的完整代码,该示例是一个完整的模板,用于构建具有实现的新父级:

sage: A = Sets().WithRealizations().example(); A
The subset algebra of {1, 2, 3} over Rational Field

sage: A??                                     # not implemented

回顾

祝贺你读到这一步!

现在,我们已经完整地了解了实现具有多种实现的代数所需的功能。实现的基础结构并不特定地与代数捆绑在一起;我们所学的内容在必要时完全适用于一般情况,例如,用于实现具有几个实现的群。