{"id":19053204,"url":"https://github.com/greydevv/pseudo-rng","last_synced_at":"2025-10-30T17:48:24.837Z","repository":{"id":133696198,"uuid":"364271051","full_name":"greydevv/pseudo-rng","owner":"greydevv","description":"Research and code regarding Linear Congruential Generators.","archived":false,"fork":false,"pushed_at":"2022-01-13T16:25:02.000Z","size":28,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-02T10:45:25.192Z","etag":null,"topics":["arithmetic","lcg","modulus","period","prime-numbers","pseudorandom-numbers"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/greydevv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-04T13:47:35.000Z","updated_at":"2023-10-03T07:25:31.000Z","dependencies_parsed_at":"2024-08-21T08:00:46.318Z","dependency_job_id":null,"html_url":"https://github.com/greydevv/pseudo-rng","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydevv%2Fpseudo-rng","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydevv%2Fpseudo-rng/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydevv%2Fpseudo-rng/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydevv%2Fpseudo-rng/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/greydevv","download_url":"https://codeload.github.com/greydevv/pseudo-rng/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240109718,"owners_count":19749181,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arithmetic","lcg","modulus","period","prime-numbers","pseudorandom-numbers"],"created_at":"2024-11-08T23:29:31.104Z","updated_at":"2025-10-30T17:48:19.786Z","avatar_url":"https://github.com/greydevv.png","language":"Python","readme":"# Pseudorandom Number Generation\n\n\n\n### Contents\n* [Introduction](https://github.com/greysonDEV/pseudo-rng#introduction)\n* [Why Pseudorandom?](https://github.com/greysonDEV/pseudo-rng#why-pseudorandom)\n* [Randomness in Computers](https://github.com/greysonDEV/pseudo-rng#randomness-in-computers)\n* [Linear Congruential Generator (LCG)](https://github.com/greysonDEV/pseudo-rng#linear-congruential-generator-lcg)\n\n\n\n### Introduction\n\nWithin this repository, the `prng` package includes a multitude of functions that allow the user to play around and experiment with pseudorandom number generation (PRNG). In this README I aim to investigate the theory and method behind PRNG as well as record my findings and research here. \n\n\n\n### Why Pseudorandom?\n\nPseudorandom numbers have many applications not only in the world of computer science but also in all of technology. The importance of PRNG is that a sequence of pseudorandom numbers is able to be reproduced, number for number. This is important in debugging computer programs and applications that rely on or deal with random numbers. For example, simulations like the Monte Carlo simulation need random numbers if they are to, well, *simulate*. A very interesting application that can be found on the Monte Carlo [*Wikipedia*](https://en.wikipedia.org/wiki/Monte_Carlo_method) page gives an example of how to calculate π using random numbers. Video games, casinos, and the shuffle feature on Spotify or Apple Music are just some of many applications of pseudorandom numbers. In fact, *all* of today's machine learning models are initialized with random weights so that the model is able to *break the symmetry* and take different paths (essential in gradient descent).\n\n\n\n### Randomness in Computers\n\nComputers are *deterministic* systems. In short, deterministic simply just means that the output of an algorithm is determined only by the inputs into that function. Computers are non-biased machines - they always follow a set of instructions to provide an output from some input. Because of this, computers themselves cannot create *truly* random numbers. Mathematician [*John von Neumann*](https://en.wikipedia.org/wiki/John_von_Neumann) once said:\n\n\u003e *Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin.*\n\nIn other words, a random number simply cannot be created via an arithmetic method. How else, if not arithmetic, can computers generate a truly random number? Well... they can't, hence ***pseudo***random.\n\nComputers, however, are able to *receive* truly random data via an external, non-deterministic method. For example, using a Geiger Counter to measure radioactive activity will provide truly random results. \n\n\n\n### Linear Congruential Generator (LCG)\n\n*Source:* [*Wikipedia*](https://en.wikipedia.org/wiki/Linear_congruential_generator)\n\nAfter reading, consider taking a look at the linked article as this section barely scrapes the surface. \n\nA *Linear Congruential Generator (LCG)* is an algorithm designed to produce pseudorandom numbers. To find the *nth* term in any linear congruential series:\n\n\u003e *X*\u003csub\u003e*n+1*\u003c/sub\u003e = (*aX*\u003csub\u003e*n*\u003c/sub\u003e + *c*)\u003csub\u003e\u003c/sub\u003e (*mod m*)\n\n\n\nThere are four parameters that are passed to an LCG:\n\n1. `m` - modulus\n2. `a` - multiplier\n3. `c` - increment\n4. `n` - seed\n\nLCGs depend heavily on \"good\" parameter choice to produce a long period.\n\nA natural question at this point would be...\n\n\u003e *Well, if the quality of the LCG depends on combinations of parameters, how should we choose the parameters?*\n\nAccording to [*Wikipedia*](https://en.wikipedia.org/wiki/Linear_congruential_generator), there are three main paths to take for LCG parameter choices:\n\n---\n\n#### 1) `m is prime, c = 0`\n\n\u003e *The period is **m−1** if the; multiplier a is chosen to be a primitive element of the integers modulo **m**. The initial state must be chosen between **1** and **m−1**.*\n\n\u003cins\u003e**Example**\u003c/ins\u003e\n```python\n\u003e\u003e\u003e m = 751\n\u003e\u003e\u003e prng = lcg(\n        m=m,\n        a=577,\n        c=0,\n        n=331,\n\n    )\n\n\u003e\u003e\u003e seq = [next(prng) for _ in range(m-1)] # length of 750\n[233, 12, 165, ..., 431, 106, 331]\n```\nIf you haven't guessed already, the period is going to be `m-1 = 751-1 = 750`. This means that if `next` is called on `prng` a few more times, the repetition becomes apparent:\n```python\n\u003e\u003e\u003e next(prng)\n233\n\n\u003e\u003e\u003e next(prng)\n12\n\n\u003e\u003e\u003e next(prng)\n165\n```\nA value for `a` can be achieved with the `primitive_roots()` utility method by passing in `m` (the example above chose 158 for `a`, which is a primitive root of `m`):\n```python\n\u003e\u003e\u003e primitive_roots(263)\n[5, 7, 10, 14, 15, ..., 158, ..., 257, 259, 260, 261]\n```\nFor further examples, the `evaluate_period` utility method is used to return the LCG's period length. Although `evaluate_period()` provides a shortcut for finding the period, the simple, more visual process above may still be utilized.\n\n---\n#### 2) `m is a power of 2, c = 0`\n\n\u003e *This form has maximal period **m/4**, achieved if **a ≡ 3** or **a ≡ 5** (**mod 8**). The initial state **X**\u003csub\u003e**0**\u003c/sub\u003e must be odd...*\n\n\u003cins\u003e**Example**\u003c/ins\u003e\n```python\n\u003e\u003e\u003e prng = lcg(\n        m=2**16,\n        a=524291,\n        c=0,\n        n=48923,\n    )\n\n\u003e\u003e\u003e evaluate_period(prng)\n16384\n```\nAbove the modulus is a power of 2 (`2**16` evaluates to 65536). The multiplier, `a`, mod `m` (`a % m`) evaluates to 3, which also satisfies the constraints. Finally, `c` is zero, and the initial state (`n`) is an odd number. The parameter choices here result in a period of 16384, which is, in fact, one fourth of the modulus.\n\n---\n\n#### 3) `c ≠ 0`\n\n\u003e *When **c ≠ 0**, correctly chosen parameters allow a period equal to **m**, for all seed values.*\n\n\"Correctly chosen parameters,\" as stated in the [*Wikipedia*](https://en.wikipedia.org/wiki/Linear_congruential_generator) article, means that:\n```\n1.  m and c are relatively prime\n2.  a - 1 is divisible by all prime factors of m\n3.  a - 1 is divisible by 4 if m is divisible by 4\n```\nNote that the third condition does not have to be met. It simply states that *if* `m` is divisible by 4, `a-1` must be as well.\n\n\u003cins\u003e**Example**\u003c/ins\u003e\n```python\n\u003e\u003e\u003e prng = lcg(\n        m=2**16, # 65536\n        a=14285,\n        c=3091,\n        n=948,\n    )\n\n\u003e\u003e\u003e evaluate_period(prng)\n65536\n```\nThis is referred to as the *Hull-Dobell Theorem* and provides a parameter structure to achieve a maximal period of `m`. Two methods are defined in this repository for playing around with some of these parameters.\n```python\n# 1.  m and c are relatively prime\n\u003e\u003e\u003e relatively_prime(2**16, 3091)\nTrue\n\n# 2.  a - 1 is divisible by all prime factors of m\n\u003e\u003e\u003e prime_factors(2**16)\n[2]\n```\n\n---\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreydevv%2Fpseudo-rng","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgreydevv%2Fpseudo-rng","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreydevv%2Fpseudo-rng/lists"}