Integral interval exchanges

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 1)

surface_dynamics.interval_exchanges.integer_iet.cylinder_number(top, bot, lengths)

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 704)

Return the number of cylinders and of a given interval exchange

EXAMPLES:

sage: from surface_dynamics.interval_exchanges.integer_iet import cylinder_number

sage: top = [0, 1]
sage: bot = [1, 0]
sage: cylinder_number(top, bot, [13, 24])
1

sage: top = [0, 0]
sage: bot = [1, 1, 2, 2, 3, 3, 4, 4]
sage: cylinder_number(top, bot, [10, 4, 3, 2, 1])
2

sage: top = [0, 0, 1, 1, 2, 2]
sage: bot = [3, 3, 4, 4, 5, 5, 6, 6]
sage: cylinder_number(top, bot, [8, 7, 10, 8, 10, 1, 6])
3
surface_dynamics.interval_exchanges.integer_iet.cylinder_statistics(top, bot, L, kind=0, flat=False)

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 556)

Return the statistics of the number of cylinders for a given total length

INPUT:

  • top – (list) composition of the top of the cylinder

  • bot – (list) composition of the bottom of the cylinder

  • L – (positive integer) the length we are considering

  • kind (integer) – choose the statistics to gather - kind=0: number of cylinders - kind=1: number of components - kind=2: tuple of cylinder widths - kind=3: tuple of cylinder heights - kind=4: tuple of pairs (cylinder width, cylinder height)

  • flat (boolean, default False) - whether to return the result as a dictionary or as a list.

OUTPUT: if flat=False a dictionary whose keys are integers or tuples and the value associated to a key k is the number of length data with sum L which corresponds to an iet with data top and bot and whose cylinder decomposition has statistics k. If flat=True a list for each each term is a statistics.

EXAMPLES:

sage: from surface_dynamics.interval_exchanges.integer_iet import cylinder_statistics

The case of H(0,0):

sage: top = [0, 1]
sage: bot = [1, 0]
sage: for n in range(2,20):
....:     s = cylinder_statistics(top, bot, n)
....:     print("%2d : %3d %3d %3d" %(n, s[1], s[2], s[1] + s[2]))
 2 :   1   1   2
 3 :   4   2   6
 4 :   7   5  12
 5 :  16   4  20
 6 :  15  15  30
 7 :  36   6  42
 8 :  35  21  56
 9 :  52  20  72
10 :  53  37  90
11 : 100  10 110
12 :  65  67 132
13 : 144  12 156
14 : 115  67 182
15 : 132  78 210
16 : 155  85 240
17 : 256  16 272
18 : 165 141 306
19 : 324  18 342

Which are the same numbers as Q(0,-1^4):

sage: top1 = [0, 1]
sage: bot1 = [1, 0]
sage: top2 = [0, 0]
sage: bot2 = [1, 1, 2, 2]
sage: for _ in range(20):
....:     n = randint(2, 100)
....:     s1 = cylinder_statistics(top1, bot1, n)
....:     s2 = cylinder_statistics(top2, bot2, 2*n)
....:     assert sorted(s1.keys()) == sorted(s2.keys())
....:     assert all(2*s1[i] == s2[i] for i in s1)
surface_dynamics.interval_exchanges.integer_iet.cylinder_widths(top, bot, lengths)

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 769)

Return the widths of cylinders of the interval exchange determined by top, bot, lengths.

EXAMPLES:

sage: from surface_dynamics.interval_exchanges.integer_iet import cylinder_widths

sage: top = [0, 1]
sage: bot = [1, 0]
sage: cylinder_widths(top, bot, [13, 24]) == [1]
True

sage: top = [0, 0]
sage: bot = [1, 1, 2, 2, 3, 3, 4, 4]
sage: cylinder_widths(top, bot, [10, 4, 3, 2, 1]) == [1, 2]
True

Genus 0 examples:

sage: top = [0, 0, 1, 1, 2, 2]
sage: bot = [3, 3, 4, 4, 5, 5, 6, 6]
sage: cylinder_widths(top, bot, [8, 7, 10, 8, 10, 1, 6]) == [1, 2, 8]
True
sage: cylinder_widths(top, bot, [1298, 814, 23, 140, 1034, 819, 142]) == [2, 3]
True
sage: cylinder_widths(top, bot, [78745, 39773, 19984, 21665, 31239, 437, 85161]) == [1, 1, 1]
True
sage: cylinder_widths(top, bot, [57453, 9483, 110211, 100249, 36644, 9853, 30401]) == [1, 1, 3]
True

sage: top = [0, 0, 1, 1]
sage: bot = [2, 2, 3, 3, 4, 4, 5, 5]
sage: cylinder_widths(top, bot, [746825, 30952, 206252, 348, 538642, 32535]) == [1]
True
sage: cylinder_widths(top, bot, [219989, 91122, 70542, 187806, 5742, 47021]) == [1, 2]
True
sage: cylinder_widths(top, bot, [49622, 73834, 4390, 46944, 43358, 28764]) == [2, 10]
True
sage: cylinder_widths(top, bot, [25489, 109646, 25473, 7492, 11490, 90680]) == [1, 2]
True

Genus 3 example:

sage: top = [0, 1, 2, 3, 4, 5, 3, 4, 6]
sage: bot = [7, 8, 1, 7, 8, 2, 5, 6, 0]
sage: cylinder_widths(top, bot, [8, 10, 8, 12, 7, 3, 10, 11, 8]) == [1]
True
sage: cylinder_widths(top, bot, [9, 10, 8, 1, 6, 3, 5, 4, 3]) == [1, 1]
True
sage: cylinder_widths(top, bot, [11, 10, 8, 12, 7, 3, 10, 11, 8]) == [1, 1, 2]
True
sage: cylinder_widths(top, bot, [948, 803, 775, 12, 7, 951, 10, 11, 8]) == [1]
True
surface_dynamics.interval_exchanges.integer_iet.cylinder_widths_and_heights(top, bot, lengths)

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 734)

Return the list of pairs (width, height) of each periodic component of the iet determined by top, bot and lengths.

EXAMPLES:

sage: from surface_dynamics.interval_exchanges.integer_iet import cylinder_widths_and_heights

sage: cylinder_widths_and_heights([0,1],[1,0],[5,2]) == [(1, 7)]
True
sage: cylinder_widths_and_heights([0,1],[1,0],[8,12]) == [(4, 5)]
True

sage: cylinder_widths_and_heights([0,1,2],[2,1,0],[5,3,2]) == [(1, 10)]
True

sage: cylinder_widths_and_heights(list(range(8)), list(range(7,-1,-1)), [1386,924,660,495,385,308,252,210]) == [(2, 930), (3, 920)]
True
surface_dynamics.interval_exchanges.integer_iet.interval_exchange_statistics(top, bot, L, kind=0, flat=False)

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 284)

Return the statistics about cylinder decompositions of the integral interval exchanges with given permutation (top, bot) and total length L.

An integral interval exchange transformation (or iet for short) decomposes into periodic components. This function allows to study these components (ie number and geometry).

INPUT:

  • top, bot (lists) – top and bottom labels (as list of numbers from 0 to n-1 where n is the number of intervals)

  • L (integer) – the total length of the integral iets to be tested

  • kind (integer) – choose the statistics to gather - kind=0: number of cylinders - kind=1: number of components - kind=2: tuple of cylinder widths - kind=3: tuple of cylinder heights - kind=4: tuple of pairs (cylinder width, cylinder height)

  • flat (boolean, default False) - whether to return the result as a dictionary or as a list.

OUTPUT: if flat=False a dictionary whose keys are integers or tuples and the value associated to a key k is the number of length data with sum L which corresponds to an iet with data top and bot and whose cylinder decomposition has statistics k. If flat=True a list for each each term is a statistics.

EXAMPLES:

Rotations always give a unique cylinder:

   sage: from surface_dynamics.interval_exchanges.integer_iet import interval_exchange_statistics
   sage: interval_exchange_statistics([0,1], [1,0], 10, 0)
   {1: 9}

Though, the widths of this unique cylinder is the gcd of the two lengths::

   sage: interval_exchange_statistics([0,1], [1,0], 10, 1) == {1: 4, 2: 4, 5: 1}
   True
   sage: [gcd(k, 10-k) for k in range(1,10)]
   [1, 2, 1, 2, 5, 2, 1, 2, 1]

Complete information about the heights of cylinders are obtained by setting kind=2:

sage: s2 = interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 2)
sage: for k in sorted(s2):
....:     print("%-6s: %s" % ('(' + ', '.join('%d' % i for i in k) + ')', s2[k]))
(1)   : 34
(1, 1): 16
(1, 2): 16
(1, 3): 4
(1, 4): 6
(1, 6): 2
(2, 2): 4
(2, 3): 2

You can recover kind=0 and kind=1 by looking and lengths and sums:

sage: from collections import defaultdict
sage: s0 = defaultdict(int)
sage: s1 = defaultdict(int)
sage: for k, v in s2.items():
....:     s0[len(k)] += v
....:     s1[sum(k)] += v

sage: dict(s0) == interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 0)
True
sage: dict(s1) == interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 1)
True

To get statistics for the heights, consider using kind=3:

sage: s3 = interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 3)
sage: for k in sorted(s3):
....:     print("%-6s: %s" % ('(' + ', '.join('%d' % i for i in k) + ')', s3[k]))
(1, 4): 4
(1, 6): 4
(1, 8): 4
(2, 2): 4
(2, 3): 2
(2, 4): 8
(2, 6): 6
(2, 8): 8
(3, 4): 2
(4, 6): 8
(10)  : 34

And for both lengths and heights, kind=4:

sage: s4 = interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 4)
sage: for key in s4:
....:     assert sum(l*h for l,h in key) == 10
surface_dynamics.interval_exchanges.integer_iet.interval_exchange_statistics_sample(top, bot, L, sample_size, kind=0, flat=False)

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 430)

Return the statistics of cylinder decomposition of a random sample of sample_size integral iet with given permutation top and bot.

INPUT:

  • top, bot – top and bottom permutation (as list of numbers starting from 0)

  • L (integer) – a magnitude order for the total length of the integral iet to be generated

  • sample_size – size of the sample

  • kind (integer) – choose the statistics to gather - kind=0: number of cylinders - kind=1: number of components - kind=2: tuple of cylinder widths - kind=3: tuple of cylinder heights - kind=4: tuple of pairs (cylinder width, cylinder height)

  • flat (boolean, default False) - whether to return the result as a dictionary or as a list.

OUTPUT: if flat=False a dictionary whose keys are integers or tuples and the value associated to a key k is the number of length data with sum L which corresponds to an iet with data top and bot and whose cylinder decomposition has statistics k. If flat=True a list for each each term is a statistics.

EXAMPLES:

Rotations always give a unique cylinder:

   sage: from surface_dynamics.interval_exchanges.integer_iet import interval_exchange_statistics
   sage: interval_exchange_statistics([0,1],[1,0],10,0)
   {1: 9}

Though, the widths of this unique cylinder is the gcd of the two lengths::

   sage: interval_exchange_statistics([0,1],[1,0],10,1) == {1: 4, 2: 4, 5: 1}
   True
   sage: [gcd(k, 10-k) for k in range(1,10)]
   [1, 2, 1, 2, 5, 2, 1, 2, 1]

Complete information about the heights of cylinders are obtained by setting kind=2:

sage: s2 = interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 2)
sage: for k in sorted(s2):
....:     print("%-6s: %s" % ('(' + ', '.join('%d' % i for i in k) + ')', s2[k]))
(1)   : 34
(1, 1): 16
(1, 2): 16
(1, 3): 4
(1, 4): 6
(1, 6): 2
(2, 2): 4
(2, 3): 2

You can recover kind=0 and kind=1 by looking and lengths and sums:

sage: from collections import defaultdict
sage: s0 = defaultdict(int)
sage: s1 = defaultdict(int)
sage: for k, v in s2.items():
....:     s0[len(k)] += v
....:     s1[sum(k)] += v

sage: dict(s0) == interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 0)
True
sage: dict(s1) == interval_exchange_statistics([0,1,2,3], [3,2,1,0], 10, 1)
True

An example of flat statistics in Q(1,1,1,1):

sage: stats = interval_exchange_statistics([0,1,2,3,1,4,5], [2,6,5,4,6,3,0], 10, kind=4, flat=True)
sage: len(stats)
40
sage: assert stats[:4] == [((1, 3), (1, 3), (1, 4)), ((1, 1), (1, 9)), ((1, 3), (1, 7)), ((1, 2), (1, 8))]
sage: assert stats[-4:] == [((1, 2), (1, 8)), ((1, 3), (1, 7)), ((1, 3), (1, 7)), ((1, 5), (1, 5))]
surface_dynamics.interval_exchanges.integer_iet.perm_to_twin(p)

File: surface_dynamics/interval_exchanges/integer_iet.pyx (starting at line 105)

Return the twin associated to the permutation p.

EXAMPLES:

sage: from surface_dynamics.interval_exchanges.integer_iet import perm_to_twin
sage: perm_to_twin([0,0,1,1,2,2])
[1, 0, 3, 2, 5, 4]
sage: perm_to_twin([0,1,2,0])
Traceback (most recent call last):
...
ValueError: p must contain integer only between 0 and 1
sage: perm_to_twin([0,0,1,0])
Traceback (most recent call last):
...
ValueError: each label must appear exactly twice
sage: perm_to_twin([1,0,1])
Traceback (most recent call last):
...
ValueError: p must have even length