Recurrent sequence scales

Given a recurrent sequence like the Fibonacci sequence

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

pick a start point and end point, say 3 and 34, take the segment between them

3, 5, 8, 13, 21, 34

divide by the smallest term

3/3, 5/3, 8/3, 13/3, 21/3, 34/3

then octave-reduce and sort to give the scale

1/1, 13/12, 4/3, 17/12, 5/3, 7/4

with period 2/1.

As you move along a recurrent sequence, the ratio between successive terms approaches a limit (1.618, or 833ยข, for the Fibonacci sequence). This means that segments far along the sequence approach scales built by stacking a generator. This gives a connection to moments of symmetry.

Further reading

Python code
"""
>>> scale1 = recurrent_sequence_scale((1, 1), (1, 1), 3, 8)
>>> scale2 = recurrent_sequence_scale((1, 1), (1, 1), 6, 11)
>>> scale3 = sorted((i * 833) % 1200 for i in range(6))
>>> print([round(1200 * log2(x)) for x in scale1])
[0, 139, 498, 603, 884, 969]
>>> print([round(1200 * log2(x)) for x in scale2])
[0, 97, 464, 563, 830, 930]
>>> print(scale3)
[0, 99, 466, 565, 833, 932]
"""

from fractions import Fraction
from math import log2, floor


def reduce(x):
    return x * Fraction(2) ** (-floor(log2(x)))


def recurrent_sequence_scale(coeffs, seed, start, stop):
    """
    >>> recurrent_sequence_scale((1, 1), (1, 1), 3, 8)
    [Fraction(1, 1), Fraction(13, 12), Fraction(4, 3), Fraction(17, 12), Fraction(5, 3), Fraction(7, 4)]
    """
    seq = list(seed)
    while len(seq) <= stop:
        seq.append(sum(c * seq[-i] for i, c in enumerate(coeffs, 1)))
    segment = seq[start : stop + 1]
    return sorted(set(reduce(Fraction(x, segment[0])) for x in segment))

Scales

FileCall
raph recurrent_sequence_scale((0, 1, 0, 1), (45, 57, 73, 93), 0, 11)
xen13-mclaren-recurrence-1 recurrent_sequence_scale((1, 1), (1, 1), 0, 10)