Fix ability tree "appx. toposort"... finally...
This commit is contained in:
parent
77726b003f
commit
b0777ecfcf
3 changed files with 78 additions and 81 deletions
39
js/atree.js
39
js/atree.js
|
@ -170,40 +170,23 @@ const atree_node = new (class extends ComputeNode {
|
|||
}
|
||||
node.parents = parents;
|
||||
}
|
||||
console.log(atree_map);
|
||||
|
||||
let sccs = make_SCC_graph(atree_head, atree_map.values());
|
||||
let atree_topo_sort = [];
|
||||
topological_sort_tree(atree_head, atree_topo_sort, new Map());
|
||||
atree_topo_sort.reverse();
|
||||
for (const scc of sccs) {
|
||||
for (const node of scc.nodes) {
|
||||
delete node.visited;
|
||||
delete node.assigned;
|
||||
delete node.scc;
|
||||
atree_topo_sort.push(node);
|
||||
}
|
||||
}
|
||||
console.log("Approximate topological order ability tree:");
|
||||
console.log(atree_topo_sort);
|
||||
return atree_topo_sort;
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* Create a reverse topological sort of the tree in the result list.
|
||||
* NOTE: our structure isn't a tree... it isn't even acyclic... but do it anyway i guess...
|
||||
*
|
||||
* https://en.wikipedia.org/wiki/Topological_sorting
|
||||
* @param tree: Root of tree to sort
|
||||
* @param res: Result list (reverse topological order)
|
||||
* @param mark_state: Bookkeeping. Call with empty Map()
|
||||
*/
|
||||
function topological_sort_tree(tree, res, mark_state) {
|
||||
const state = mark_state.get(tree);
|
||||
if (state === undefined) {
|
||||
// unmarked.
|
||||
mark_state.set(tree, false); // temporary mark
|
||||
for (const child of tree.children) {
|
||||
topological_sort_tree(child, res, mark_state);
|
||||
}
|
||||
mark_state.set(tree, true); // permanent mark
|
||||
res.push(tree);
|
||||
}
|
||||
// these cases are not needed. Case 1 does nothing, case 2 should never happen.
|
||||
// else if (state === true) { return; } // permanent mark.
|
||||
// else if (state === false) { throw "not a DAG"; } // temporary mark.
|
||||
}
|
||||
|
||||
/**
|
||||
* Display ability tree from topologically sorted list.
|
||||
*
|
||||
|
|
|
@ -223,21 +223,15 @@ function construct_scc_graph(items_to_consider) {
|
|||
let terminal_node = {
|
||||
item: null,
|
||||
children: [],
|
||||
parents: nodes,
|
||||
visited: false,
|
||||
assigned: false,
|
||||
scc: null
|
||||
parents: nodes
|
||||
};
|
||||
let root_node = {
|
||||
item: null,
|
||||
children: nodes,
|
||||
parents: [],
|
||||
visited: false,
|
||||
assigned: false,
|
||||
scc: null
|
||||
};
|
||||
for (const item of items_to_consider) {
|
||||
nodes.push({item: item, children: [terminal_node], parents: [root_node], visited: false, assigned: false, scc: null});
|
||||
nodes.push({item: item, children: [terminal_node], parents: [root_node]});
|
||||
}
|
||||
// Dependency graph construction.
|
||||
for (const node_a of nodes) {
|
||||
|
@ -253,50 +247,6 @@ function construct_scc_graph(items_to_consider) {
|
|||
}
|
||||
}
|
||||
}
|
||||
const res = []
|
||||
/*
|
||||
* SCC graph construction.
|
||||
* https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
|
||||
*/
|
||||
function visit(u, res) {
|
||||
if (u.visited) { return; }
|
||||
u.visited = true;
|
||||
for (const child of u.children) {
|
||||
if (!child.visited) { visit(child, res); }
|
||||
}
|
||||
res.push(u);
|
||||
}
|
||||
visit(root_node, res);
|
||||
res.reverse();
|
||||
const sccs = [];
|
||||
function assign(node, cur_scc) {
|
||||
if (node.assigned) { return; }
|
||||
cur_scc.nodes.push(node);
|
||||
node.scc = cur_scc;
|
||||
node.assigned = true;
|
||||
for (const parent of node.parents) {
|
||||
assign(parent, cur_scc);
|
||||
}
|
||||
}
|
||||
for (const node of res) {
|
||||
if (node.assigned) { continue; }
|
||||
const cur_scc = {
|
||||
nodes: [],
|
||||
children: new Set(),
|
||||
parents: new Set()
|
||||
};
|
||||
assign(node, cur_scc);
|
||||
sccs.push(cur_scc);
|
||||
}
|
||||
for (const scc of sccs) {
|
||||
for (const node of scc.nodes) {
|
||||
for (const child of node.children) {
|
||||
scc.children.add(child.scc);
|
||||
}
|
||||
for (const parent of node.parents) {
|
||||
scc.parents.add(parent.scc);
|
||||
}
|
||||
}
|
||||
}
|
||||
const sccs = make_SCC_graph(root_node, nodes);
|
||||
return [root_node, terminal_node, sccs];
|
||||
}
|
||||
|
|
64
js/utils.js
64
js/utils.js
|
@ -889,3 +889,67 @@ function make_elem(type, classlist = [], args = {}) {
|
|||
}
|
||||
return ret_elem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nodes must have:
|
||||
* node: {
|
||||
* parents: List[node]
|
||||
* children: List[node]
|
||||
* }
|
||||
*
|
||||
* This function will define: "visited, assigned, scc" properties
|
||||
* Assuming a connected graph. (only one root)
|
||||
*/
|
||||
function make_SCC_graph(root_node, nodes) {
|
||||
for (const node of nodes) {
|
||||
node.visited = false;
|
||||
node.assigned = false;
|
||||
node.scc = null;
|
||||
}
|
||||
const res = []
|
||||
/*
|
||||
* SCC graph construction.
|
||||
* https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
|
||||
*/
|
||||
function visit(u, res) {
|
||||
if (u.visited) { return; }
|
||||
u.visited = true;
|
||||
for (const child of u.children) {
|
||||
if (!child.visited) { visit(child, res); }
|
||||
}
|
||||
res.push(u);
|
||||
}
|
||||
visit(root_node, res);
|
||||
res.reverse();
|
||||
const sccs = [];
|
||||
function assign(node, cur_scc) {
|
||||
if (node.assigned) { return; }
|
||||
cur_scc.nodes.push(node);
|
||||
node.scc = cur_scc;
|
||||
node.assigned = true;
|
||||
for (const parent of node.parents) {
|
||||
assign(parent, cur_scc);
|
||||
}
|
||||
}
|
||||
for (const node of res) {
|
||||
if (node.assigned) { continue; }
|
||||
const cur_scc = {
|
||||
nodes: [],
|
||||
children: new Set(),
|
||||
parents: new Set()
|
||||
};
|
||||
assign(node, cur_scc);
|
||||
sccs.push(cur_scc);
|
||||
}
|
||||
for (const scc of sccs) {
|
||||
for (const node of scc.nodes) {
|
||||
for (const child of node.children) {
|
||||
scc.children.add(child.scc);
|
||||
}
|
||||
for (const parent of node.parents) {
|
||||
scc.parents.add(parent.scc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sccs;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue