In [1]:
import tohu
from tohu.v4.primitive_generators import Integer
from tohu.v4.derived_generators import *
from tohu.v4.dispatch_generators import SelectOne
from tohu.v4.utils import print_generated_sequence, make_dummy_tuples

In [2]:
print(f'Tohu version: {tohu.__version__}')


Tohu version: v0.5.0+213.g591a6fa.dirty

Apply

Apply allows applying a given function to one or multiple input generators.

Example: squaring a single integer


In [3]:
def square(x):
    return x * x

In [4]:
g = Integer(0, 9).set_tohu_name('g')
h = Apply(square, g).set_tohu_name('h')

In [5]:
g.reset(seed=12345)
print_generated_sequence(g, num=20, fmt='2d')
print_generated_sequence(h, num=20, fmt='2d')


Generated sequence:  6,  0,  4,  5,  3,  4,  9,  6,  2,  5,  1,  6,  4,  8,  2,  9,  8,  2,  5,  1
Generated sequence: 36,  0, 16, 25,  9, 16, 81, 36,  4, 25,  1, 36, 16, 64,  4, 81, 64,  4, 25,  1

Example: combining multiple integers


In [6]:
g1 = Integer(1, 9)
g2 = Integer(1, 9)
g3 = Integer(1, 9)

Let's define a function which takes three integers as input and apply it to the generators g1, g2, g3 defined above.


In [7]:
def func(x, y, z):
    return x * 100 + y*10 + z

In [8]:
h = Apply(func, g1, g2, g3)

In [9]:
g1.reset(seed=11111)
g2.reset(seed=22222)
g3.reset(seed=33333)
print_generated_sequence(g1, num=10, fmt='3d')
print_generated_sequence(g2, num=10, fmt='3d')
print_generated_sequence(g3, num=10, fmt='3d')
print_generated_sequence(h, num=10, fmt='3d')


Generated sequence:   6,   1,   6,   6,   7,   2,   9,   3,   3,   6
Generated sequence:   5,   5,   8,   7,   3,   7,   3,   4,   9,   2
Generated sequence:   3,   7,   8,   8,   4,   6,   6,   6,   5,   9
Generated sequence: 653, 157, 688, 678, 734, 276, 936, 346, 395, 629

"Chained" Apply


In [10]:
def add(x, y):
    return x + y

Example 1: chaining explicitly defined generators


In [11]:
g1 = Integer(100, 200)
g2 = Integer(300, 400)
g3 = Integer(500, 600)
g4 = Integer(700, 800)

In [12]:
h5 = Apply(add, g1, g2)
h6 = Apply(add, g3, g4)
h7 = Apply(add, h5, h6)

In [13]:
items1 = list(g1.generate(num=10, seed=11111))
items2 = list(g2.generate(num=10, seed=22222))
items3 = list(g3.generate(num=10, seed=33333))
items4 = list(g4.generate(num=10, seed=44444))

In [14]:
#items5 = list(h5.generate(num=10))
#items6 = list(h6.generate(num=10))
items7 = list(h7.generate(num=10))

In [15]:
items_expected = [a+b+c+d for (a, b, c, d) in zip(items1, items2, items3, items4)]

In [16]:
print(items_expected)
print(items7)


[1699, 1741, 1783, 1850, 1900, 1805, 1788, 1761, 1822, 1882]
[1699, 1741, 1783, 1850, 1900, 1805, 1788, 1761, 1822, 1882]

In [17]:
assert items_expected == items7

Example 2: chaining implicitly defined generators


In [18]:
g1 = Integer(100, 200)
g2 = Integer(300, 400)
g3 = Integer(500, 600)
g4 = Integer(700, 800)

In [19]:
h = Apply(add, Apply(add, g1, g2), Apply(add, g3, g4))

In [20]:
items1 = list(g1.generate(num=10, seed=11111))
items2 = list(g2.generate(num=10, seed=22222))
items3 = list(g3.generate(num=10, seed=33333))
items4 = list(g4.generate(num=10, seed=44444))

In [21]:
items_h = list(h.generate(num=10))

In [22]:
items_expected = [a+b+c+d for (a, b, c, d) in zip(items1, items2, items3, items4)]

In [23]:
print(items_expected)
print(items_h)


[1699, 1741, 1783, 1850, 1900, 1805, 1788, 1761, 1822, 1882]
[1699, 1741, 1783, 1850, 1900, 1805, 1788, 1761, 1822, 1882]

In [24]:
assert items_expected == items_h

GetAttribute


In [25]:
chars = 'abcdefghijklmnopqrstuvwxyz'

In [26]:
some_tuples = make_dummy_tuples(chars)

In [27]:
g = SelectOne(some_tuples)

In [28]:
print_generated_sequence(g, num=10, sep='\n', seed=12345)


Generated sequence:

Quux(x='NN', y='nn')
Quux(x='XX', y='xx')
Quux(x='AA', y='aa')
Quux(x='ZZ', y='zz')
Quux(x='JJ', y='jj')
Quux(x='LL', y='ll')
Quux(x='GG', y='gg')
Quux(x='II', y='ii')
Quux(x='SS', y='ss')
Quux(x='NN', y='nn')

In [29]:
h1 = GetAttribute(g, 'x')
h2 = GetAttribute(g, 'y')

In [30]:
g.reset(seed=12345)
print_generated_sequence(g, num=10, sep='\n', seed=12345)
print_generated_sequence(h1, num=10)
print_generated_sequence(h2, num=10)


Generated sequence:

Quux(x='NN', y='nn')
Quux(x='XX', y='xx')
Quux(x='AA', y='aa')
Quux(x='ZZ', y='zz')
Quux(x='JJ', y='jj')
Quux(x='LL', y='ll')
Quux(x='GG', y='gg')
Quux(x='II', y='ii')
Quux(x='SS', y='ss')
Quux(x='NN', y='nn')
Generated sequence: NN, XX, AA, ZZ, JJ, LL, GG, II, SS, NN
Generated sequence: nn, xx, aa, zz, jj, ll, gg, ii, ss, nn

Lookup


In [31]:
double_chars = [c*2 for c in chars]

In [32]:
def dec(char, repeat=1):
    "Convert `char` to a string, optionally repeating multiple times"
    s = str(ord(char) - 96)
    return s * repeat

In [33]:
mapping = {c*2: [dec(c, repeat=1), dec(c, repeat=2), dec(c, repeat=3)] for c in chars}
#mapping

Example 1: chaining of explicitly defined generators


In [34]:
g = SelectOne(double_chars)
h1 = Lookup(g, mapping)
h2 = SelectOneDerived(h1)  # chained lookup

In [35]:
g.reset(seed=12345)
h2.reset(seed=99999)
print_generated_sequence(g, num=20, seed=12345)
print_generated_sequence(h1, num=20)
print_generated_sequence(h2, num=20)


Generated sequence: nn, xx, aa, zz, jj, ll, gg, ii, ss, nn, ff, ll, dd, nn, ii, rr, uu, ff, tt, rr
Generated sequence: ['14', '1414', '141414'], ['24', '2424', '242424'], ['1', '11', '111'], ['26', '2626', '262626'], ['10', '1010', '101010'], ['12', '1212', '121212'], ['7', '77', '777'], ['9', '99', '999'], ['19', '1919', '191919'], ['14', '1414', '141414'], ['6', '66', '666'], ['12', '1212', '121212'], ['4', '44', '444'], ['14', '1414', '141414'], ['9', '99', '999'], ['18', '1818', '181818'], ['21', '2121', '212121'], ['6', '66', '666'], ['20', '2020', '202020'], ['18', '1818', '181818']
Generated sequence: 14, 2424, 111, 262626, 101010, 12, 77, 99, 19, 1414, 66, 121212, 444, 141414, 999, 18, 21, 666, 2020, 181818

Example 2: chaining of implicitly defined generators


In [36]:
g = SelectOne(double_chars)
h = SelectOneDerived(Lookup(g, mapping))  # chained lookup

In [37]:
g.reset(seed=12345)
h.reset(seed=99999)
print_generated_sequence(g, num=20, seed=12345)
print_generated_sequence(h, num=20)


Generated sequence: nn, xx, aa, zz, jj, ll, gg, ii, ss, nn, ff, ll, dd, nn, ii, rr, uu, ff, tt, rr
Generated sequence: 14, 2424, 111, 262626, 101010, 12, 77, 99, 19, 1414, 66, 121212, 444, 141414, 999, 18, 21, 666, 2020, 181818

SelectOneDerived


In [38]:
g = SelectOne([(1, 11, 111), (2, 22, 222), (3, 33, 333), (4, 44, 444), (5, 55, 555)])
h = SelectOneDerived(g)

In [39]:
g.reset(seed=12345)
h.reset(seed=99999)

print_generated_sequence(g, num=10)
print_generated_sequence(h, num=10)


Generated sequence: (4, 44, 444), (1, 11, 111), (3, 33, 333), (3, 33, 333), (2, 22, 222), (3, 33, 333), (5, 55, 555), (4, 44, 444), (2, 22, 222), (3, 33, 333)
Generated sequence: 4, 11, 333, 333, 222, 3, 55, 44, 2, 33

In [ ]: