Compute the number of fill-edges using the algorithm in Rose et al. "Algorithmic Aspects of Vertex Elimination on Graphs", SIAM J. Comput., Vol. 5, No. 2, 1976 (RTL76)
| 32 | // Compute the number of fill-edges using the algorithm in |
| 33 | // Rose et al. "Algorithmic Aspects of Vertex Elimination on Graphs", SIAM J. Comput., Vol. 5, No. 2, 1976 (RTL76) |
| 34 | Count compute_fill(graph_access &graph, const std::vector<NodeID> &ordering) { |
| 35 | // Find the order of nodes by sorting node ids based on their order |
| 36 | std::vector<NodeID> node_order(graph.number_of_nodes()); |
| 37 | std::iota(node_order.begin(), node_order.end(), 0); |
| 38 | std::sort(node_order.begin(), node_order.end(), |
| 39 | [&ordering](NodeID a, NodeID b) { return ordering[a] < ordering[b]; }); |
| 40 | |
| 41 | // Build a copy of 'graph' that we can modify, using monotone adjacencies |
| 42 | // The monotone adjacency of x are those neighbors of x which are ordered after x. |
| 43 | std::vector<std::vector<NodeID>> adjacencies; |
| 44 | Count edge_count = 0; |
| 45 | forall_nodes(graph, node) { |
| 46 | adjacencies.push_back({}); |
| 47 | forall_out_edges(graph, edge, node) { |
| 48 | auto target = graph.getEdgeTarget(edge); |
| 49 | if (ordering[target] > ordering[node]) { |
| 50 | adjacencies.back().push_back(target); |
| 51 | edge_count++; |
| 52 | } |
| 53 | } endfor |
| 54 | } endfor |
| 55 | |
| 56 | std::vector<bool> test(graph.number_of_nodes(), false); |
| 57 | for (const auto node: node_order) { // node = i in RTL76 |
| 58 | NodeID k = graph.number_of_nodes(); // smallest ordering in the neighborhood of node that's greater than node |
| 59 | // eliminate duplicates in A(v) and compute m(v), v = node |
| 60 | // A(v): monotone adjacency of v |
| 61 | // m(v): node ordered at position k |
| 62 | for (auto it = adjacencies[node].begin(); it != adjacencies[node].end(); ) { |
| 63 | auto neighbor = *it; // neighbor = w in RTL76 |
| 64 | if (test[ordering[neighbor]]) { |
| 65 | it = adjacencies[node].erase(it); |
| 66 | } else { |
| 67 | test[ordering[neighbor]] = true; |
| 68 | k = std::min(k, ordering[neighbor]); |
| 69 | ++it; |
| 70 | } |
| 71 | } |
| 72 | auto m = node_order[k]; // the node ordered in the k-th place |
| 73 | for (auto it = adjacencies[node].begin(); it != adjacencies[node].end(); ++it) { |
| 74 | auto neighbor = *it; |
| 75 | test[ordering[neighbor]] = false; |
| 76 | if (neighbor != m) { |
| 77 | adjacencies[m].push_back(neighbor); |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | Count fill_edge_count = 0; |
| 82 | for (const auto &adj: adjacencies) { |
| 83 | fill_edge_count += adj.size(); |
| 84 | } |
| 85 | return fill_edge_count - edge_count; |
| 86 | } |