Ticket #15349: trac_15349-lazy-family-values-dg.patch

File trac_15349-lazy-family-values-dg.patch, 16.3 KB (added by darij, 9 years ago)
  • sage/sets/family.py

    # HG changeset patch
    # User darij grinberg <darijgrinberg@gmail.com>
    # Date 1383462578 25200
    # Node ID 839c49fe7d4c206d35358dd201f335b8e3885801
    # Parent  dc029471c9063cc44bc9aa05ffa40b9ca97da8c1
    trac #15349: value() for lazy families
    
    diff --git a/sage/sets/family.py b/sage/sets/family.py
    a b from sage.categories.enumerated_sets imp 
    3737from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    3838from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
    3939from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
    40 from sage.misc.lazy_import import lazy_import
    4140from sage.rings.integer import Integer
    4241from sage.misc.misc import AttrCallObject
    43 from warnings import warn
    44 name_warn_message = "The keyword name for family has never been used and will be removed shortly. Please update your code."
    4542
    46 def Family(indices, function = None, hidden_keys = [], hidden_function = None, lazy = False, name=None):
     43def Family(indices, function = None, hidden_keys = [], hidden_function = None, lazy = False):
    4744    r"""
    48     A Family is an associative container which models a family
    49     `(f_i)_{i \in I}`. Then, f[i] returns the element of the family
    50     indexed by i. Whenever available, set and combinatorial class
    51     operations (counting, iteration, listing) on the family are induced
    52     from those of the index set.
     45    A ``Family`` is an associative container which models a family
     46    `(f_i)_{i \in I}`. Then, ``f[i]`` returns the element of the family
     47    ``f`` indexed by ``i``. Whenever available, set and combinatorial
     48    class operations (counting, iteration, listing) on the family are
     49    induced from those of the index set.
    5350
    5451    There are several available implementations (classes) for different
    55     usages; Family serves as a factory, and will create instances of
    56     the appropriate classes depending on its arguments.
     52    usages; ``Family`` serves as a factory, and will create instances
     53    of the appropriate classes depending on its arguments.
    5754
    5855    EXAMPLES:
    5956
    60     In its simplest form, a list l or a tuple by itself is considered as the
    61     family `(l[i]_{i \in I})` where `I` is the range `0\dots,len(l)`. So
    62     Family(l) returns the corresponding family::
     57    In its simplest form, a list ``l`` or a tuple by itself is considered
     58    as the family `(l[i]_{i \in I})` where `I` is the range
     59    `0,1,\dots,len(l)-1`. So Family(l) returns the corresponding family::
    6360
    6461        sage: f = Family([1,2,3])
    6562        sage: f
    def Family(indices, function = None, hid 
    7471        sage: f
    7572        Family (3, 5, 7)
    7673
    77     A family can also be constructed from a dictionary t. The resulting
    78     family is very close to t, except that the elements of the family
    79     are the values of t. Here, we define the family `(f_i)_{i \in \{3,4,7\}}`
    80     with f_3='a', f_4='b', and f_7='d'::
     74    A family can also be constructed from a dictionary ``t``. The resulting
     75    family is very close to ``t``, except that the elements of the family
     76    are the values of ``t``. Here, we define the family
     77    `(f_i)_{i \in \{3,4,7\}}` with ``f_3='a'``, ``f_4='b'``, and
     78    ``f_7='d'``::
    8179
    8280        sage: f = Family({3: 'a', 4: 'b', 7: 'd'})
    8381        sage: f
    def Family(indices, function = None, hid 
    152150
    153151    Note that the ``lazy`` keyword parameter is only needed to force
    154152    laziness. Usually it is automatically set to a correct default value (ie:
    155     ``False`` for finite data structures and ``True`` for enumerated sets::
     153    ``False`` for finite data structures and ``True`` for enumerated sets)::
    156154
    157155        sage: f == Family(ZZ, lambda i: 2*i)
    158156        True
    159157
    160     Beware that for those kind of families len(f) is not supposed to
    161     work. As a replacement, use the .cardinality() method::
     158    Beware that for those kinds of families ``len(f)`` is not supposed to
     159    work. As a replacement, use the ``.cardinality()`` method::
    162160
    163161       sage: f = Family(Permutations(3), attrcall("to_lehmer_code"))
    164162       sage: list(f)
    def Family(indices, function = None, hid 
    167165       6
    168166
    169167    Caveat: Only certain families with lazy behavior can be pickled. In
    170     particular, only functions that work with Sage's pickle_function
    171     and unpickle_function (in sage.misc.fpickle) will correctly
     168    particular, only functions that work with Sage's ``pickle_function``
     169    and ``unpickle_function`` (in ``sage.misc.fpickle``) will correctly
    172170    unpickle. The following two work::
    173171
    174172       sage: f = Family(Permutations(3), lambda p: p.to_lehmer_code()); f
    def Family(indices, function = None, hid 
    192190       ValueError: Cannot pickle code objects from closures
    193191
    194192    Finally, it can occasionally be useful to add some hidden elements
    195     in a family, which are accessible as f[i], but do not appear in the
    196     keys or the container operations::
     193    to a family, which are accessible as ``f[i]``, but do not appear in
     194    the keys or the container operations::
    197195
    198196        sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
    199197        sage: f
    def Family(indices, function = None, hid 
    217215    called::
    218216
    219217        sage: def compute_value(i):
    220         ...       print('computing 2*'+str(i))
    221         ...       return 2*i
     218        ....:       print('computing 2*'+str(i))
     219        ....:       return 2*i
    222220        sage: f = Family([3,4,7], compute_value, hidden_keys=[2])
    223221        computing 2*3
    224222        computing 2*4
    def Family(indices, function = None, hid 
    264262        sage: len(f)
    265263        3
    266264
    267     Family accept finite and infinite EnumeratedSets as input::
     265    ``Family`` accepts finite and infinite ``EnumeratedSet``s as input::
    268266
    269267        sage: f = Family(FiniteEnumeratedSet([1,2,3]))
    270268        sage: f
    def Family(indices, function = None, hid 
    344342        ['cc', 'aa', 'bb']
    345343    """
    346344
    347     if name is not None:
    348         warn(name_warn_message)
    349345    assert(type(hidden_keys) == list)
    350346    assert(isinstance(lazy, bool))
    351347
    352348    if hidden_keys == []:
    353349        if hidden_function is not None:
    354                 raise ValueError, "hidden_function keyword only makes sense together with hidden_keys keyword !"
     350                raise ValueError("hidden_function keyword only makes sense together with hidden_keys keyword !")
    355351        elif function is None:
    356352            if lazy:
    357                 raise ValueError, "lazy keyword only makes sense together with function keyword !"
     353                raise ValueError("lazy keyword only makes sense together with function keyword !")
    358354            if isinstance(indices, dict):
    359355                return FiniteFamily(indices)
    360356            if isinstance(indices, (list, tuple) ):
    def Family(indices, function = None, hid 
    375371            return LazyFamily(indices, function)
    376372    else:
    377373        if lazy:
    378             raise ValueError, "lazy keyword is incompatible with hidden keys !"
     374            raise ValueError("lazy keyword is incompatible with hidden keys !")
    379375        if hidden_function is None:
    380376            hidden_function = function
    381377        return FiniteFamilyWithHiddenKeys(dict([(i, function(i)) for i in indices]),
    def Family(indices, function = None, hid 
    385381
    386382class AbstractFamily(Parent):
    387383    """
    388     The abstract class for family
     384    The abstract class for family.
    389385
    390386    Any family belongs to a class which inherits from ``AbstractFamily``.
    391387    """
    class AbstractFamily(Parent): 
    401397        """
    402398        return []
    403399
    404     def zip(self, f, other, name = None):
     400    def zip(self, f, other):
    405401        """
    406402        Given two families with same index set `I` (and same hidden
    407403        keys if relevant), returns the family
    class AbstractFamily(Parent): 
    419415        """
    420416        assert(self.keys() == other.keys())
    421417        assert(self.hidden_keys() == other.hidden_keys())
    422         if name is not None:
    423             warn(name_warn_message)
    424418        return Family(self.keys(), lambda i: f(self[i],other[i]), hidden_keys = self.hidden_keys())
    425419
    426     def map(self, f, name = None):
     420    def map(self, f):
    427421        """
    428422        Returns the family `( f(\mathtt{self}[i]) )_{i \in I}`, where
    429423        `I` is the index set of self.
    class AbstractFamily(Parent): 
    437431            sage: list(g)
    438432            ['a1', 'b1', 'd1']
    439433        """
    440         if name is not None:
    441             warn(name_warn_message)
    442434        return Family(self.keys(), lambda i: f(self[i]), hidden_keys = self.hidden_keys())
    443435
    444436    # temporary; tested by TestSuite.
    class AbstractFamily(Parent): 
    466458
    467459class FiniteFamily(AbstractFamily):
    468460    r"""
    469     A FiniteFamily is an associative container which models a finite
    470     family `(f_i)_{i \in I}`. Its elements `f_i` are therefore
    471     its values. Instances should be created via the Family factory,
    472     which see for further examples and tests.
     461    A ``FiniteFamily`` is an associative container which models a
     462    finite family `(f_i)_{i \in I}`. Its elements `f_i` are therefore
     463    its values. Instances should be created via the ``Family`` factory,
     464    which should be consulted for further examples and tests.
    473465
    474     EXAMPLES: We define the family `(f_i)_{i \in \{3,4,7\}}` with f_3=a,
    475     f_4=b, and f_7=d::
     466    EXAMPLES:
     467
     468    We define the family `(f_i)_{i \in \{3,4,7\}}` with ``f_3='a'``,
     469    ``f_4='b'``, and ``f_7='d'``::
    476470
    477471        sage: from sage.sets.family import FiniteFamily
    478472        sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
    class FiniteFamily(AbstractFamily): 
    489483        sage: f.keys()
    490484        [3, 4, 7]
    491485
    492     However f behaves as a container for the `f_i`'s::
     486    However ``f`` behaves as a container for the `f_i`'s::
    493487
    494488        sage: list(f)
    495489        ['a', 'b', 'd']
    class FiniteFamily(AbstractFamily): 
    543537
    544538    def values(self):
    545539        """
    546         Returns the elements of this family
     540        Return the list of the elements of this family.
    547541
    548542        EXAMPLES::
    549543
    class FiniteFamily(AbstractFamily): 
    697691
    698692class FiniteFamilyWithHiddenKeys(FiniteFamily):
    699693    r"""
    700     A close variant of FiniteFamily where the family contains some
     694    A close variant of ``FiniteFamily`` where the family contains some
    701695    hidden keys whose corresponding values are computed lazily (and
    702     remembered). Instances should be created via the Family factory,
    703     which see for examples and tests.
     696    remembered). Instances should be created via the ``Family``
     697    factory, which should also be consulted for examples and tests.
    704698
    705699    Caveat: Only instances of this class whose functions are compatible
    706     with sage.misc.fpickle can be pickled.
     700    with `sage.misc.fpickle`` can be pickled.
    707701    """
    708702    def __init__(self, dictionary, hidden_keys, hidden_function):
    709703        """
    class FiniteFamilyWithHiddenKeys(FiniteF 
    797791
    798792class LazyFamily(AbstractFamily):
    799793    r"""
    800     A LazyFamily(I, f) is an associative container which models the
     794    ``LazyFamily(I, f)`` is an associative container which models the
    801795    (possibly infinite) family `(f(i))_{i \in I}`.
    802796
    803     Instances should be created via the Family factory, which see for
    804     examples and tests.
     797    Instances should be created via the ``Family`` factory, whose
     798    documentation also provides examples and tests.
    805799    """
    806     def __init__(self, set, function, name=None):
     800    def __init__(self, set, function):
    807801        """
    808802        TESTS::
    809803
    class LazyFamily(AbstractFamily): 
    834828            category = EnumeratedSets()
    835829
    836830        Parent.__init__(self, category = category)
    837         if name is not None:
    838             warn(name_warn_message)
    839831        from copy import copy
    840832        self.set = copy(set)
    841833        self.function = function
    class LazyFamily(AbstractFamily): 
    843835
    844836    def __eq__(self, other):
    845837        """
    846         WARNING: Since there is no way to compare function, we only compare
    847         their name.
     838        WARNING: Since there is no way to compare functions, we only compare
     839        their names.
    848840
    849841        TESTS::
    850842
    class LazyFamily(AbstractFamily): 
    855847            sage: f == g
    856848            True
    857849        """
    858         from sage.misc.fpickle import pickle_function
    859850        if not isinstance(other, self.__class__):
    860851            return False
    861852        if not self.set == other.set:
    class LazyFamily(AbstractFamily): 
    897888
    898889    def keys(self):
    899890        """
    900         Returns self's keys.
     891        Returns ``self``'s keys.
    901892
    902893        EXAMPLES::
    903894
    class LazyFamily(AbstractFamily): 
    908899        """
    909900        return self.set
    910901
     902    def values(self, lazy_list=False):
     903        """
     904        Return the elements of this family, either as a list
     905        (if the optional keyword ``lazy_list`` is set to
     906        ``False``, which it is by default), or as a lazy list
     907        (if that keyword is set to ``True``).
     908
     909        This will misbehave when ``self`` is infinite, unless
     910        the optional keyword ``lazy_list`` is set to ``True``,
     911        in which case a lazy list will be returned.
     912
     913        EXAMPLES::
     914
     915            sage: from sage.sets.family import LazyFamily
     916            sage: f = LazyFamily(["c", "a", "b"], lambda x: x+x)
     917            sage: f.values()
     918            ['cc', 'aa', 'bb']
     919            sage: f.values(lazy_list=True)
     920            lazy list ['cc', 'aa', 'bb']
     921
     922            sage: from itertools import count
     923            sage: f = LazyFamily(count(), lambda x: x**2)
     924            sage: f.values(lazy_list=True)
     925            lazy list [0, 1, 4, ...]
     926        """
     927        if not lazy_list:
     928            return [ self.function(key) for key in self.set ]
     929        else:
     930            from sage.misc.lazy_list import lazy_list
     931            return lazy_list( self.function(key) for key in self.set )
     932
    911933    def cardinality(self):
    912934        """
    913         Return the number of elements in self.
     935        Return the number of elements in ``self``.
    914936
    915937        EXAMPLES::
    916938
    class LazyFamily(AbstractFamily): 
    10091031
    10101032class TrivialFamily(AbstractFamily):
    10111033    r"""
    1012     ``TrivialFamily(c)`` turn the container c into a family indexed by
    1013     the set `{0, \dots, len(c)}`. The container `c` can be either a list or a
    1014     tuple.
     1034    ``TrivialFamily(c)`` turns the container ``c`` into a family indexed by
     1035    the set `\{0, 1, \dots, \mathrm{len}(c) - 1\}`. The container `c` can
     1036    be either a list or a tuple.
    10151037
    1016     Instances should be created via the Family factory, which see for
    1017     examples and tests.
     1038    Instances should be created via the ``Family`` factory, which should
     1039    also be consulted for examples and tests.
    10181040    """
    10191041    def __init__(self, enumeration):
    10201042        """
    class TrivialFamily(AbstractFamily): 
    10251047            Family (3, 4, 7)
    10261048            sage: f = TrivialFamily([3,4,7]); f
    10271049            Family (3, 4, 7)
     1050            sage: TrivialFamily([3,4,7])[2]
     1051            7
    10281052            sage: TestSuite(f).run()
    10291053        """
    10301054        Parent.__init__(self, category = FiniteEnumeratedSets())
    class TrivialFamily(AbstractFamily): 
    10541078
    10551079    def keys(self):
    10561080        """
    1057         Returns self's keys.
     1081        Returns ``self``'s keys.
    10581082
    10591083        EXAMPLES::
    10601084
    class TrivialFamily(AbstractFamily): 
    10671091
    10681092    def cardinality(self):
    10691093        """
    1070         Return the number of elements in self.
     1094        Return the number of elements in ``self``.
    10711095
    10721096        EXAMPLES::
    10731097
    from sage.rings.infinity import Infinity 
    11431167
    11441168class EnumeratedFamily(LazyFamily):
    11451169    r"""
    1146     ``EnumeratedFamily(c)`` turn the enumerated set c into a family indexed by
    1147     the set `{0,\dots, c.cardinality()}`.
     1170    ``EnumeratedFamily(c)`` turns the enumerated set `c` into a family
     1171    indexed by the set `\{0, 1, \dots, c.\mathrm{cardinality()}-1 \}`.
    11481172
    1149     Instances should be created via the Family factory, which see for
    1150     examples and tests.
     1173    Instances should be created via the ``Family`` factory; see the
     1174    latter's documentation for examples and tests.
    11511175    """
    11521176    def __init__(self, enumset):
    11531177        """
    class EnumeratedFamily(LazyFamily): 
    12111235
    12121236    def keys(self):
    12131237        """
    1214         Returns self's keys.
     1238        Returns ``self``'s keys.
    12151239
    12161240        EXAMPLES::
    12171241
    class EnumeratedFamily(LazyFamily): 
    12291253
    12301254    def cardinality(self):
    12311255        """
    1232         Return the number of elements in self.
     1256        Return the number of elements in ``self``.
    12331257
    12341258        EXAMPLES::
    12351259