Created
April 9, 2021 02:07
-
-
Save tvquizphd/8f270043489afb04f08c7e617295b977 to your computer and use it in GitHub Desktop.
Print a "tree" diagram for nodes where each node has a poisson distributed number of children.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let evaluate_poisson_probability = (mean, x, x_fact) => { | |
return (mean ** x) / (Math.exp(mean) * x_fact); | |
} | |
let make_poisson_array = (mean) => { | |
if (mean < 1) { | |
console.error(`Poisson with mean ${mean} less than 1 is not supported.`); | |
} | |
const factorial = [ | |
1, 1, 2, 6, 24, 120, 720, 5040, | |
40320, 362880, 3628800, 39916800, | |
479001600, 6227020800, 87178291200, | |
1307674368000, 20922789888000 | |
]; | |
const poisson_array = factorial.reduce((array, x_fact, x) => { | |
const x_prob = evaluate_poisson_probability(mean, x, x_fact); | |
const latest = array[array.length -1] || 0; | |
return array.concat([x_prob + latest]); | |
}, []); | |
const max_supported = poisson_array.length - 1; | |
if (poisson_array[max_supported] < 999 / 1000) { | |
console.error(`Poisson with mean ${mean} has > 1/1000 chance of exceeding ${max_supported}.`); | |
return []; | |
} | |
return poisson_array; | |
} | |
let sample_poisson_array = (poisson_array) => { | |
const sample_prob = Math.random(); | |
return poisson_array.reduce((result, prob) => { | |
if (sample_prob <= prob) { | |
return result; | |
} | |
return result + 1 | |
}, 0); | |
} | |
let name_level = (depth, children) => { | |
const MAX_NAME_DEPTH = 4; | |
if (depth >= MAX_NAME_DEPTH && children.length == 0) { | |
return "leaf"; | |
} | |
return "+"; | |
} | |
let make_level = (depth=0) => { | |
let children = [] | |
const MAX_DEPTH = 8; | |
const MIN_BRANCH_LEVEL = 6; | |
const level = MAX_DEPTH - depth; | |
const branch_power = level - MIN_BRANCH_LEVEL; | |
const mean_children = 2 ** Math.max(0, branch_power); | |
const poisson = make_poisson_array(mean_children); | |
if (level >= 0 && poisson.length > 4) { | |
const num_children = sample_poisson_array(poisson); | |
children = [...Array(num_children).keys()].map(_ => { | |
return make_level(depth + 1); | |
}); | |
} | |
return new TreeNode(name_level(depth, children), children); | |
} | |
class TreeNode { | |
constructor(name, children) { | |
this.name = name; | |
this.children = children; | |
} | |
toString() { | |
return this.print("", "", ""); | |
} | |
print(buffer, prefix, childrenPrefix) { | |
buffer += prefix; | |
buffer += this.name; | |
buffer += "\n"; | |
const last_i = this.children.length - 1; | |
this.children.forEach((next, i) => { | |
if (i < last_i) { | |
buffer = next.print(buffer, childrenPrefix + "├── ", childrenPrefix + "│ "); | |
} else { | |
buffer = next.print(buffer, childrenPrefix + "└── ", childrenPrefix + " "); | |
} | |
}); | |
return buffer; | |
} | |
} | |
make_level().toString() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment