Skip to content

Commit 570f05c

Browse files
committed
Update: random number generators
1 parent f2bfcf7 commit 570f05c

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed

kaleidoscope/generators.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Copyright (c) Brockmann Consult GmbH, 2025
2+
# License: MIT
3+
4+
"""
5+
This module provides random number generators.
6+
"""
7+
8+
import numpy as np
9+
from numpy.random import BitGenerator
10+
from numpy.random import Generator
11+
from overrides import overrides
12+
13+
from .interface.generating import Generating
14+
from .interface.generating import Normal
15+
from .interface.generating import Uniform
16+
from .interface.generating import Univariate
17+
18+
19+
def default_bit_generator(
20+
seed: int | np.ndarray | None = None,
21+
) -> BitGenerator:
22+
"""
23+
Returns the default bit generator.
24+
25+
:param seed: The seed.
26+
:return: The default bit generator.
27+
"""
28+
from numpy.random import PCG64DXSM
29+
30+
return PCG64DXSM(seed)
31+
32+
33+
def default_generator(seed) -> Generator:
34+
"""
35+
Returns the default generator.
36+
37+
:param seed: The seed.
38+
:return: The default generator.
39+
"""
40+
return Generator(
41+
seed
42+
if isinstance(seed, BitGenerator)
43+
else default_bit_generator(seed)
44+
)
45+
46+
47+
class DefaultGenerator(Generating):
48+
"""The default random number generator."""
49+
50+
_g: Generator
51+
52+
def __init__(self, seed: int | np.ndarray | BitGenerator | None = None):
53+
"""
54+
Creates a new random number generator.
55+
56+
:param seed: The seed.
57+
"""
58+
self._g = default_generator(seed)
59+
60+
@overrides
61+
def random(self) -> int:
62+
return self._g.integers(0x8000000000000000)
63+
64+
65+
class DefaultUniform(Uniform):
66+
"""The default uniform random deviate."""
67+
68+
_g: Generator
69+
70+
def __init__(self, seed: int | np.ndarray | BitGenerator | None = None):
71+
"""
72+
Creates a new random variate.
73+
74+
:param seed: The seed.
75+
"""
76+
self._g = default_generator(seed)
77+
78+
@overrides
79+
def get(self, i: int) -> Univariate:
80+
return self
81+
82+
@overrides
83+
def random(self) -> float:
84+
return self._g.random()
85+
86+
@overrides
87+
def randoms(self, randoms: np.ndarray) -> np.ndarray:
88+
self._g.random(out=randoms)
89+
return randoms
90+
91+
92+
class DefaultNormal(Normal):
93+
"""The default normal random variate."""
94+
95+
_g: Generator
96+
97+
def __init__(self, seed: int | np.ndarray | BitGenerator | None = None):
98+
"""
99+
Creates a new random variate.
100+
101+
:param seed: The seed.
102+
"""
103+
self._g = default_generator(seed)
104+
105+
@overrides
106+
def get(self, i: int) -> Univariate:
107+
return self
108+
109+
@overrides
110+
def random(self) -> float:
111+
return self._g.standard_normal()
112+
113+
@overrides
114+
def randoms(self, randoms: np.ndarray) -> np.ndarray:
115+
self._g.standard_normal(out=randoms)
116+
return randoms
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright (c) Brockmann Consult GmbH, 2025
2+
# License: MIT
3+
4+
"""
5+
This module provides unit-level tests for random number generators.
6+
"""
7+
8+
import unittest
9+
10+
from numpy.random import PCG64
11+
12+
from kaleidoscope.generators import DefaultGenerator
13+
14+
15+
class DefaultGeneratorTest(unittest.TestCase):
16+
17+
def test_random(self):
18+
rng = DefaultGenerator(seed=PCG64(42))
19+
self.assertEqual(6164909031098000398, rng.random())
20+
self.assertEqual(62765134502071353, rng.random())
21+
self.assertEqual(6068961337446000720, rng.random())
22+
self.assertEqual(3424215743300924766, rng.random())
23+
self.assertEqual(1906168894638979906, rng.random())
24+
self.assertEqual(1787925334117997081, rng.random())
25+
26+
27+
if __name__ == "__main__":
28+
unittest.main()

0 commit comments

Comments
 (0)