# HG changeset patch
# User darij grinberg
# 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/sage/sets/family.py
+++ b/sage/sets/family.py
@@ -37,29 +37,26 @@ from sage.categories.enumerated_sets imp
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
-from sage.misc.lazy_import import lazy_import
from sage.rings.integer import Integer
from sage.misc.misc import AttrCallObject
-from warnings import warn
-name_warn_message = "The keyword name for family has never been used and will be removed shortly. Please update your code."
-def Family(indices, function = None, hidden_keys = [], hidden_function = None, lazy = False, name=None):
+def Family(indices, function = None, hidden_keys = [], hidden_function = None, lazy = False):
r"""
- A Family is an associative container which models a family
- `(f_i)_{i \in I}`. Then, f[i] returns the element of the family
- indexed by i. Whenever available, set and combinatorial class
- operations (counting, iteration, listing) on the family are induced
- from those of the index set.
+ A ``Family`` is an associative container which models a family
+ `(f_i)_{i \in I}`. Then, ``f[i]`` returns the element of the family
+ ``f`` indexed by ``i``. Whenever available, set and combinatorial
+ class operations (counting, iteration, listing) on the family are
+ induced from those of the index set.
There are several available implementations (classes) for different
- usages; Family serves as a factory, and will create instances of
- the appropriate classes depending on its arguments.
+ usages; ``Family`` serves as a factory, and will create instances
+ of the appropriate classes depending on its arguments.
EXAMPLES:
- In its simplest form, a list l or a tuple by itself is considered as the
- family `(l[i]_{i \in I})` where `I` is the range `0\dots,len(l)`. So
- Family(l) returns the corresponding family::
+ In its simplest form, a list ``l`` or a tuple by itself is considered
+ as the family `(l[i]_{i \in I})` where `I` is the range
+ `0,1,\dots,len(l)-1`. So Family(l) returns the corresponding family::
sage: f = Family([1,2,3])
sage: f
@@ -74,10 +71,11 @@ def Family(indices, function = None, hid
sage: f
Family (3, 5, 7)
- A family can also be constructed from a dictionary t. The resulting
- family is very close to t, except that the elements of the family
- are the values of t. Here, we define the family `(f_i)_{i \in \{3,4,7\}}`
- with f_3='a', f_4='b', and f_7='d'::
+ A family can also be constructed from a dictionary ``t``. The resulting
+ family is very close to ``t``, except that the elements of the family
+ are the values of ``t``. Here, we define the family
+ `(f_i)_{i \in \{3,4,7\}}` with ``f_3='a'``, ``f_4='b'``, and
+ ``f_7='d'``::
sage: f = Family({3: 'a', 4: 'b', 7: 'd'})
sage: f
@@ -152,13 +150,13 @@ def Family(indices, function = None, hid
Note that the ``lazy`` keyword parameter is only needed to force
laziness. Usually it is automatically set to a correct default value (ie:
- ``False`` for finite data structures and ``True`` for enumerated sets::
+ ``False`` for finite data structures and ``True`` for enumerated sets)::
sage: f == Family(ZZ, lambda i: 2*i)
True
- Beware that for those kind of families len(f) is not supposed to
- work. As a replacement, use the .cardinality() method::
+ Beware that for those kinds of families ``len(f)`` is not supposed to
+ work. As a replacement, use the ``.cardinality()`` method::
sage: f = Family(Permutations(3), attrcall("to_lehmer_code"))
sage: list(f)
@@ -167,8 +165,8 @@ def Family(indices, function = None, hid
6
Caveat: Only certain families with lazy behavior can be pickled. In
- particular, only functions that work with Sage's pickle_function
- and unpickle_function (in sage.misc.fpickle) will correctly
+ particular, only functions that work with Sage's ``pickle_function``
+ and ``unpickle_function`` (in ``sage.misc.fpickle``) will correctly
unpickle. The following two work::
sage: f = Family(Permutations(3), lambda p: p.to_lehmer_code()); f
@@ -192,8 +190,8 @@ def Family(indices, function = None, hid
ValueError: Cannot pickle code objects from closures
Finally, it can occasionally be useful to add some hidden elements
- in a family, which are accessible as f[i], but do not appear in the
- keys or the container operations::
+ to a family, which are accessible as ``f[i]``, but do not appear in
+ the keys or the container operations::
sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
sage: f
@@ -217,8 +215,8 @@ def Family(indices, function = None, hid
called::
sage: def compute_value(i):
- ... print('computing 2*'+str(i))
- ... return 2*i
+ ....: print('computing 2*'+str(i))
+ ....: return 2*i
sage: f = Family([3,4,7], compute_value, hidden_keys=[2])
computing 2*3
computing 2*4
@@ -264,7 +262,7 @@ def Family(indices, function = None, hid
sage: len(f)
3
- Family accept finite and infinite EnumeratedSets as input::
+ ``Family`` accepts finite and infinite ``EnumeratedSet``s as input::
sage: f = Family(FiniteEnumeratedSet([1,2,3]))
sage: f
@@ -344,17 +342,15 @@ def Family(indices, function = None, hid
['cc', 'aa', 'bb']
"""
- if name is not None:
- warn(name_warn_message)
assert(type(hidden_keys) == list)
assert(isinstance(lazy, bool))
if hidden_keys == []:
if hidden_function is not None:
- raise ValueError, "hidden_function keyword only makes sense together with hidden_keys keyword !"
+ raise ValueError("hidden_function keyword only makes sense together with hidden_keys keyword !")
elif function is None:
if lazy:
- raise ValueError, "lazy keyword only makes sense together with function keyword !"
+ raise ValueError("lazy keyword only makes sense together with function keyword !")
if isinstance(indices, dict):
return FiniteFamily(indices)
if isinstance(indices, (list, tuple) ):
@@ -375,7 +371,7 @@ def Family(indices, function = None, hid
return LazyFamily(indices, function)
else:
if lazy:
- raise ValueError, "lazy keyword is incompatible with hidden keys !"
+ raise ValueError("lazy keyword is incompatible with hidden keys !")
if hidden_function is None:
hidden_function = function
return FiniteFamilyWithHiddenKeys(dict([(i, function(i)) for i in indices]),
@@ -385,7 +381,7 @@ def Family(indices, function = None, hid
class AbstractFamily(Parent):
"""
- The abstract class for family
+ The abstract class for family.
Any family belongs to a class which inherits from ``AbstractFamily``.
"""
@@ -401,7 +397,7 @@ class AbstractFamily(Parent):
"""
return []
- def zip(self, f, other, name = None):
+ def zip(self, f, other):
"""
Given two families with same index set `I` (and same hidden
keys if relevant), returns the family
@@ -419,11 +415,9 @@ class AbstractFamily(Parent):
"""
assert(self.keys() == other.keys())
assert(self.hidden_keys() == other.hidden_keys())
- if name is not None:
- warn(name_warn_message)
return Family(self.keys(), lambda i: f(self[i],other[i]), hidden_keys = self.hidden_keys())
- def map(self, f, name = None):
+ def map(self, f):
"""
Returns the family `( f(\mathtt{self}[i]) )_{i \in I}`, where
`I` is the index set of self.
@@ -437,8 +431,6 @@ class AbstractFamily(Parent):
sage: list(g)
['a1', 'b1', 'd1']
"""
- if name is not None:
- warn(name_warn_message)
return Family(self.keys(), lambda i: f(self[i]), hidden_keys = self.hidden_keys())
# temporary; tested by TestSuite.
@@ -466,13 +458,15 @@ class AbstractFamily(Parent):
class FiniteFamily(AbstractFamily):
r"""
- A FiniteFamily is an associative container which models a finite
- family `(f_i)_{i \in I}`. Its elements `f_i` are therefore
- its values. Instances should be created via the Family factory,
- which see for further examples and tests.
+ A ``FiniteFamily`` is an associative container which models a
+ finite family `(f_i)_{i \in I}`. Its elements `f_i` are therefore
+ its values. Instances should be created via the ``Family`` factory,
+ which should be consulted for further examples and tests.
- EXAMPLES: We define the family `(f_i)_{i \in \{3,4,7\}}` with f_3=a,
- f_4=b, and f_7=d::
+ EXAMPLES:
+
+ We define the family `(f_i)_{i \in \{3,4,7\}}` with ``f_3='a'``,
+ ``f_4='b'``, and ``f_7='d'``::
sage: from sage.sets.family import FiniteFamily
sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'})
@@ -489,7 +483,7 @@ class FiniteFamily(AbstractFamily):
sage: f.keys()
[3, 4, 7]
- However f behaves as a container for the `f_i`'s::
+ However ``f`` behaves as a container for the `f_i`'s::
sage: list(f)
['a', 'b', 'd']
@@ -543,7 +537,7 @@ class FiniteFamily(AbstractFamily):
def values(self):
"""
- Returns the elements of this family
+ Return the list of the elements of this family.
EXAMPLES::
@@ -697,13 +691,13 @@ class FiniteFamily(AbstractFamily):
class FiniteFamilyWithHiddenKeys(FiniteFamily):
r"""
- A close variant of FiniteFamily where the family contains some
+ A close variant of ``FiniteFamily`` where the family contains some
hidden keys whose corresponding values are computed lazily (and
- remembered). Instances should be created via the Family factory,
- which see for examples and tests.
+ remembered). Instances should be created via the ``Family``
+ factory, which should also be consulted for examples and tests.
Caveat: Only instances of this class whose functions are compatible
- with sage.misc.fpickle can be pickled.
+ with `sage.misc.fpickle`` can be pickled.
"""
def __init__(self, dictionary, hidden_keys, hidden_function):
"""
@@ -797,13 +791,13 @@ class FiniteFamilyWithHiddenKeys(FiniteF
class LazyFamily(AbstractFamily):
r"""
- A LazyFamily(I, f) is an associative container which models the
+ ``LazyFamily(I, f)`` is an associative container which models the
(possibly infinite) family `(f(i))_{i \in I}`.
- Instances should be created via the Family factory, which see for
- examples and tests.
+ Instances should be created via the ``Family`` factory, whose
+ documentation also provides examples and tests.
"""
- def __init__(self, set, function, name=None):
+ def __init__(self, set, function):
"""
TESTS::
@@ -834,8 +828,6 @@ class LazyFamily(AbstractFamily):
category = EnumeratedSets()
Parent.__init__(self, category = category)
- if name is not None:
- warn(name_warn_message)
from copy import copy
self.set = copy(set)
self.function = function
@@ -843,8 +835,8 @@ class LazyFamily(AbstractFamily):
def __eq__(self, other):
"""
- WARNING: Since there is no way to compare function, we only compare
- their name.
+ WARNING: Since there is no way to compare functions, we only compare
+ their names.
TESTS::
@@ -855,7 +847,6 @@ class LazyFamily(AbstractFamily):
sage: f == g
True
"""
- from sage.misc.fpickle import pickle_function
if not isinstance(other, self.__class__):
return False
if not self.set == other.set:
@@ -897,7 +888,7 @@ class LazyFamily(AbstractFamily):
def keys(self):
"""
- Returns self's keys.
+ Returns ``self``'s keys.
EXAMPLES::
@@ -908,9 +899,40 @@ class LazyFamily(AbstractFamily):
"""
return self.set
+ def values(self, lazy_list=False):
+ """
+ Return the elements of this family, either as a list
+ (if the optional keyword ``lazy_list`` is set to
+ ``False``, which it is by default), or as a lazy list
+ (if that keyword is set to ``True``).
+
+ This will misbehave when ``self`` is infinite, unless
+ the optional keyword ``lazy_list`` is set to ``True``,
+ in which case a lazy list will be returned.
+
+ EXAMPLES::
+
+ sage: from sage.sets.family import LazyFamily
+ sage: f = LazyFamily(["c", "a", "b"], lambda x: x+x)
+ sage: f.values()
+ ['cc', 'aa', 'bb']
+ sage: f.values(lazy_list=True)
+ lazy list ['cc', 'aa', 'bb']
+
+ sage: from itertools import count
+ sage: f = LazyFamily(count(), lambda x: x**2)
+ sage: f.values(lazy_list=True)
+ lazy list [0, 1, 4, ...]
+ """
+ if not lazy_list:
+ return [ self.function(key) for key in self.set ]
+ else:
+ from sage.misc.lazy_list import lazy_list
+ return lazy_list( self.function(key) for key in self.set )
+
def cardinality(self):
"""
- Return the number of elements in self.
+ Return the number of elements in ``self``.
EXAMPLES::
@@ -1009,12 +1031,12 @@ class LazyFamily(AbstractFamily):
class TrivialFamily(AbstractFamily):
r"""
- ``TrivialFamily(c)`` turn the container c into a family indexed by
- the set `{0, \dots, len(c)}`. The container `c` can be either a list or a
- tuple.
+ ``TrivialFamily(c)`` turns the container ``c`` into a family indexed by
+ the set `\{0, 1, \dots, \mathrm{len}(c) - 1\}`. The container `c` can
+ be either a list or a tuple.
- Instances should be created via the Family factory, which see for
- examples and tests.
+ Instances should be created via the ``Family`` factory, which should
+ also be consulted for examples and tests.
"""
def __init__(self, enumeration):
"""
@@ -1025,6 +1047,8 @@ class TrivialFamily(AbstractFamily):
Family (3, 4, 7)
sage: f = TrivialFamily([3,4,7]); f
Family (3, 4, 7)
+ sage: TrivialFamily([3,4,7])[2]
+ 7
sage: TestSuite(f).run()
"""
Parent.__init__(self, category = FiniteEnumeratedSets())
@@ -1054,7 +1078,7 @@ class TrivialFamily(AbstractFamily):
def keys(self):
"""
- Returns self's keys.
+ Returns ``self``'s keys.
EXAMPLES::
@@ -1067,7 +1091,7 @@ class TrivialFamily(AbstractFamily):
def cardinality(self):
"""
- Return the number of elements in self.
+ Return the number of elements in ``self``.
EXAMPLES::
@@ -1143,11 +1167,11 @@ from sage.rings.infinity import Infinity
class EnumeratedFamily(LazyFamily):
r"""
- ``EnumeratedFamily(c)`` turn the enumerated set c into a family indexed by
- the set `{0,\dots, c.cardinality()}`.
+ ``EnumeratedFamily(c)`` turns the enumerated set `c` into a family
+ indexed by the set `\{0, 1, \dots, c.\mathrm{cardinality()}-1 \}`.
- Instances should be created via the Family factory, which see for
- examples and tests.
+ Instances should be created via the ``Family`` factory; see the
+ latter's documentation for examples and tests.
"""
def __init__(self, enumset):
"""
@@ -1211,7 +1235,7 @@ class EnumeratedFamily(LazyFamily):
def keys(self):
"""
- Returns self's keys.
+ Returns ``self``'s keys.
EXAMPLES::
@@ -1229,7 +1253,7 @@ class EnumeratedFamily(LazyFamily):
def cardinality(self):
"""
- Return the number of elements in self.
+ Return the number of elements in ``self``.
EXAMPLES::