Enumerated set from iterator¶
EXAMPLES:
We build a set from the iterator graphs that returns a canonical
representative for each isomorphism class of graphs:
sage: # needs sage.graphs
sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator
sage: E = EnumeratedSetFromIterator(
....:   graphs,
....:   name='Graphs',
....:   category=InfiniteEnumeratedSets(),
....:   cache=True)
sage: E
Graphs
sage: E.unrank(0)
Graph on 0 vertices
sage: E.unrank(4)
Graph on 3 vertices
sage: E.cardinality()
+Infinity
sage: E.category()
Category of facade infinite enumerated sets
>>> from sage.all import *
>>> # needs sage.graphs
>>> from sage.sets.set_from_iterator import EnumeratedSetFromIterator
>>> E = EnumeratedSetFromIterator(
...   graphs,
...   name='Graphs',
...   category=InfiniteEnumeratedSets(),
...   cache=True)
>>> E
Graphs
>>> E.unrank(Integer(0))
Graph on 0 vertices
>>> E.unrank(Integer(4))
Graph on 3 vertices
>>> E.cardinality()
+Infinity
>>> E.category()
Category of facade infinite enumerated sets
The module also provides decorator for functions and methods:
sage: from sage.sets.set_from_iterator import set_from_function
sage: @set_from_function
....: def f(n): return xsrange(n)
sage: f(3)
{0, 1, 2}
sage: f(5)
{0, 1, 2, 3, 4}
sage: f(100)
{0, 1, 2, 3, 4, ...}
sage: from sage.sets.set_from_iterator import set_from_method
sage: class A:
....:     @set_from_method
....:     def f(self, n):
....:         return xsrange(n)
sage: a = A()
sage: a.f(3)
{0, 1, 2}
sage: f(100)
{0, 1, 2, 3, 4, ...}
>>> from sage.all import *
>>> from sage.sets.set_from_iterator import set_from_function
>>> @set_from_function
... def f(n): return xsrange(n)
>>> f(Integer(3))
{0, 1, 2}
>>> f(Integer(5))
{0, 1, 2, 3, 4}
>>> f(Integer(100))
{0, 1, 2, 3, 4, ...}
>>> from sage.sets.set_from_iterator import set_from_method
>>> class A:
...     @set_from_method
...     def f(self, n):
...         return xsrange(n)
>>> a = A()
>>> a.f(Integer(3))
{0, 1, 2}
>>> f(Integer(100))
{0, 1, 2, 3, 4, ...}
- class sage.sets.set_from_iterator.Decorator[source]¶
- Bases: - object- Abstract class that manage documentation and sources of the wrapped object. - The method needs to be stored in the attribute - self.f
- class sage.sets.set_from_iterator.DummyExampleForPicklingTest[source]¶
- Bases: - object- Class example to test pickling with the decorator - set_from_method.- Warning - This class is intended to be used in doctest only. - EXAMPLES: - sage: from sage.sets.set_from_iterator import DummyExampleForPicklingTest sage: DummyExampleForPicklingTest().f() {10, 11, 12, 13, 14, ...} - >>> from sage.all import * >>> from sage.sets.set_from_iterator import DummyExampleForPicklingTest >>> DummyExampleForPicklingTest().f() {10, 11, 12, 13, 14, ...} - f()[source]¶
- Return the set between - self.startand- self.stop.- EXAMPLES: - sage: from sage.sets.set_from_iterator import DummyExampleForPicklingTest sage: d = DummyExampleForPicklingTest() sage: d.f() {10, 11, 12, 13, 14, ...} sage: d.start = 4 sage: d.stop = 200 sage: d.f() {4, 5, 6, 7, 8, ...} - >>> from sage.all import * >>> from sage.sets.set_from_iterator import DummyExampleForPicklingTest >>> d = DummyExampleForPicklingTest() >>> d.f() {10, 11, 12, 13, 14, ...} >>> d.start = Integer(4) >>> d.stop = Integer(200) >>> d.f() {4, 5, 6, 7, 8, ...} 
 - start = 10¶
 - stop = 100¶
 
- class sage.sets.set_from_iterator.EnumeratedSetFromIterator(f, args=None, kwds=None, name=None, category=None, cache=False)[source]¶
- Bases: - Parent- A class for enumerated set built from an iterator. - INPUT: - f– a function that returns an iterable from which the set is built from
- args– tuple; arguments to be sent to the function \(f\)
- kwds– dictionary; keywords to be sent to the function \(f\)
- name– an optional name for the set
- category– (default:- None) an optional category for that enumerated set. If you know that your iterator will stop after a finite number of steps you should set it as- FiniteEnumeratedSets, conversely if you know that your iterator will run over and over you should set it as- InfiniteEnumeratedSets.
- cache– boolean (default:- False); whether or not use a cache mechanism for the iterator. If- True, then the function \(f\) is called only once.
 - EXAMPLES: - sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(graphs, args=(7,)); E # needs sage.graphs {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, ...} sage: E.category() # needs sage.graphs Category of facade enumerated sets - >>> from sage.all import * >>> from sage.sets.set_from_iterator import EnumeratedSetFromIterator >>> E = EnumeratedSetFromIterator(graphs, args=(Integer(7),)); E # needs sage.graphs {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, ...} >>> E.category() # needs sage.graphs Category of facade enumerated sets - The same example with a cache and a custom name: - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True, # needs sage.graphs ....: name="Graphs with 8 vertices", ....: category=FiniteEnumeratedSets()); E Graphs with 8 vertices sage: E.unrank(3) # needs sage.graphs Graph on 8 vertices sage: E.category() # needs sage.graphs Category of facade finite enumerated sets - >>> from sage.all import * >>> E = EnumeratedSetFromIterator(graphs, args=(Integer(8),), cache=True, # needs sage.graphs ... name="Graphs with 8 vertices", ... category=FiniteEnumeratedSets()); E Graphs with 8 vertices >>> E.unrank(Integer(3)) # needs sage.graphs Graph on 8 vertices >>> E.category() # needs sage.graphs Category of facade finite enumerated sets - Note - In order to make the - TestSuiteworks, the elements of the set should have parents.- clear_cache()[source]¶
- Clear the cache. - EXAMPLES: - sage: from itertools import count sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(count, args=(1,), cache=True) sage: e1 = E._cache; e1 lazy list [1, 2, 3, ...] sage: E.clear_cache() sage: E._cache lazy list [1, 2, 3, ...] sage: e1 is E._cache False - >>> from sage.all import * >>> from itertools import count >>> from sage.sets.set_from_iterator import EnumeratedSetFromIterator >>> E = EnumeratedSetFromIterator(count, args=(Integer(1),), cache=True) >>> e1 = E._cache; e1 lazy list [1, 2, 3, ...] >>> E.clear_cache() >>> E._cache lazy list [1, 2, 3, ...] >>> e1 is E._cache False 
 - is_parent_of(x)[source]¶
- Test whether - xis in- self.- If the set is infinite, only the answer - Trueshould be expected in finite time.- EXAMPLES: - sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: P = Partitions(12, min_part=2, max_part=5) # needs sage.combinat sage: E = EnumeratedSetFromIterator(P.__iter__) # needs sage.combinat sage: P([5,5,2]) in E # needs sage.combinat True - >>> from sage.all import * >>> from sage.sets.set_from_iterator import EnumeratedSetFromIterator >>> P = Partitions(Integer(12), min_part=Integer(2), max_part=Integer(5)) # needs sage.combinat >>> E = EnumeratedSetFromIterator(P.__iter__) # needs sage.combinat >>> P([Integer(5),Integer(5),Integer(2)]) in E # needs sage.combinat True 
 - unrank(i)[source]¶
- Return the element at position - i.- EXAMPLES: - sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) sage: E.unrank(2) Graph on 8 vertices sage: E.unrank(2) == F.unrank(2) True - >>> from sage.all import * >>> # needs sage.graphs >>> from sage.sets.set_from_iterator import EnumeratedSetFromIterator >>> E = EnumeratedSetFromIterator(graphs, args=(Integer(8),), cache=True) >>> F = EnumeratedSetFromIterator(graphs, args=(Integer(8),), cache=False) >>> E.unrank(Integer(2)) Graph on 8 vertices >>> E.unrank(Integer(2)) == F.unrank(Integer(2)) True 
 
- class sage.sets.set_from_iterator.EnumeratedSetFromIterator_function_decorator(f=None, name=None, **options)[source]¶
- Bases: - Decorator- Decorator for - EnumeratedSetFromIterator.- Name could be string or a function - (args, kwds) -> string.- Warning - If you are going to use this with the decorator - cached_function(), you must place the- @cached_functionfirst. See the example below.- EXAMPLES: - sage: from sage.sets.set_from_iterator import set_from_function sage: @set_from_function ....: def f(n): ....: for i in range(n): ....: yield i**2 + i + 1 sage: f(3) {1, 3, 7} sage: f(100) {1, 3, 7, 13, 21, ...} - >>> from sage.all import * >>> from sage.sets.set_from_iterator import set_from_function >>> @set_from_function ... def f(n): ... for i in range(n): ... yield i**Integer(2) + i + Integer(1) >>> f(Integer(3)) {1, 3, 7} >>> f(Integer(100)) {1, 3, 7, 13, 21, ...} - To avoid ambiguity, it is always better to use it with a call which provides optional global initialization for the call to - EnumeratedSetFromIterator:- sage: @set_from_function(category=InfiniteEnumeratedSets()) ....: def Fibonacci(): ....: a = 1; b = 2 ....: while True: ....: yield a ....: a, b = b, a + b sage: F = Fibonacci(); F {1, 2, 3, 5, 8, ...} sage: F.cardinality() +Infinity - >>> from sage.all import * >>> @set_from_function(category=InfiniteEnumeratedSets()) ... def Fibonacci(): ... a = Integer(1); b = Integer(2) ... while True: ... yield a ... a, b = b, a + b >>> F = Fibonacci(); F {1, 2, 3, 5, 8, ...} >>> F.cardinality() +Infinity - A simple example with many options: - sage: @set_from_function(name="From %(m)d to %(n)d", ....: category=FiniteEnumeratedSets()) ....: def f(m, n): return xsrange(m, n + 1) sage: E = f(3,10); E From 3 to 10 sage: E.list() [3, 4, 5, 6, 7, 8, 9, 10] sage: E = f(1,100); E From 1 to 100 sage: E.cardinality() 100 sage: f(n=100, m=1) == E True - >>> from sage.all import * >>> @set_from_function(name="From %(m)d to %(n)d", ... category=FiniteEnumeratedSets()) ... def f(m, n): return xsrange(m, n + Integer(1)) >>> E = f(Integer(3),Integer(10)); E From 3 to 10 >>> E.list() [3, 4, 5, 6, 7, 8, 9, 10] >>> E = f(Integer(1),Integer(100)); E From 1 to 100 >>> E.cardinality() 100 >>> f(n=Integer(100), m=Integer(1)) == E True - An example which mixes together - set_from_function()and- cached_method():- sage: @cached_function ....: @set_from_function(name="Graphs on %(n)d vertices", ....: category=FiniteEnumeratedSets(), cache=True) ....: def Graphs(n): return graphs(n) sage: Graphs(10) # needs sage.graphs Graphs on 10 vertices sage: Graphs(10).unrank(0) # needs sage.graphs Graph on 10 vertices sage: Graphs(10) is Graphs(10) # needs sage.graphs True - >>> from sage.all import * >>> @cached_function ... @set_from_function(name="Graphs on %(n)d vertices", ... category=FiniteEnumeratedSets(), cache=True) ... def Graphs(n): return graphs(n) >>> Graphs(Integer(10)) # needs sage.graphs Graphs on 10 vertices >>> Graphs(Integer(10)).unrank(Integer(0)) # needs sage.graphs Graph on 10 vertices >>> Graphs(Integer(10)) is Graphs(Integer(10)) # needs sage.graphs True - The - @cached_functionmust go first:- sage: @set_from_function(name="Graphs on %(n)d vertices", ....: category=FiniteEnumeratedSets(), cache=True) ....: @cached_function ....: def Graphs(n): return graphs(n) sage: Graphs(10) # needs sage.graphs Graphs on 10 vertices sage: Graphs(10).unrank(0) # needs sage.graphs Graph on 10 vertices sage: Graphs(10) is Graphs(10) # needs sage.graphs False - >>> from sage.all import * >>> @set_from_function(name="Graphs on %(n)d vertices", ... category=FiniteEnumeratedSets(), cache=True) ... @cached_function ... def Graphs(n): return graphs(n) >>> Graphs(Integer(10)) # needs sage.graphs Graphs on 10 vertices >>> Graphs(Integer(10)).unrank(Integer(0)) # needs sage.graphs Graph on 10 vertices >>> Graphs(Integer(10)) is Graphs(Integer(10)) # needs sage.graphs False 
- class sage.sets.set_from_iterator.EnumeratedSetFromIterator_method_caller(inst, f, name=None, **options)[source]¶
- Bases: - Decorator- Caller for decorated method in class. - INPUT: - inst– an instance of a class
- f– a method of a class of- inst(and not of the instance itself)
- name– (optional) either a string (which may contains substitution rules from argument or a function- args, kwds -> string
- options– any option accepted by- EnumeratedSetFromIterator
 
- class sage.sets.set_from_iterator.EnumeratedSetFromIterator_method_decorator(f=None, **options)[source]¶
- Bases: - object- Decorator for enumerated set built from a method. - INPUT: - f– (optional) function from which are built the enumerated sets at each call
- name– (optional) string (which may contains substitution rules from argument) or a function- (args,kwds) -> string
- any option accepted by - EnumeratedSetFromIterator.
 - EXAMPLES: - sage: from sage.sets.set_from_iterator import set_from_method sage: class A(): ....: def n(self): return 12 ....: @set_from_method ....: def f(self): return xsrange(self.n()) sage: a = A() sage: print(a.f.__class__) <class 'sage.sets.set_from_iterator.EnumeratedSetFromIterator_method_caller'> sage: a.f() {0, 1, 2, 3, 4, ...} sage: A.f(a) {0, 1, 2, 3, 4, ...} - >>> from sage.all import * >>> from sage.sets.set_from_iterator import set_from_method >>> class A(): ... def n(self): return Integer(12) ... @set_from_method ... def f(self): return xsrange(self.n()) >>> a = A() >>> print(a.f.__class__) <class 'sage.sets.set_from_iterator.EnumeratedSetFromIterator_method_caller'> >>> a.f() {0, 1, 2, 3, 4, ...} >>> A.f(a) {0, 1, 2, 3, 4, ...} - A more complicated example with a parametrized name: - sage: class B(): ....: @set_from_method(name="Graphs(%(n)d)", ....: category=FiniteEnumeratedSets()) ....: def graphs(self, n): return graphs(n) sage: b = B() sage: G3 = b.graphs(3); G3 Graphs(3) sage: G3.cardinality() # needs sage.graphs 4 sage: G3.category() Category of facade finite enumerated sets sage: B.graphs(b, 3) Graphs(3) - >>> from sage.all import * >>> class B(): ... @set_from_method(name="Graphs(%(n)d)", ... category=FiniteEnumeratedSets()) ... def graphs(self, n): return graphs(n) >>> b = B() >>> G3 = b.graphs(Integer(3)); G3 Graphs(3) >>> G3.cardinality() # needs sage.graphs 4 >>> G3.category() Category of facade finite enumerated sets >>> B.graphs(b, Integer(3)) Graphs(3) - And a last example with a name parametrized by a function: - sage: class D(): ....: def __init__(self, name): self.name = str(name) ....: def __str__(self): return self.name ....: @set_from_method(name=lambda self, n: str(self) * n, ....: category=FiniteEnumeratedSets()) ....: def subset(self, n): ....: return xsrange(n) sage: d = D('a') sage: E = d.subset(3); E aaa sage: E.list() [0, 1, 2] sage: F = d.subset(n=10); F aaaaaaaaaa sage: F.list() [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - >>> from sage.all import * >>> class D(): ... def __init__(self, name): self.name = str(name) ... def __str__(self): return self.name ... @set_from_method(name=lambda self, n: str(self) * n, ... category=FiniteEnumeratedSets()) ... def subset(self, n): ... return xsrange(n) >>> d = D('a') >>> E = d.subset(Integer(3)); E aaa >>> E.list() [0, 1, 2] >>> F = d.subset(n=Integer(10)); F aaaaaaaaaa >>> F.list() [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - Todo - It is not yet possible to use - set_from_methodin conjunction with- cached_method.