ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/feedthejoe / src/core/rank/random.js

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/feedthejoe / src/core/rank/random.js
DateNot specified in source
RepositoryJanady13/feedthejoe
Revision0e608a2b515a959bf35d2783428766624400ca3c
Branchmain
Path or archive membersrc/core/rank/random.js
Original SHA-256868e00489bbe252597640b28e472c4d23b31c17d888f53d09b2528018059de4f
Git blob SHAd5d3c444b280d4a3ec20c4079a70698ada5a3220
Reading-copy SHA-256868e00489bbe252597640b28e472c4d23b31c17d888f53d09b2528018059de4f

Original source ↗

Recovered source transcript

/** * Seeded pseudo-randomness. * * The recommender is stochastic by design — Thompson sampling needs draws from * a Beta posterior. Stochastic is not the same as untestable: every draw in * this system comes from an explicit, injected generator, so a test can pin the * seed and assert an exact ordering. * * Nothing here touches Math.random(). That is deliberate and load-bearing. */ /** * mulberry32 — a 32-bit PRNG with a full 2^32 period and good statistical * properties for our purposes (we need plausible jitter, not cryptography). * * @param {number} seed Any integer. * @returns {() => number} Generator yielding floats in [0, 1). */ export function mulberry32(seed) { let a = seed >>> 0; return function next() { a = (a + 0x6d2b79f5) >>> 0; let t = a; t = Math.imul(t ^ (t >>> 15), 1 | t); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } /** * Derive a stable 32-bit seed from a string, so an item id maps to the same * jitter on every render. FNV-1a. * * @param {string} str * @returns {number} */ export function seedFrom(str) { let h = 2166136261 >>> 0; for (let i = 0; i < str.length; i += 1) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619) >>> 0; } return h >>> 0; } /** * Standard normal deviate via the Box–Muller transform. * * @param {() => number} rng * @returns {number} */ export function gaussian(rng) { // u must be non-zero for log(); the half-open range of rng() makes 0 possible. let u = 0; while (u === 0) u = rng(); const v = rng(); return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v); } /** * Gamma(shape, 1) draw via Marsaglia & Tsang (2000), "A Simple Method for * Generating Gamma Variables", ACM TOMS 26(3). * * The method is defined for shape >= 1; for shape < 1 we use the standard * boost identity G(a) = G(a+1) * U^(1/a). * * @param {() => number} rng * @param {number} shape Must be > 0. * @returns {number} */ export function gammaSample(rng, shape) { if (!(shape > 0)) throw new RangeError(`gammaSample: shape must be > 0, got ${shape}`); if (shape < 1) { const u = Math.max(rng(), Number.MIN_VALUE); return gammaSample(rng, shape + 1) * Math.pow(u, 1 / shape); } const d = shape - 1 / 3; const c = 1 / Math.sqrt(9 * d); // Rejection loop. Expected iterations is < 1.01 for all shape >= 1, so this // terminates promptly; there is no unbounded-loop risk in practice. for (;;) { let x; let v; do { x = gaussian(rng); v = 1 + c * x; } while (v <= 0); v = v * v * v; const u = rng(); const x2 = x * x; // Squeeze: cheap acceptance test that avoids the logarithms most of the time. if (u < 1 - 0.0331 * x2 * x2) return d * v; if (Math.log(u) < 0.5 * x2 + d * (1 - v + Math.log(v))) return d * v; } } /** * Beta(alpha, beta) draw, built from two Gamma draws: * X ~ G(a,1), Y ~ G(b,1) => X / (X + Y) ~ Beta(a, b) * * This is the sampling primitive behind Thompson sampling: each topic carries a * Beta posterior over "will this visitor engage", and we rank by a draw from it * rather than by its mean. Sampling is what produces exploration — a topic with * little evidence has a wide posterior and will sometimes draw high, which is * exactly the cold-start promotion behaviour we want. * * @param {() => number} rng * @param {number} alpha Successes + prior. Must be > 0. * @param {number} beta Failures + prior. Must be > 0. * @returns {number} A value in [0, 1]. */ export function betaSample(rng, alpha, beta) { const x = gammaSample(rng, alpha); const y = gammaSample(rng, beta); const sum = x + y; // Both gammas underflowing to 0 is astronomically unlikely but not impossible; // fall back to the posterior mean rather than emitting NaN. if (sum === 0) return alpha / (alpha + beta); return x / sum; }

Mathematical records from this source

Search equations, builds, manuscript text, and recovered sources.