/* * @author Hong-Phuc Bui * @filename dfhi-random-test * Initial Date 16.12.19 */ import {expect, test} from "@jest/globals"; import * as Rand from "./dfhi-random.js"; const LONGEST_TIMEOUT = 2*5000; // secs test( "uniform distribution with default min = 0", () => { let min = 0, max = 10; let uniformSetupFn = (a,b) => () => Rand.uniform(b); testUniformDistribution(min, max, uniformSetupFn); }); test("uniform distribution in a rang [min,max)", () => { let max = 10, min = 5; let uniformSetupFn = (a, b) => () => Rand.uniform(a, b); testUniformDistribution(min, max, uniformSetupFn); }); function testUniformDistribution(min, max, uniformSetupFn) { let randomCount = 1000, dist = {}; let uniformFn = uniformSetupFn(min, max); for (let i = 0; i < randomCount; ++i) { let r = uniformFn(); expect(r < max).toBeTruthy(); expect(min <= r).toBeTruthy(); if (dist[r]) { dist[r] += 1; } else { dist[r] = 1; } } let exemplars = max - min; // how many distinct int numbers in [min, max); let means = randomCount/exemplars; // Erwartungswert let epsilon = 0.5; for (let [key, value] of Object.entries(dist) ) { let diff = Math.abs((value-means)/value ); expect(diff < epsilon ).toBeTruthy(); } } test ("bad range of uniform", () => { let max = 10, min = max + 1; try{ Rand.uniform(min, max); }catch (error) { expect(error.message).toBe('bad range [11, 10)'); } }); test( "discrete distribution", () => { let p = [0.1, 0.3, 0.6]; testDiscreteDist(p); }, LONGEST_TIMEOUT); test("discrete random 2", () => { let p = [0.1, 0.5]; // same as [0.1, 0.5, 0.5] testDiscreteDist(p); }, LONGEST_TIMEOUT); function testDiscreteDist(p) { let countRandom = {}; let iteration = 10000; for(let count = 0; count < iteration; ++count) { let i = Rand.discrete(p); if (countRandom[i]) { countRandom[i] += 1; } else { countRandom[i] = 1; } } console.log(p); let lastP = 1 - p.reduce( (acc, c) => acc + c ); let epsilon = 0.1; for( let [key,count] of Object.entries(countRandom) ) { let testP = p[key] ? p[key] : lastP; let cP = count / iteration, percentDiff = Math.abs(cP - testP) / testP; let msg = `probability of ${key} is ${count} / ${iteration} = ${cP},` + `near by ${testP} with relative error less than ${percentDiff*100}%` expect(percentDiff < epsilon).toBeTruthy(); } } test("discrete bad distribution", () => { let p = [0.5, 0.5, 0.5]; // same as [0.1, 0.5, 0.5] try { Rand.discrete(p); } catch (error) { expect(error.message).toBe('bad distribution [0.5,0.5,0.5]'); } });