|
1 | 1 | """
|
2 | 2 | Axioms
|
3 | 3 |
|
4 |
| -See :mod:`sage.categories.primer` for an introduction to axioms, and |
5 |
| -:class:`CategoryWithAxiom` for how to implement axioms and the |
6 |
| -documentation of the axiom infrastructure. |
| 4 | +This documentation covers how to implement axioms and proceeds with an |
| 5 | +overview of the implementation of the axiom infrastructure. It assumes |
| 6 | +that the reader is familiar with the :mod:`category primer |
| 7 | +<sage.categories.primer>`, and in particular its :ref:`section about |
| 8 | +axioms <category-primer-axioms>`. |
| 9 | +
|
| 10 | +Implementing axioms |
| 11 | +------------------- |
| 12 | +
|
| 13 | +To start with, assume one wants to provide code for the objects of |
| 14 | +some existing category ``Cs()`` that satisfy some existing axiom |
| 15 | +``A``. All one needs to do is define in ``Cs`` a nested class |
| 16 | +inheriting from :class:`CategoryWithAxiom`:: |
| 17 | +
|
| 18 | + sage: from sage.categories.category_with_axiom import CategoryWithAxiom |
| 19 | + sage: class Cs(Category): |
| 20 | + ....: def super_categories(self): |
| 21 | + ....: return [Sets()] |
| 22 | + ....: class Finite(CategoryWithAxiom): |
| 23 | + ....: class ParentMethods: |
| 24 | + ....: def foo(self): |
| 25 | + ....: print "I am a method on finite C's" |
| 26 | +
|
| 27 | +:: |
| 28 | +
|
| 29 | + sage: Cs().Finite() |
| 30 | + Category of finite cs |
| 31 | + sage: Cs().Finite().super_categories() |
| 32 | + [Category of finite sets, Category of cs] |
| 33 | + sage: Cs().Finite().all_super_categories() |
| 34 | + [Category of finite cs, Category of finite sets, |
| 35 | + Category of cs, Category of sets, ...] |
| 36 | + sage: Cs().Finite().axioms() |
| 37 | + frozenset(['Finite']) |
| 38 | +
|
| 39 | +Now a parent declared in the category ``Cs().Finite()`` inherits from |
| 40 | +all the methods of finite sets and of finite C's:: |
| 41 | +
|
| 42 | + sage: P = Parent(category=Cs().Finite()) |
| 43 | + sage: P.is_finite() |
| 44 | + True |
| 45 | + sage: P.foo() |
| 46 | + I am a method on finite C's |
| 47 | +
|
| 48 | +Note that this is following the same idiom as for |
| 49 | +:mod:`covariant functorial constructions |
| 50 | +<sage.categories.covariant_functorial_construction>`. |
| 51 | +The category ``Cs().Finite()`` is aware that it has been constructed |
| 52 | +from the category ``Cs()`` and adding the axiom ``Finite``:: |
| 53 | +
|
| 54 | + sage: Cs().Finite().base_category() |
| 55 | + Category of cs |
| 56 | + sage: Cs().Finite()._axiom |
| 57 | + 'Finite' |
| 58 | +
|
| 59 | +Over time, the code of the nested class ``Cs.Finite`` may become large |
| 60 | +and too cumbersome to keep as a nested class of ``Cs``. Or the |
| 61 | +category with axiom may have a name of its own in the litterature, |
| 62 | +like *semigroups* rather than *associative magmas*, or *fields* rather |
| 63 | +than *commutative division rings*. In this case, the category with |
| 64 | +axiom can be put in a separate file, with just a link from ``Cs``:: |
| 65 | +
|
| 66 | + sage: class Cs(Category): |
| 67 | + ....: def super_categories(self): |
| 68 | + ....: return [Sets()] |
| 69 | + ....: Finite = LazyImport('sage.categories.finite_cs', 'FiniteCs') |
| 70 | +
|
| 71 | +For a working example look up the code of the class |
| 72 | +:class:`FiniteSets` and the link to it in :class:`Sets`. |
| 73 | +
|
| 74 | +In this scenario, the category with axiom can equivalently be created |
| 75 | +directly or through its base category:: |
| 76 | +
|
| 77 | + sage: FiniteSets() |
| 78 | + Category of finite sets |
| 79 | + sage: Sets().Finite() |
| 80 | + Category of finite sets |
| 81 | + sage: Sets().Finite() is FiniteSets() |
| 82 | + True |
| 83 | +
|
| 84 | +For the former idiom to work, and with the current implementation of |
| 85 | +axioms, the class :class:`FiniteSets` needs to be aware of the class |
| 86 | +of its base category (here, :class:`Sets`) and of the axiom (here, |
| 87 | +``Finite``):: |
| 88 | +
|
| 89 | + sage: FiniteSets._base_category_class_and_axiom |
| 90 | + (sage.categories.sets_cat.Sets, 'Finite') |
| 91 | + sage: Semigroups._base_category_class_and_axiom |
| 92 | + [sage.categories.magmas.Magmas, 'Associative'] |
| 93 | + sage: Fields._base_category_class_and_axiom |
| 94 | + (sage.categories.division_rings.DivisionRings, 'Commutative') |
| 95 | + sage: FiniteDimensionalAlgebrasWithBasis._base_category_class_and_axiom |
| 96 | + (sage.categories.algebras_with_basis.AlgebrasWithBasis, 'FiniteDimensional') |
| 97 | +
|
| 98 | +As a syntactic sugar, Sage tries some obvious heuristics to guess |
| 99 | +those from the name of the category with axiom (see |
| 100 | +:func:`base_category_class_and_axiom` for the details). When this |
| 101 | +fails, typically because the category has a name of its own like |
| 102 | +:class:`Fields`, the attribute ``_base_category_class_and_axiom`` |
| 103 | +should be set explicitly. See for example the code of the classes |
| 104 | +:class:`Semigroups` or :class:`Fields`. |
| 105 | +
|
| 106 | +.. TODO:: |
| 107 | +
|
| 108 | + - Checking if the appropriate category does not exist |
| 109 | + - Handling of multiple axioms, tree structure of the code |
| 110 | + - Implementing a new axiom |
| 111 | + - Deduction rules |
| 112 | + - Specifications |
| 113 | + - Algorithm for adding axioms and computing intersections |
| 114 | + - Flesh out the design goals |
| 115 | +
|
| 116 | +Specifications |
| 117 | +^^^^^^^^^^^^^^ |
| 118 | +
|
| 119 | +*** The base category of an AdjectiveCategory is not a JoinCategory |
| 120 | +*** If A is a category with a given axiom (e.g. from one of its super categories) |
| 121 | + then that axiom does not appear in A (and recursively in any nested subcategory) |
| 122 | +*** The set of categories for which an axiom is defined is a lower set |
| 123 | + The same name can't be used for two axioms with different meanings. |
| 124 | +*** DONE The super categories of a category are not join categories |
| 125 | + - State "DONE" from "" [2013-06-05 mer. 08:44] |
| 126 | +*** DONE self.is_subcategory( Category.join(self.super_categories()) ) |
| 127 | + - State "DONE" from "" [2013-06-05 mer. 08:44] |
| 128 | +*** DONE self._cmp_key() > other._cmp_key() for other in self.super_categories() |
| 129 | +*** DONE Any super category of a CategoryWithParameters should either be a CategoryWithParameters or a CategorySingleton |
| 130 | +*** DONE axiom categories of singleton categories should be singletons |
| 131 | +*** DONE axiom categories of CategoryOverBaseRing should be categories over base ring. |
| 132 | +*** DEFERRED should join categories of CategoryOverBaseRing be categories over base ring? |
| 133 | + In the mean time, a base_ring method has been added to most of those; see Modules.SubcategoryMethods |
| 134 | +*** DEFERRED Functorial construction categories (Graded, CartesianProducts, ...) of singleton categories should be singleton categories |
| 135 | + Nothing difficult, but this will need to rework the current "no |
| 136 | + subclass of a concrete class" assertion test of Category_singleton.__classcall__ |
| 137 | +*** DEFERRED covariant functorial construction categories over a category over base ring should be a category over base ring |
| 138 | +
|
| 139 | +
|
| 140 | +
|
| 141 | +Design goals |
| 142 | +^^^^^^^^^^^^ |
| 143 | +
|
| 144 | + - Flexibility in the code layout: the category of, say, finite |
| 145 | + sets can be implemented either within the Sets category (in a |
| 146 | + nested class Sets.Finite), or in a separate file (typically in |
| 147 | + a class FiniteSets in a lazily imported module |
| 148 | + sage.categories.finite_sets). |
| 149 | +
|
| 150 | +.. NOTE:: |
| 151 | +
|
| 152 | + The constructor for instances of this class takes as input the |
| 153 | + base category. Hence, they should in principle be constructed |
| 154 | + as:: |
| 155 | +
|
| 156 | + sage: FiniteSets(Sets()) # todo: not tested |
| 157 | + Category of finite sets |
| 158 | +
|
| 159 | + sage: Sets.Finite(Sets()) # todo: not tested |
| 160 | + Category of finite sets |
| 161 | +
|
| 162 | + None of those syntaxes are really practical for the user. So instead, |
| 163 | + this object is to be constructed using any of the following idioms:: |
| 164 | +
|
| 165 | + sage: Sets()._with_axiom('Finite') |
| 166 | + Category of finite sets |
| 167 | + sage: FiniteSets() |
| 168 | + Category of finite sets |
| 169 | + sage: Sets().Finite() |
| 170 | + Category of finite sets |
| 171 | +
|
| 172 | + The later two are implemented using respectively |
| 173 | + :meth:`__classcall__` and :meth:`__classget__` which see. |
| 174 | +
|
| 175 | +.. TODO: |
| 176 | +
|
| 177 | + - Implement compatibility axiom / functorial constructions |
| 178 | +
|
| 179 | + E.g. join(A.CartesianProducts(), B.CartesianProducts()) = join(A,B).CartesianProducts() |
| 180 | +
|
| 181 | + - An axiom category of a singleton category is automatically a |
| 182 | + singleton category. Should this also be implemented for |
| 183 | + categories with base ring? |
| 184 | +
|
| 185 | + - Once full subcategories are implemented (see :trac:`10668`), |
| 186 | + make category with axioms be such. Should all full subcategories |
| 187 | + be implemented in term of axioms? |
7 | 188 |
|
8 | 189 | TESTS:
|
9 | 190 |
|
@@ -307,192 +488,11 @@ class CategoryWithAxiom(Category):
|
307 | 488 | r"""
|
308 | 489 | An abstract class for categories obtained by adding an axiom to a base category.
|
309 | 490 |
|
310 |
| - This documentation covers how to implement axioms and proceeds |
311 |
| - with an overview of the implementation of the axiom |
312 |
| - infrastructure. It assumes that the reader is familiar with the |
313 |
| - :mod:`category primer <sage.categories.primer>`, and in particular |
314 |
| - its :ref:`section about axioms <category-primer-axioms>`. |
315 |
| -
|
316 |
| - Implementing axioms |
317 |
| - ------------------- |
318 |
| -
|
319 |
| - To start with, assume one wants to provide code for the objects of |
320 |
| - some existing category ``Cs()`` that satisfy some existing axiom |
321 |
| - ``A``. All one needs to do is define in `Cs` a nested class |
322 |
| - inheriting from :class:`CategoryWithAxiom`:: |
323 |
| -
|
324 |
| - sage: from sage.categories.category_with_axiom import CategoryWithAxiom |
325 |
| - sage: class Cs(Category): |
326 |
| - ....: def super_categories(self): |
327 |
| - ....: return [Sets()] |
328 |
| - ....: class Finite(CategoryWithAxiom): |
329 |
| - ....: class ParentMethods: |
330 |
| - ....: def foo(self): |
331 |
| - ....: print "I am a method on finite C's" |
332 |
| -
|
333 |
| - :: |
334 |
| -
|
335 |
| - sage: Cs().Finite() |
336 |
| - Category of finite cs |
337 |
| - sage: Cs().Finite().super_categories() |
338 |
| - [Category of finite sets, Category of cs] |
339 |
| - sage: Cs().Finite().all_super_categories() |
340 |
| - [Category of finite cs, Category of finite sets, |
341 |
| - Category of cs, Category of sets, ...] |
342 |
| - sage: Cs().Finite().axioms() |
343 |
| - frozenset(['Finite']) |
344 |
| -
|
345 |
| - Now a parent declared in the category ``Cs().Finite()`` inherits |
346 |
| - from all the methods of finite sets and of finite C's:: |
347 |
| -
|
348 |
| - sage: P = Parent(category=Cs().Finite()) |
349 |
| - sage: P.is_finite() |
350 |
| - True |
351 |
| - sage: P.foo() |
352 |
| - I am a method on finite C's |
353 |
| -
|
354 |
| - Note that this is following the same idiom as for |
355 |
| - :mod:`covariant functorial constructions |
356 |
| - <sage.categories.covariant_functorial_construction>`. |
357 |
| - The category ``Cs().Finite()`` is aware that it has been |
358 |
| - constructed from the category ``Cs()`` and adding the axiom |
359 |
| - ``Finite``:: |
360 |
| -
|
361 |
| - sage: Cs().Finite().base_category() |
362 |
| - Category of cs |
363 |
| - sage: Cs().Finite()._axiom |
364 |
| - 'Finite' |
365 |
| -
|
366 |
| - Over time, the code of the nested class ``Cs.Finite`` may become |
367 |
| - large and too cumbersome to keep as a nested class of `C`. Or the |
368 |
| - category with axiom may have a name of its own in the litterature, |
369 |
| - like *semigroups* rather than *associative magmas*, or *fields* |
370 |
| - rather than *commutative division rings*. In this case, the |
371 |
| - category with axiom can be put in a separate file, with just a |
372 |
| - link from ``Cs``:: |
373 |
| -
|
374 |
| - sage: class Cs(Category): |
375 |
| - ....: def super_categories(self): |
376 |
| - ....: return [Sets()] |
377 |
| - ....: Finite = LazyImport('sage.categories.finite_cs', 'FiniteCs') |
378 |
| -
|
379 |
| - For a working example look up the code of the class |
380 |
| - :class:`FiniteSets` and the link to it in :class:`Sets`. |
381 |
| -
|
382 |
| - In this scenario, the category with axiom can equivalently be |
383 |
| - created directly or through its base category:: |
384 |
| -
|
385 |
| - sage: FiniteSets() |
386 |
| - Category of finite sets |
387 |
| - sage: Sets().Finite() |
388 |
| - Category of finite sets |
389 |
| - sage: Sets().Finite() is FiniteSets() |
390 |
| - True |
391 |
| -
|
392 |
| - For the former idiom to work, and with the current implementation |
393 |
| - of axioms, the class :class:`FiniteSets` needs to be aware of the |
394 |
| - class of its base category (here, :class:`Sets`) and of the axiom |
395 |
| - (here, ``Finite``):: |
396 |
| -
|
397 |
| - sage: FiniteSets._base_category_class_and_axiom |
398 |
| - (sage.categories.sets_cat.Sets, 'Finite') |
399 |
| - sage: Semigroups._base_category_class_and_axiom |
400 |
| - [sage.categories.magmas.Magmas, 'Associative'] |
401 |
| - sage: Fields._base_category_class_and_axiom |
402 |
| - (sage.categories.division_rings.DivisionRings, 'Commutative') |
403 |
| - sage: FiniteDimensionalAlgebrasWithBasis._base_category_class_and_axiom |
404 |
| - (sage.categories.algebras_with_basis.AlgebrasWithBasis, 'FiniteDimensional') |
405 |
| -
|
406 |
| - As a syntactic sugar, Sage tries some obvious heuristics to guess |
407 |
| - those from the name of the category with axiom (see |
408 |
| - :func:`base_category_class_and_axiom` for the details). When this |
409 |
| - fails, typically because the category has a name of its own like |
410 |
| - :class:`Fields`, the attribute ``_base_category_class_and_axiom`` |
411 |
| - should be set explicitly. See for example the code of the classes |
412 |
| - :class:`Semigroups` or :class:`Fields`. |
413 |
| -
|
414 |
| - .. TODO:: |
415 |
| -
|
416 |
| - - Checking if the appropriate category does not exist |
417 |
| - - Handling of multiple axioms, tree structure of the code |
418 |
| - - Implementing a new axiom |
419 |
| - - Deduction rules |
420 |
| - - Specifications |
421 |
| - - Algorithm for adding axioms and computing intersections |
422 |
| - - Flesh out the design goals |
423 |
| -
|
424 |
| - Specifications |
425 |
| - ^^^^^^^^^^^^^^ |
426 |
| -
|
427 |
| - *** The base category of an AdjectiveCategory is not a JoinCategory |
428 |
| - *** If A is a category with a given axiom (e.g. from one of its super categories) |
429 |
| - then that axiom does not appear in A (and recursively in any nested subcategory) |
430 |
| - *** The set of categories for which an axiom is defined is a lower set |
431 |
| - The same name can't be used for two axioms with different meanings. |
432 |
| - *** DONE The super categories of a category are not join categories |
433 |
| - - State "DONE" from "" [2013-06-05 mer. 08:44] |
434 |
| - *** DONE self.is_subcategory( Category.join(self.super_categories()) ) |
435 |
| - - State "DONE" from "" [2013-06-05 mer. 08:44] |
436 |
| - *** DONE self._cmp_key() > other._cmp_key() for other in self.super_categories() |
437 |
| - *** DONE Any super category of a CategoryWithParameters should either be a CategoryWithParameters or a CategorySingleton |
438 |
| - *** DONE axiom categories of singleton categories should be singletons |
439 |
| - *** DONE axiom categories of CategoryOverBaseRing should be categories over base ring. |
440 |
| - *** DEFERRED should join categories of CategoryOverBaseRing be categories over base ring? |
441 |
| - In the mean time, a base_ring method has been added to most of those; see Modules.SubcategoryMethods |
442 |
| - *** DEFERRED Functorial construction categories (Graded, CartesianProducts, ...) of singleton categories should be singleton categories |
443 |
| - Nothing difficult, but this will need to rework the current "no |
444 |
| - subclass of a concrete class" assertion test of Category_singleton.__classcall__ |
445 |
| - *** DEFERRED covariant functorial construction categories over a category over base ring should be a category over base ring |
446 |
| -
|
447 |
| -
|
448 |
| -
|
449 |
| - Design goals |
450 |
| - ^^^^^^^^^^^^ |
451 |
| -
|
452 |
| - - Flexibility in the code layout: the category of, say, finite |
453 |
| - sets can be implemented either within the Sets category (in a |
454 |
| - nested class Sets.Finite), or in a separate file (typically in |
455 |
| - a class FiniteSets in a lazily imported module |
456 |
| - sage.categories.finite_sets). |
457 |
| -
|
458 |
| - .. NOTE:: |
459 |
| -
|
460 |
| - The constructor for instances of this class takes as input the |
461 |
| - base category. Hence, they should in principle be constructed |
462 |
| - as:: |
463 |
| -
|
464 |
| - sage: FiniteSets(Sets()) # todo: not tested |
465 |
| - Category of finite sets |
466 |
| -
|
467 |
| - sage: Sets.Finite(Sets()) # todo: not tested |
468 |
| - Category of finite sets |
469 |
| -
|
470 |
| - None of those syntaxes are really practical for the user. So instead, |
471 |
| - this object is to be constructed using any of the following idioms:: |
472 |
| -
|
473 |
| - sage: Sets()._with_axiom('Finite') |
474 |
| - Category of finite sets |
475 |
| - sage: FiniteSets() |
476 |
| - Category of finite sets |
477 |
| - sage: Sets().Finite() |
478 |
| - Category of finite sets |
479 |
| -
|
480 |
| - The later two are implemented using respectively |
481 |
| - :meth:`__classcall__` and :meth:`__classget__` which see. |
482 |
| -
|
483 |
| - .. TODO: |
484 |
| -
|
485 |
| - - Implement compatibility axiom / functorial constructions |
486 |
| -
|
487 |
| - E.g. join(A.CartesianProducts(), B.CartesianProducts()) = join(A,B).CartesianProducts() |
488 |
| -
|
489 |
| - - An axiom category of a singleton category is automatically a |
490 |
| - singleton category. Should this also be implemented for |
491 |
| - categories with base ring? |
492 |
| -
|
493 |
| - - Once full subcategories are implemented (see :trac:`10668`), |
494 |
| - make category with axioms be such. Should all full subcategories |
495 |
| - be implemented in term of axioms? |
| 491 | + See the :mod:`category primer <sage.categories.primer>`, and in |
| 492 | + particular its :ref:`section about axioms <category-primer-axioms>` |
| 493 | + for an introduction to axioms, and :class:`CategoryWithAxiom` for |
| 494 | + how to implement axioms and the documentation of the axiom |
| 495 | + infrastructure. |
496 | 496 | """
|
497 | 497 |
|
498 | 498 | @lazy_class_attribute
|
|
0 commit comments