Skip to content

Instantly share code, notes, and snippets.

@jhumigas
Last active April 15, 2024 20:49
Show Gist options
  • Save jhumigas/3a80b5a7e01eb3a59d905e29068714d6 to your computer and use it in GitHub Desktop.
Save jhumigas/3a80b5a7e01eb3a59d905e29068714d6 to your computer and use it in GitHub Desktop.
First try for a Lagged, Fibonacci (pseudo) Random Number Generators
#!usr/bin/python
from random import randint
from math import pow
_lag1 = 55
_lag2 = 24
_modulus = 31
#_firstterms = [randint(0,pow(2,_modulus)) for x in range(0,_lag1)]
_firstterms = [773, 744, 844, 228, 13, 1011, 691, 1, 1106, 730, 438, 102, 498, 1004, 111, 1230, 217, 1133, 703, 686, 78, 551, 60, 1009, 772, 922, 1223, 1205, 511, 876, 992, 162, 85, 296, 837, 755, 579, 268, 64, 194, 811, 645, 626, 140, 395, 1162, 322, 64, 97, 477, 117, 803, 1233, 288, 117, 594]
def lagfib(n):
if n<=_lag1:
# Take among the firstterms
return _firstterms[n]
else:
# Compute recursively Xn
return (lagfib(n-_lag1)+ lagfib(n-_lag2)) % int(pow(2,_modulus))
# # General form
# def lagfibG(n,lag1=55, lag2=24, modulus=31, firstterms=None):
# print('Initialization')
# # Chose the highest lag
# lagmax = max(lag1, lag2)
# if firstterms is None:
# # Generate the first terms
# # Warning : these first terms are generated for the initialization
# firstterms = [randint(0, int(pow(2,modulus))) for x in range(0,lagmax)]
# # print(firstterms)
# print('Generating Xn')
# if n<=lagmax:
# return firstterms[n]
# else:
# # Compute recursively Xn
# return (lagfibG(n-lag1, firstterms=firstterms) + lagfibG(n-lag2, firstterms=firstterms)) % int(pow(2,modulus))
@CelestialStreamer
Copy link

Try this:

from collections import deque

def lagged_fibonacci_sequence(j: int, k: int, m: int):
    """
    A generator of a lagged Fibonacci Sequence defined by:
    ```text
    F(n) = 1, for 0 <= n < k
    F(n) = F(n - j) + F(n - k) (mod m), for n >= k.
    ```
    """
    j, k = min(j, k), max(j, k)  # allow entering offsets in any order
    d = deque([1] * k)
    while True:
        yield d[-k]
        d[-k] = (d[-j] + d[-k]) % m
        d.rotate(-1)

You can generate the first 1,000 terms of your example with:

from itertools import islice

terms = list(islice(lagged_fibonacci_sequence(55, 24, 31), 1000))

@CelestialStreamer
Copy link

If you want to avoid the negative indices:

def lagged_fibonacci_sequence(j: int, k: int, m: int):
    """
    A generator of a lagged Fibonacci Sequence defined by:
    ```text
    F(n) = 1, for 0 <= n < k
    F(n) = F(n - j) + F(n - k) (mod m), for n >= k.
    ```
    """
    j, k = min(j, k), max(j, k)
    d = deque([1] * k)
    j -= 1
    k -= 1
    while True:
        yield d[k]
        d[k] = (d[j] + d[k]) % m
        d.rotate()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment