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.start
andself.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 fromargs
– 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 setcategory
– (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 asFiniteEnumeratedSets
, conversely if you know that your iterator will run over and over you should set it asInfiniteEnumeratedSets
.cache
– boolean (default:False
); whether or not use a cache mechanism for the iterator. IfTrue
, 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
TestSuite
works, 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
x
is inself
.If the set is infinite, only the answer
True
should 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_function
first. 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()
andcached_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_function
must 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 classf
– a method of a class ofinst
(and not of the instance itself)name
– (optional) either a string (which may contains substitution rules from argument or a functionargs, kwds -> string
options
– any option accepted byEnumeratedSetFromIterator
- 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 callname
– (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_method
in conjunction withcached_method
.