| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Harmonic.Traversal.Probabilistic
Description
This module implements probabilistic selection for the generative engine. The key concept is the "entropy" knob: higher gamma shape parameter pushes selection probability deeper into the sorted candidate list, favoring more "unusual" but still valid harmonic choices.
Academic Lineage
Data Science In The Creative Process (South, 2018): the probabilistic
traversal strategy (T component of Wiggins' Creative Systems Framework).
The original implementation used R's rgamma via inline-r; this module
replaces it with a pure Haskell gamma distribution from mwc-random.
Synopsis
- gammaIndex :: Double -> Int -> IO Int
- gammaIndexScaled :: Double -> Int -> IO Int
- gammaIndexScaledWith :: GenIO -> Double -> Int -> IO Int
- gammaSelect :: Double -> [(a, Double)] -> IO (Maybe a)
- gammaSelectFromPool :: Double -> [(a, Double)] -> IO (Maybe a)
- gammaSequence :: Double -> Double -> Int -> IO [Int]
- weightedSelect :: [(a, Double)] -> IO (Maybe a)
- pickWeighted :: [(a, Double)] -> Double -> a
- withRandomGen :: Int -> (StdGen -> a) -> a
Gamma Sampling
gammaIndex :: Double -> Int -> IO Int Source #
Draw an index from a gamma distribution.
The shape parameter controls "unusualness": shape ≈ 1.0: High probability of index 0 or 1 (common paths) shape > 2.0: Distribution peak moves away from 0 (unusual paths) shape > 4.0: Very likely to pick 3rd, 4th, or deeper indices
The index is clamped to [0, maxIndex] to ensure valid selection. Alpha is floored at 0.01 to prevent crash when entropy=0.
Implementation uses Statistics.Distribution.Gamma for the distribution and mwc-random for high-quality random number generation.
Draw an index scaled for entropy in [0, 1] range.
Maps entropy to gamma shape parameter (shape = 1 + entropy * 9): entropy = 0.0 -> shape = 1.0 (strongly peaked at index 0) entropy = 0.5 -> shape = 5.5 (moderate spread) entropy = 1.0 -> shape = 10.0 (spread toward higher indices)
The index is clamped to [0, poolSize-1]. This is the primary selection function for the redesigned algorithm.
Arguments
| :: GenIO | Shared random generator |
| -> Double | Entropy in [0, 1] range |
| -> Int | Pool size (e.g., 30) |
| -> IO Int |
Like gammaIndexScaled but uses an existing random generator instead of
creating a new one. Avoids per-call overhead of reading /dev/urandom.
gammaSelect :: Double -> [(a, Double)] -> IO (Maybe a) Source #
Select an element from a weighted list using gamma sampling.
The list is first sorted by weight (highest first), then gamma sampling determines which index to pick. Higher shape = deeper index = more unusual.
If the list is empty, returns Nothing.
gammaSelectFromPool :: Double -> [(a, Double)] -> IO (Maybe a) Source #
Select an element from a candidate pool using scaled gamma sampling.
The pool is expected to be pre-sorted (highest score first). Entropy controls how "adventurous" the selection is: entropy = 0.0 -> almost always picks top candidate entropy = 1.0 -> frequently picks candidates deep in the list
If the pool is empty, returns Nothing.
Arguments
| :: Double | Gamma shape parameter |
| -> Double | Entropy multiplier (scales shape) |
| -> Int | Number of indices to generate |
| -> IO [Int] |
Generate a sequence of gamma-distributed indices.
Matches legacy gammaGen behavior: generate n indices for n transitions. Each index can be used to select from a sorted candidate list.
Weighted Selection
weightedSelect :: [(a, Double)] -> IO (Maybe a) Source #
Select from a weighted list using standard roulette wheel selection.
Each element's selection probability is proportional to its weight. This is used when gamma "unusualness" is not desired.
pickWeighted :: [(a, Double)] -> Double -> a Source #
Pure version of weighted selection given a random value in [0, total]. Useful for deterministic testing.
Random Utilities
withRandomGen :: Int -> (StdGen -> a) -> a Source #
Execute an action with a fresh random generator. Provides a seeded StdGen for reproducible randomness.