Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Ticket 16465 : improve the category and give a framework of class of …
Browse files Browse the repository at this point in the history
…combinatorial structures
  • Loading branch information
elixyre committed Jun 11, 2014
1 parent af6f02c commit 16685a3
Show file tree
Hide file tree
Showing 5 changed files with 529 additions and 3 deletions.
16 changes: 14 additions & 2 deletions src/sage/categories/combinatorial_structures.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# -*- coding: utf-8 -*-
"""
The category of classes of combinatorial structures
AUTHORS:
- Jean-Baptiste Priez (2014)
"""
from sage.categories.category import Category
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
Expand All @@ -16,7 +20,7 @@ class CombinatorialStructures(Category):
"""

def super_categories(self):
return [SetsWithGrading(), InfiniteEnumeratedSets()]
return [SetsWithGrading()]#, InfiniteEnumeratedSets()] that

class ParentMethods:

Expand Down Expand Up @@ -49,6 +53,14 @@ def restrict_class_of_structures(self, min, max):
*max*.
"""

def __iter__(self):
"""
"""
for grade in self.grading_set():
for obj in self.graded_component(grade):
yield obj

class GradedComponents(Category):

def super_categories(self):
Expand All @@ -57,7 +69,7 @@ def super_categories(self):
class ParentMethods:

def _repr_(self):
return repr(self.ambient()) + " of degree " + repr(self.grade())
return repr(self.ambient()) + " of degree " + repr(self.grading())

@abstract_method(optional=False)
def ambient(self):
Expand Down
157 changes: 157 additions & 0 deletions src/sage/categories/examples/combinatorial_structures_compositions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# -*- coding: utf-8 -*-
"""
Example of implementation of class of combinatorial structures
--------------------------------------------------------------
This module implements a simple version of the class of compositions of integer.
"[..] a composition of an integer `n` is a way of writing `n` as the sum of a sequence of
(strictly) positive integers." Wikipedia
This module provides a light implementation to rapid use. This example uses the following pattern::
from sage.combinat.structures import Structures, Structure
class MyStructure(Structure):
def check(self):
# a way to check if the structure is correct
@lazy_class_attribute
def _auto_parent_(self):
# my default parent
return ClassOfStructures()
## + specific design of my structure
class MyGradedComponent(Structures.GradedComponent):
def __iter__(self):
# an iterator of the objets of the graded component
class ClassOfStructures(Structures):
def grading(self, obj):
# a way to way the grading of the graded component which contains the obj
# we specify the class which defines the graded components
GradedComponent = MyGradedComponent
AUTHORS:
- Jean-Baptiste Priez (2014)
"""
from itertools import imap
from sage.combinat.structures import Structures, Structure
from sage.misc.lazy_attribute import lazy_class_attribute
from sage.rings.integer import Integer
from sage.structure.list_clone import ClonableIntArray


class Composition(Structure, ClonableIntArray):
"""
A composition could be represented as a vector of integers so one use *ClonableIntArray*
to implement our structures.
In that example, we choose to use a more general structures: *ElementWrapper*
The class *Structure* is a simple class use to not (re)define a classcall method.
Usually, the classcall is use on elements to avoid explicit parent in argument::
Composition([3,1,2], parent=Compositions())
TESTS::
sage: from sage.categories.examples.combinatorial_structures_compositions import Composition
sage: I = Composition([2,1,3]); I
[2, 1, 3]
sage: I.parent()
Compositions of integers
sage: I.grade()
5
"""

def check(self):
"""
The check has to be given to specify the structure
"""
assert(all(isinstance(i, (int, Integer)) for i in self))

@lazy_class_attribute
def _auto_parent_(self):
"""
I use this trick to not call a Composition with an explicit parent.
(It is a lazy class attribute to avoid to conflict with *Compositions*)
"""
return Compositions()


class Compositions(Structures):
"""
TESTS::
sage: from sage.categories.examples.combinatorial_structures_compositions import, Compositions
sage: C3 = Compositions(3); C3
Compositions of integers of degree 3
sage: C3.ambient()
Compositions of integers
sage: TestSuite(Compositions()).run()
"""

def grading(self, I):
"""
TESTS::
sage: from sage.categories.examples.combinatorial_structures_compositions import Composition, Compositions
sage: I = Composition([2,1,3]); I
sage: I.parent().grading(I)
5
sage: Compositions().grading(I)
5
"""
return sum(I)

def _repr_(self):
"""
TESTS::
sage: from sage.categories.examples.combinatorial_structures_compositions import Compositions
sage: Compositions()
Compositions of integers
sage: Compositions(3)
Compositions of integers of degree 3
"""
return "Compositions of integers"

# I have to specify *Compositions* is the parent of the elements *Composition*.
Element = Composition

class GradedComponent(Structures.GradedComponent):

def cardinality(self):
return Integer(2)**self.grading()

def __iter__(self):
"""
TESTS::
sage: from sage.categories.examples.combinatorial_structures_compositions import Compositions
sage: Compositions(4).list()
[[4], [1, 3], [2, 2], [1, 1, 2], [3, 1], [1, 2, 1], [2, 1, 1], [1, 1, 1, 1]]
"""
def nested(k):
# little trick to avoid to create too many object *Composition*:
## That avoid the trip: Composition(... list(Composition(list(Composition([1])) + [2])) + ...)
if k == 0: yield ()
else:
for i in range(k):
for I in nested(i):
yield I + (k-i,)

return imap(self._element_constructor_, nested(self.grading()))


2 changes: 2 additions & 0 deletions src/sage/categories/sets_with_grading.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ def graded_component(self, grade):
"""
return self.subset(grade)

@abstract_method(optional=True)
def grading(self, elt):
"""
Return the grading of the element ``elt`` of ``self``.
Expand All @@ -199,6 +200,7 @@ def grading(self, elt):
"""

#@cached_method
@abstract_method(optional=True)
def generating_series(self):
"""
Default implementation for generating series.
Expand Down
5 changes: 4 additions & 1 deletion src/sage/combinat/binary_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
# the License, or (at your option) any later version.
# http://www.gnu.org/licenses/
#*****************************************************************************
from sage.categories.category import Category
from sage.categories.combinatorial_structures import CombinatorialStructures
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
from sage.functions.other import sqrt
from sage.rings.rational_field import RationalField
from sage.structure.list_clone import ClonableArray
Expand Down Expand Up @@ -2803,7 +2805,8 @@ def __init__(self):
"""
DisjointUnionEnumeratedSets.__init__(
self, Family(NonNegativeIntegers(), BinaryTrees_size),
facade=True, keepkey=False, category=CombinatorialStructures())
facade=True, keepkey=False, category=Category.join([InfiniteEnumeratedSets(), CombinatorialStructures()])
)

def _repr_(self):
"""
Expand Down
Loading

0 comments on commit 16685a3

Please sign in to comment.