Ticket #3738: 3738-0-generators.patch

File 3738-0-generators.patch, 10.7 KB (added by robertwb, 11 years ago)
  • new file sage/structure/generators.pxd

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1217319870 25200
    # Node ID 5c038484dca0bd93a47cab8cf0c19e9a9d31d41a
    # Parent  caf27382be671b9f0231fa4a06f4a7c3074d944e
    generators object
    
    diff -r caf27382be67 -r 5c038484dca0 sage/structure/generators.pxd
    - +  
     1from sage.structure.sage_object cimport SageObject
     2
     3cdef class Generators(SageObject):
     4
     5    cdef readonly _obj
     6    cdef readonly _index_set
     7    cdef readonly _category
     8
     9    cpdef get_from_index(self, i)
     10    cpdef index_set(self)
     11    cpdef category(self)
     12    cpdef obj(self)
     13    cpdef count(self)
     14    cpdef list(self)
     15
     16cdef class Generators_finite(Generators):
     17    cdef Py_ssize_t _n
     18
     19cdef class Generators_list(Generators_finite):
     20    cdef _L
     21       
     22cdef class Generators_naturals(Generators):
     23    pass
     24
     25cdef class Generators_none(Generators):
     26    pass
     27
     28cdef class Generators_lazy_all(Generators):
     29    cdef _f
     30    cdef int _compute_gens(self) except -1
     31   
  • new file sage/structure/generators.pyx

    diff -r caf27382be67 -r 5c038484dca0 sage/structure/generators.pyx
    - +  
     1"""
     2This module implements Generators, a type of object that represents (algebraic) generators of a Sage object.
     3
     4
     5"""
     6
     7include "../ext/stdsage.pxi"
     8from sage.structure.sage_object cimport SageObject
     9
     10class GenIter(SageObject):
     11    """
     12    An iterator over a set of generators.
     13    """
     14    def __init__(self, Generators gens):
     15        if gens._index_set is None:
     16            self._index_iter = iter(xrange(gens.count()))
     17        else:
     18            self._index_iter = iter(gens._index_set)
     19        self._gens = gens
     20
     21    def next(self):
     22        return self._gens.get_from_index(self._index_iter.next())
     23
     24    def __iter__(self):
     25        return self
     26
     27cdef class Generators(SageObject):
     28    """
     29    This class implements generators that can be attached to CategoryObjects.
     30    """
     31    def __init__(self, obj, index_set, category):
     32        self._obj = obj
     33        self._index_set = index_set
     34        self._category = category
     35       
     36    cpdef get_from_index(self, i):
     37        return self._obj._gen_(i)
     38
     39    def __contains__(self, x):
     40        for a in self:
     41            if x == a:
     42                return True
     43        return False
     44
     45    def __call__(self, i):
     46        return self.get_from_index(i)
     47
     48    def __getitem__(self, i):
     49        if isinstance(i, slice):
     50            return self.list()[i]
     51        return self.get_from_index(i)
     52
     53    def __iter__(self):
     54        return GenIter(self)
     55
     56    def __len__(self):
     57        return self.count()
     58
     59    cpdef index_set(self):
     60        if self._index_set is None:
     61            return range(self.count())
     62        else:
     63            return self._index_set
     64
     65    cpdef category(self):
     66        return self._category
     67
     68    cpdef obj(self):
     69        return self._obj
     70
     71    cpdef count(self):
     72        return len(self._index_set)
     73
     74    cpdef list(self):
     75        try:
     76            if not self._index_set.is_finite():
     77                raise ValueError, "index set must be finite to compute list"
     78        except AttributeError:
     79            pass
     80        return [self.get_from_index(i) for i in self.index_set()]
     81
     82    def _repr_(self):
     83        if not PY_TYPE_CHECK(self._obj, Generators):
     84            return "Set of generators of %s"%(self.obj())
     85        else:
     86            raise RuntimeError, "Set of generators of a generators object"
     87
     88cdef class Generators_finite(Generators):
     89    def __init__(self, obj, n, index_set, category):
     90        """
     91        Creates a generator object representing finitely many generators.
     92        """
     93        self._n = n
     94        Generators.__init__(self, obj, index_set, category)
     95
     96    cpdef count(self):
     97        return self._n
     98
     99    def __cmp__(self, other_unty):
     100        cdef Generators_finite other = other_unty
     101        return cmp((self._obj, self._n, self._index_set, self._category),
     102                   (other._obj, other._n, other._index_set, other._category))
     103                   
     104
     105    def _repr_(self):
     106        return "(" + ", ".join([repr(self[i]) for i in self.index_set()]) +  ")"
     107       
     108    def __reduce__(self):
     109        return make_finite_gens, (self._obj, self._n, self._index_set, self._category)
     110       
     111def make_finite_gens(obj, n, index_set, category):
     112    return Generators_finite(obj, n, index_set, category)
     113           
     114
     115cdef class Generators_list(Generators_finite):
     116    """
     117    This class represents a set of generaters as a tuple of elements, indexed
     118    by the integers 0 to len(self)-1.
     119   
     120    It is the easiest to use of all the generator classes, and gets constructed
     121    implicitly when a list is passed into \code{_populate_generators_}.
     122    """
     123    def __init__(self, obj, L, category):
     124        """
     125        EXAMPLES:
     126            sage: from sage.structure.generators import Generators_list
     127            sage: gens = Generators_list(ZZ, [2,3], Rings)
     128            sage: gens.count()
     129            2
     130            sage: gens(1)
     131            3
     132            sage: list(gens)
     133            [2, 3]
     134        """
     135        self._L = tuple(L)
     136        Generators_finite.__init__(self, obj, len(self._L), None, category)
     137
     138    cpdef get_from_index(self, i):
     139        """
     140        EXAMPLES:
     141            sage: from sage.structure.generators import Generators_list
     142            sage: gens = Generators_list(ZZ, [5,9], Rings)
     143            sage: gens.get_from_index(0)
     144            5
     145        """
     146        try:
     147            return self._L[i]
     148        except IndexError:
     149            raise IndexError, "No such generator: %s must be less than %s" % (i, len(self._L))
     150
     151    def __iter__(self):
     152        """
     153        EXAMPLES:
     154            sage: from sage.structure.generators import Generators_list
     155            sage: gens = Generators_list(ZZ, [3,4,5], Rings)
     156            sage: [x^2 for x in gens]
     157            [9, 16, 25]
     158        """
     159        return iter(self._L)
     160
     161    cpdef list(self):
     162        """
     163        Actually returns a tuple, which is immutable.
     164       
     165        EXAMPLES:
     166            sage: from sage.structure.generators import Generators_list
     167            sage: gens = Generators_list(ZZ, (1,2,3), Rings)
     168            sage: gens.list()
     169            (1, 2, 3)
     170        """
     171        return self._L
     172       
     173    def __reduce__(self):
     174        return make_list_gens, (self._obj, self._L, self._category)
     175       
     176    def __cmp__(left, _right):
     177        cdef Generators_list right
     178        try:
     179            right = _right
     180            return cmp(left._n, right._n) or \
     181                   cmp(left._L, right._L) or \
     182                   cmp(left._category, right._category)
     183        except TypeError:
     184            return cmp(type(left), type(right))
     185
     186    def _repr_(self):
     187        return repr(self._L)
     188           
     189def make_list_gens(*args):
     190    """
     191    TEST:
     192        sage: from sage.structure.generators import Generators_list
     193        sage: gens = Generators_list(QQ, [-3,17], Fields())
     194        sage: loads(dumps(gens)) == gens
     195        True
     196    """
     197    return Generators_list(*args)
     198       
     199cdef class Generators_naturals(Generators):
     200    def __init__(self, obj, category):
     201        import sage.rings.natural_parents
     202        Generators.__init__(self, obj, sage.rings.natural_parents.NaturalSemiring, category)
     203
     204    cpdef count(self):
     205        import sage.rings.infinity
     206        return sage.rings.infinity.infinity
     207
     208    def __getitem__(self, i):
     209        if isinstance(i, slice):
     210            raise NotImplementedError
     211        return self.get_from_index(i)
     212
     213cdef class Generators_none(Generators):
     214    def __init__(self, obj, category = None):
     215        Generators.__init__(self, obj, None, category)
     216
     217    cpdef get_from_index(self, i):
     218        if self._category is None:
     219            raise ValueError, "this object does not have generators"
     220        else:
     221            raise ValueError, "this object does not have generators in that category"
     222
     223    def __contains__(self, x):
     224        if self._category is None:
     225            raise ValueError, "this object does not have generators"
     226        else:
     227            raise ValueError, "this object does not have generators in that category"
     228
     229    def __iter__(self):
     230        if self._category is None:
     231            raise ValueError, "this object does not have generators"
     232        else:
     233            raise ValueError, "this object does not have generators in that category"
     234
     235    cpdef index_set(self):
     236        if self._category is None:
     237            raise ValueError, "this object does not have generators"
     238        else:
     239            raise ValueError, "this object does not have generators in that category"
     240
     241    cpdef count(self):
     242        if self._category is None:
     243            raise ValueError, "this object does not have generators"
     244        else:
     245            raise ValueError, "this object does not have generators in that category"
     246
     247    cpdef list(self):
     248        if self._category is None:
     249            raise ValueError, "this object does not have generators"
     250        else:
     251            raise ValueError, "this object does not have generators in that category"
     252   
     253
     254
     255cdef class Generators_lazy_all(Generators):
     256    """
     257    Use this generators class if there is a finite list of generators that is expensive to compute but which is computed all at once.
     258    """
     259    def __init__(self, G, index_set, category, computing_function):
     260        self._f = computing_function
     261        Generators.__init__(self, G, index_set, category)
     262
     263    cdef int _compute_gens(self) except -1:
     264        self._gens = self._f()
     265
     266    cpdef get_from_index(self, i):
     267        try:
     268            return self._gens[i]
     269        except AttributeError:
     270            self._compute_gens()
     271        return self._gens[i]
     272
     273    cpdef count(self):
     274        try:
     275            return len(self._gens)
     276        except AttributeError:
     277            self._compute_gens()
     278        return len(self._gens)
     279
     280    cpdef list(self):
     281        try:
     282            return list(self._gens)
     283        except AttributeError:
     284            self._compute_gens()
     285        return list(self._gens)
     286
     287    def _repr_(self):
     288        try:
     289            return repr(self._gens)
     290        except AttributeError:
     291            self._compute_gens()
     292        return repr(self._gens)
     293
  • setup.py

    diff -r caf27382be67 -r 5c038484dca0 setup.py
    a b time_series = Extension('sage.finance.ti 
    478478#####################################################
    479479
    480480ext_modules = [ \
     481
     482    Extension('sage.structure.generators',
     483              sources = ['sage/structure/generators.pyx']), \
     484
    481485    free_module_element,
    482486   
    483487    complex_double_vector,