Package sage :: Package combinat :: Module family
[hide private]
[frames] | no frames]

Module family

source code


Families



Classes [hide private]
  AbstractFamily
  FiniteFamily
A FiniteFamily is an associative container which models a finite family (f_i)_{i in I}.
  FiniteFamilyWithHiddenKeys
A close variant of FiniteFamily where the family contains some hidden keys whose corresponding values are computed lazily (and remembered).
  LazyFamily
A LazyFamily(I, f) is an associative container which models the (possibly infinite) family (f(i))_{i in I}.
Functions [hide private]
 
Family(indices, function=['4ti2-20061025', 'R-2.6.0', 'atlas-3.7.37', 'atlas-3.8.1', 'a..., name=['4ti2-20061025', 'R-2.6.0', 'atlas-3.7.37', 'atlas-3.8.1', 'a..., hidden_keys=[], hidden_function=['4ti2-20061025', 'R-2.6.0', 'atlas-3.7.37', 'atlas-3.8.1', 'a...)
A Family is an associative container which models a family (f_i)_{i in I}.
source code
Function Details [hide private]

Family(indices, function=['4ti2-20061025', 'R-2.6.0', 'atlas-3.7.37', 'atlas-3.8.1', 'a..., name=['4ti2-20061025', 'R-2.6.0', 'atlas-3.7.37', 'atlas-3.8.1', 'a..., hidden_keys=[], hidden_function=['4ti2-20061025', 'R-2.6.0', 'atlas-3.7.37', 'atlas-3.8.1', 'a...)

source code 

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.

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.

EXAMPLES:

    In its simplest form, a list l by itself is considered as the
    family $(l[i]_{i in I})$ where $I$ is the range $0\dots,len(l)$.
    So Family(l) just returns it.

        sage: f = Family([1,2,3])
        sage: f
        [1, 2, 3]

    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
        Finite family {3: 'a', 4: 'b', 7: 'd'}
        sage: f[7]
        'd'
        sage: len(f)
        3
        sage: list(f)
        ['a', 'b', 'd']
        sage: [ x for x in f ]
        ['a', 'b', 'd']
        sage: f.keys()
        [3, 4, 7]
        sage: 'b' in f  
        True
        sage: 'e' in f
        False

    A familly can also be constructed by its index set $I$ and a
    function $f$, as in $(f(i))_{i in I}$:

        sage: f = Family([3,4,7], lambda i: 2*i)
        sage: f
        Finite family {3: 6, 4: 8, 7: 14}
        sage: f.keys()
        [3, 4, 7]
        sage: f[7]
        14
        sage: list(f)
        [6, 8, 14]
        sage: [ x for x in f]
        [6, 8, 14]
        sage: len(f)
        3

    By default, if the index set is a list, all images are
    computed right away, and stored in an internal
    dictionary. Note that this requires all the elements of the
    list to be hashable. One can ask instead for the images $f(i)$
    to be computed lazily, when needed:

        sage: f = LazyFamily([3,4,7], lambda i: 2r*i)
        sage: f
        Lazy family (f(i))_{i in [3, 4, 7]}
        sage: f[7]
        14
        sage: list(f)
        [6, 8, 14]
        sage: [ x for x in f]
        [6, 8, 14]
        sage: len(f)
        3

    This allows in particular for modeling infinite families:
        sage: f = Family(ZZ, lambda i: 2r*i)
        sage: f
        Lazy family (f(i))_{i in Integer Ring}
        sage: f.keys()
        Integer Ring
        sage: f[1]
        2
        sage: f[-5]
        -10
        sage: i = f.__iter__()
        sage: i.next(), i.next(), i.next(), i.next(), i.next()
        (0, 2, -2, 4, -4)

    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
    unpickle.

    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.

        sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2])
        sage: f
        Finite family {3: 6, 4: 8, 7: 14}
        sage: f.keys()
        [3, 4, 7]
        sage: f.hidden_keys()
        [2]
        sage: f[7]
        14
        sage: f[2]
        4
        sage: list(f)
        [6, 8, 14]
        sage: [ x for x in f]
        [6, 8, 14]
        sage: len(f)
        3

    The following example illustrates when the function is actually called:
        sage: def compute_value(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
        computing 2*7
        sage: f
        Finite family {3: 6, 4: 8, 7: 14}
        sage: f.keys()
        [3, 4, 7]
        sage: f.hidden_keys()
        [2]
        sage: f[7]
        14
        sage: f[2]
        computing 2*2
        4
        sage: f[2]
        4
        sage: list(f)
        [6, 8, 14]
        sage: [ x for x in f]
        [6, 8, 14]
        sage: len(f)
        3

    Here is a close variant where the function for the hidden keys
    is different from that for the other keys:

        sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2], hidden_function = lambda i: 3*i)
        sage: f
        Finite family {3: 6, 4: 8, 7: 14}
        sage: f.keys()
        [3, 4, 7]
        sage: f.hidden_keys()
        [2]
        sage: f[7]
        14
        sage: f[2]
        6
        sage: list(f)
        [6, 8, 14]
        sage: [ x for x in f]
        [6, 8, 14]
        sage: len(f)
        3

    Family behaves the same way with FiniteCombinatorialClass
    instances and lists.  This feature will eventually disapear
    when FiniteCombinatorialClass won't be needed anymore.
    
        sage: f = Family(FiniteCombinatorialClass([1,2,3]))
        sage: f
        Combinatorial class with elements in [1, 2, 3]

        sage: f = Family(FiniteCombinatorialClass([3,4,7]), lambda i: 2*i)
        sage: f
        Finite family {3: 6, 4: 8, 7: 14}
        sage: f.keys()
        [3, 4, 7]
        sage: f[7]
        14
        sage: list(f)
        [6, 8, 14]
        sage: [ x for x in f]
        [6, 8, 14]
        sage: len(f)
        3

    TESTS:
        sage: f = Family({1:'a', 2:'b', 3:'c'})
        sage: f
        Finite family {1: 'a', 2: 'b', 3: 'c'}
        sage: f[2]
        'b'
        sage: loads(dumps(f)) == f
        True

        sage: f = Family(range(1,27), lambda i: chr(i+96))
        sage: f
            Finite family {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i', 10: 'j', 11: 'k', 12: 'l', 13: 'm', 14: 'n', 15: 'o', 16: 'p', 17: 'q', 18: 'r', 19: 's', 20: 't', 21: 'u', 22: 'v', 23: 'w', 24: 'x', 25: 'y', 26: 'z'}
        sage: f[2]
        'b'