Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Project: Sage Days 74
Views: 159
Kernel: SageMath 6.10

Infrastructure for generic code in Sage: categories, axioms, constructions

from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.cartesian_product import CartesianProductsCategory

Parents, Elements, and generic code, the plain Python way

class SemigroupElement: def __pow__(self, k): assert k==8 self = self * self self = self * self self = self * self return self class Stroumph(SemigroupElement): def __init__(self, name): self._name = name def __repr__(self): return self._name def __mul__(self, other): return other def sing(self): print "I sing"
s = Stroumph("Stroumph coquet"); s
Stroumph coquet
t = Stroumph("Stroumph costaud"); t
Stroumph costaud
s*t
Stroumph costaud
s^8
Stroumph coquet
class Semigroup: def cayley_graph(): pass # stuff about generators, ... class BandOfStroumphs(Semigroup): def __iter__(self): yield Stroumph("Stroumph coquet") yield Stroumph("Stroumph costaud") yield Stroumph("Grand stroumph")
for x in BandOfStroumphs(): print x
Stroumph coquet Stroumph costaud Grand stroumph

A hierarchy of abstract classes the usual way

class Set(object): """Methods for sets""" class SetElement(object): """Methods for elements of sets""" class SetMorphism(object): """Methods for set morphisms""" class Magma(Set): """Methods for magmas""" class MagmaElement(SetElement): """Methods for elements of magmas""" class Semigroup(Magma): """Methods for semigroups""" class SemigroupElement(MagmaElement): """Methods for elements of semigroups""" def __pow__(self, k): pass

Refactoring as a category

class MySemigroups(Category): def super_categories(self): # Mathematical information return [Magmas()] class ParentMethods: # This is a mix-in """Methods for semigroups""" class ElementMethods: """Methods for semigroup elements""" def __pow__(self, k): pass class MorphismMethods: """Methods for semigroup morphisms"""
MySemigroups().super_categories()
[Category of magmas]
cls = MySemigroups().parent_class
cls.mro()
[<class '__main__.MySemigroups.parent_class'>, <class 'sage.categories.magmas.Magmas.parent_class'>, <class 'sage.categories.sets_cat.Sets.parent_class'>, <class 'sage.categories.sets_with_partial_maps.SetsWithPartialMaps.parent_class'>, <class 'sage.categories.objects.Objects.parent_class'>, <type 'object'>]

A complete Parent, written the Sage way

class BandOfStroumphs(Parent): def __init__(self): category = Semigroups() & EnumeratedSets().Finite() Parent.__init__(self, category=category) def semigroup_generators(self): return Family(list(self)) def __iter__(self): yield self("Stroumph coquet") yield self("Stroumph costaud") yield self("Grand stroumph") class Element(ElementWrapper): def _mul_(self, other): return other
B = BandOfStroumphs()
B("Stroumph coquet")
'Stroumph coquet'
B.list()
<bound method BandOfStroumphs_with_category.list of <class '__main__.BandOfStroumphs_with_category'>>
s = B.an_element(); s
'Stroumph coquet'
B.cayley_graph()
Image in a Jupyter notebook
TestSuite(B).run(verbose=True, skip="_test_pickling")
running ._test_an_element() . . . pass running ._test_associativity() . . . pass running ._test_cardinality() . . . pass running ._test_category() . . . pass running ._test_elements() . . . Running the test suite of self.an_element() running ._test_category() . . . pass running ._test_eq() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_pickling() . . . fail Traceback (most recent call last): File "/opt/sage-git/local/lib/python2.7/site-packages/sage/misc/sage_unittest.py", line 283, in run test_method(tester = tester) File "sage/structure/sage_object.pyx", line 665, in sage.structure.sage_object.SageObject._test_pickling (/opt/sage-git/src/build/cythonized/sage/structure/sage_object.c:5231) tester.assertEqual(loads(dumps(self)), self) File "sage/structure/sage_object.pyx", line 1130, in sage.structure.sage_object.dumps (/opt/sage-git/src/build/cythonized/sage/structure/sage_object.c:12525) return obj.dumps(compress) File "sage/structure/sage_object.pyx", line 488, in sage.structure.sage_object.SageObject.dumps (/opt/sage-git/src/build/cythonized/sage/structure/sage_object.c:3912) s = cPickle.dumps(self, protocol=2) PicklingError: Can't pickle <class '__main__.Element'>: attribute lookup __main__.Element failed ------------------------------------------------------------ The following tests failed: _test_pickling 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_enumerated_set_contains() . . . pass running ._test_enumerated_set_iter_cardinality() . . . pass running ._test_enumerated_set_iter_list() . . . pass running ._test_eq() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_some_elements() . . . pass The following tests failed: _test_elements
B.category()
Join of Category of finite semigroups and Category of finite enumerated sets
B.categories()
[Join of Category of finite semigroups and Category of finite enumerated sets, Category of finite semigroups, Category of semigroups, Category of magmas, Category of finite enumerated sets, Category of enumerated sets, Category of finite sets, Category of sets, Category of sets with partial maps, Category of objects]
B.__class__.mro()
[<class '__main__.BandOfStroumphs_with_category'>, <class '__main__.BandOfStroumphs'>, <type 'sage.structure.parent.Parent'>, <type 'sage.structure.category_object.CategoryObject'>, <type 'sage.structure.sage_object.SageObject'>, <class 'sage.categories.category.JoinCategory.parent_class'>, <class 'sage.categories.finite_semigroups.FiniteSemigroups.parent_class'>, <class 'sage.categories.semigroups.Semigroups.parent_class'>, <class 'sage.categories.magmas.Magmas.parent_class'>, <class 'sage.categories.finite_enumerated_sets.FiniteEnumeratedSets.parent_class'>, <class 'sage.categories.enumerated_sets.EnumeratedSets.parent_class'>, <class 'sage.categories.finite_sets.FiniteSets.parent_class'>, <class 'sage.categories.sets_cat.Sets.parent_class'>, <class 'sage.categories.sets_with_partial_maps.SetsWithPartialMaps.parent_class'>, <class 'sage.categories.objects.Objects.parent_class'>, <type 'object'>]

Side benefits of having categories as first class objects

C = Semigroups()
C
Category of semigroups
S = C.example()
S??
C.axioms()
frozenset({'Associative'})
C.structure()
frozenset({Category of additive unital additive magmas, Category of additive magmas, Category of euclidean domains, Category of unital magmas, Category of magmas, Category of sets with partial maps, Category of sets})
C = Fields(); C
Category of fields
C.structure()
frozenset({Category of additive unital additive magmas, Category of additive magmas, Category of euclidean domains, Category of unital magmas, Category of magmas, Category of sets with partial maps, Category of sets})
C.axioms()
frozenset({'AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Commutative', 'Distributive', 'Division', 'NoZeroDivisors', 'Unital'})
C = HopfAlgebras(QQ).Graded().Connected().Commutative().WithBasis()
C.structure()
frozenset({Category of additive unital additive magmas, Category of additive magmas, Category of coalgebras over Rational Field, Category of filtered modules over Rational Field, Category of graded modules over Rational Field, Category of hopf algebras over Rational Field, Category of left modules over Rational Field, Category of unital magmas, Category of magmas, Category of right modules over Rational Field, Category of sets with partial maps, Category of sets})
C.axioms()
frozenset({'AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Commutative', 'Connected', 'Distributive', 'Unital', 'WithBasis'})

Operations on categories

  • Adding an axiom

Magmas().Commutative()
Category of commutative magmas
Rings().Commutative()
Category of commutative rings
  • Intersection

Groups() & Sets().Finite()
Category of finite groups
C = (AdditiveMagmas() & Magmas()).Distributive(); C
Category of distributive magmas and additive magmas
C = C.AdditiveAssociative().AdditiveUnital().AdditiveCommutative(); C
Category of additive commutative additive associative additive unital distributive magmas and additive magmas
C = C.Associative().Unital(); C
Category of semirings
C = C.AdditiveInverse(); C
Category of rings
C = C.Division(); C
Category of division rings
C = C.Finite(); C
Category of finite fields
C.axioms()
frozenset({'AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Commutative', 'Distributive', 'Division', 'Finite', 'NoZeroDivisors', 'Unital'})
C.structure()
frozenset({Category of additive unital additive magmas, Category of additive magmas, Category of euclidean domains, Category of unital magmas, Category of magmas, Category of sets with partial maps, Category of sets})