samples.js (1890B)
1 // Imports 2 3 import stdlib_normal from '@stdlib/random/base/normal/lib/main.js'; 4 import stdlib_lognormal from '@stdlib/random/base/lognormal/lib/main.js'; 5 6 // Functions 7 const DEFAULT_N = 10**6 8 function generator(f) { 9 let g = (a, b, n = DEFAULT_N) => { 10 let result = new Array(n) 11 for (let i = 0; i < n; i++) { 12 result[i] = f(a, b, n) 13 } 14 return result 15 } 16 return g 17 } 18 const sum = xs => xs.reduce((acc, x) => acc + x, 0) 19 20 const normal = generator(stdlib_normal) 21 const lognormal = generator(stdlib_lognormal) 22 const to = (low, high, n = DEFAULT_N) => { 23 let normal95confidencePoint = 1.6448536269514722 24 let logLow = Math.log(low) 25 let logHigh = Math.log(high) 26 let meanlog = (logLow + logHigh) / 2 27 let sdlog = (logHigh - logLow) / (2.0 * normal95confidencePoint) 28 return lognormal(meanlog, sdlog, n) 29 } 30 31 const mixture = (dists_array, weights_array, n = DEFAULT_N) => { 32 let normalized_weights = weights_array.map(w => w / sum(weights_array)) 33 let cummulative_sums = Array(normalized_weights.length) 34 normalized_weights.reduce((acc, x, i) => { 35 cummulative_sums[i] = acc + x 36 return cummulative_sums[i] 37 }, 0) 38 const helper_probs = [...new Array(n)].map(_ => Math.random()) 39 const results = helper_probs.map(p => { 40 let match_index = cummulative_sums.findIndex(x => x > p) 41 if(match_index == -1){ 42 console.log("Error: This should never happen.") 43 } 44 let target_loc = match_index // == -1 ? 0 : match_index 45 let target_samples = dists_array[target_loc] 46 return target_samples[Math.floor(Math.random() * target_samples.length)]; 47 }) 48 return(results) 49 50 } 51 52 // Example 53 let p_a = 0.8 54 let p_b = 0.5 55 let p_c = p_a * p_b 56 57 let dists = [ 58 [0], [1], to(1, 3), 59 to(2, 10) 60 ] 61 let weights = [ 62 (1 - p_c), 63 p_c / 2, 64 p_c / 4, 65 p_c / 4 66 ] 67 let result = mixture(dists, weights) 68 let mean_result = sum(result)/result.length 69 console.log(mean_result)