Random Number Generators
PyHDC provides seven families of deterministic random number generators.
They plug into encodings via the generator= constructor parameter and
produce reproducible hypervectors when seeded.
The HDCGenerator interface
All generators implement the abstract base class
HDCGenerator. Its public interface:
Method |
Description |
|---|---|
|
Return a list of |
|
Return a list of |
|
Return a list of |
|
True if this generator can produce bits |
|
True if this generator can produce words |
|
True if this generator can produce floats |
|
Return to the initial state as if just constructed |
|
Return the current internal state |
|
Set a new seed and reinitialise |
Generator output types and encoding compatibility
Each generator produces one of three output types. The encoding’s
EncodingSpec.generator_output_type specifies which type it needs.
Generator family |
Output type |
Compatible encoding families |
|---|---|---|
LCG, PCG, Xorshift, ShiftedCounter |
words / floats |
All encodings (MAP_C, HRR, BSC, BSDC, FHRR, VTB, MBAT, …) |
LFSR, DLFSR |
bits |
Binary/integer encodings only: MAP_B, MAP_I, BSC, BSDC |
LCA |
bits |
Binary/integer encodings only: MAP_B, MAP_I, BSC, BSDC |
LCG: Linear Congruential Generator
Formula: \(X_{n+1} = (a X_n + c) \bmod m\)
Fast and simple, low-order bits are less random. Sufficient for most HDC experiments.
Classes: LCGGenerator, MultiplicativeLCGGenerator
Presets (CommonLCGGenerators):
numerical_recipes(seed): a = 1664525, c = 1013904223, m = 2^32park_miller(seed): Lehmer generator, no increment; a = 16807, m = 2^31-1minstd_rand(seed): a = 48271borland(seed): Borland C++ parametersglibc(seed): glibc parametersmsvc(seed): Visual C++ parameters
LFSR: Linear Feedback Shift Register
Shifts a binary register and XORs feedback taps to generate bits. Produces a maximal-length sequence of period \(2^n - 1\) for an \(n\)-bit register. Natively produces bits so is suitable for binary and integer encodings.
Classes: LFSRGenerator, FibonacciLFSRGenerator, GaloisLFSRGenerator
Presets (CommonLFSRGenerators): preset tap configurations for widths
8, 10, 12, 14, 16, 24, 32.
DLFSR: Digit-Serial LFSR
A digit-serial variant of LFSR that processes multiple bits per cycle. Useful for hardware implementations where parallelism is available.
Classes: DLFSRGenerator, FibonacciDLFSRGenerator,
GaloisDLFSRGenerator, MatrixDLFSRGenerator
Presets (CommonDLFSRGenerators): various compact configurations.
LCA: Linear Cellular Automata
A 1-D cellular automaton where each cell’s next state depends on itself and its neighbours. Simple, spatially structured, and highly parallelisable.
Classes: LCAGenerator, ElementaryLCAGenerator,
TotalisticLCAGenerator
Presets (CommonLCAGenerators): selected rules with good randomness
properties.
PCG: Permuted Congruential Generator
An LCG with a final permutation step that produces substantially better statistical quality than plain LCG while keeping the same speed. Recommended when you want both reproducibility and good randomness.
Classes: PCGGenerator, MultiplicativePCGGenerator
Presets (CommonPCGGenerators):
pcg32(seed): standard 32-bit PCG (recommended)pcg32_fast(seed): multiplicative variant, slightly faster
Xorshift family
Very fast generators based on XOR and bit-shift operations. Excellent for large-batch generation with continuous encodings.
Classes (all inherit from XorshiftGenerator):
Xorshift32Generator, Xorshift64Generator, Xorshift128Generator,
XorshiftPlusGenerator, XorshiftStarGenerator,
Xoroshiro128PlusGenerator, Xoroshiro128StarStarGenerator,
Xoshiro256StarStarGenerator, SplitMix64Generator
Presets (CommonXorshiftGenerators):
xorshift32(seed): 32-bit Xorshiftxorshift64(seed): 64-bit Xorshift (better period)xorshift128(seed): 128-bit state (very long period)
Utility: splitmix64_seed(seed); generates independent seeds for
multiple generators from a single master seed.
ShiftedCounter family
Counter-based generators that apply a cryptographic-style scrambling function to a monotonically increasing counter. The scrambling function (Feistel network, ARX cipher, SPN, or custom) ensures that sequential counter values produce seemingly random outputs.
Classes: ShiftedCounterGenerator, FeistelCounterGenerator,
ARXCounterGenerator, SPNCounterGenerator,
CustomMappingCounterGenerator
Presets (CommonCounterGenerators): preset key configurations for each
variant.
When to use each family
Use case |
Recommended family |
|---|---|
General-purpose reproducibility |
PCG ( |
Hardware mapping |
LFSR or LCA (natively produce bits) |
High-throughput float generation |
Xorshift ( |
Parallel generation from one seed |
Xorshift + |
Custom cryptographic properties |
ShiftedCounter ( |
Maximum simplicity and portability |
LCG ( |
Vectorized fast path for batched generation
When you call generate() with a batch size such as
size=(D, N) or size=(D, N, M), PyHDC takes one of two routes. For a
fixed set of i.i.d. element distributions it draws the whole batch in a single
vectorized operation, for everything else it falls back to a per-vector loop.
The two routes do not produce identical output. The fast path draws the whole
batch in one call, so it is reproducible for a fixed seed and shape but not
value-identical to the loop. The loop fallback does match N single-vector
draws (see below).
Qualifying generators. The fast path triggers only when use_generator
is False (no custom HDCGenerator was supplied) and
the encoding’s element distribution is one of these six i.i.d. generators:
BernoulliBipolar: equal-probability draw from{-1, +1}BernoulliBinary: equal-probability draw from{0, 1}UniformBipolar: uniform on[-1, 1]UniformAngles: uniform on[-pi, pi]NormalReal: Gaussian with standard deviationsqrt(1/D)BernoulliSparse: Bernoulli with probability1/sqrt(D)
These are the defaults behind the MAP, BSC, BSDC (dense), HRR/FHRR, and related families, so most batched generation hits the fast path automatically.
Reproducible, but not identical to the loop. The fast path draws the batch
in one (D, *batch) call. Under a fixed seed and shape it reproduces itself,
but it is not value-identical to N successive generate(size=D) calls. A
single block draw and a per-vector loop walk the random stream in different
orders.
Ordered and custom generators use the loop. Two cases fall back to the sequential per-column loop:
use_generatoris True, meaning you passed a customHDCGenerator(LCG, PCG, Xorshift, LFSR, DLFSR, LCA, ShiftedCounter) or setuse_generator=True.the element distribution is not one of the six i.i.d. generators above. This covers
SparseSegmented(theBSDC_SEGgenerator, which is segment-structured rather than i.i.d.) and any custom distribution.
In the fallback, PyHDC generates the N vectors one at a time and stacks
them as columns, so a seeded batch equals N successive single-vector draws.
For these generators the batch and the loop agree exactly, only the i.i.d. fast
path trades that loop-equality for speed.