Skip to content

Instantly share code, notes, and snippets.

@tvquizphd
Created April 9, 2021 02:07
Show Gist options
  • Save tvquizphd/8f270043489afb04f08c7e617295b977 to your computer and use it in GitHub Desktop.
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.
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