10 namespace graph_algorithm
13 NetlistGraph::NetlistGraph(Netlist* nl) : m_nl(nl)
17 NetlistGraph::NetlistGraph(
Netlist* nl, igraph_t&& graph, std::unordered_map<u32, Gate*>&& nodes_to_gates) : m_nl(nl), m_graph(
std::move(graph)), m_nodes_to_gates(
std::move(nodes_to_gates))
22 m_graph_initialized =
true;
23 m_graph_ptr = &m_graph;
25 for (
const auto& [node, gate] : m_nodes_to_gates)
29 m_gates_to_nodes[gate] = node;
38 if (m_graph_initialized)
40 igraph_destroy(&m_graph);
48 return ERR(
"no gates given");
51 Netlist* nl = gates.front()->get_netlist();
52 std::unordered_set<Gate*> in_scope;
57 return ERR(
"gate is a nullptr");
59 if (g->get_netlist() != nl)
61 return ERR(
"gates belong to different netlists");
63 if (!in_scope.insert(g).second)
65 return ERR(
"gate '" + g->get_name() +
"' with ID " + std::to_string(g->get_id()) +
" was given more than once");
69 auto graph = std::unique_ptr<NetlistGraph>(
new NetlistGraph(nl));
75 const u32 node = node_counter++;
76 graph->m_gates_to_nodes[g] = node;
77 graph->m_nodes_to_gates[node] = g;
82 std::vector<Net*> nets;
83 std::unordered_set<Net*> visited_nets;
86 for (
auto* n : g->get_fan_out_nets())
88 if ((filter ==
nullptr || filter(n)) && visited_nets.insert(n).second)
94 std::sort(nets.begin(), nets.end(), [](
const Net* lhs,
const Net* rhs) { return lhs->get_id() < rhs->get_id(); });
96 std::vector<std::pair<Gate*, Gate*>> edges;
97 std::unordered_set<Gate*> has_incoming_edge;
98 for (
const auto*
net : nets)
100 for (
const auto* src_ep :
net->get_sources())
102 auto* src_gate = src_ep->get_gate();
103 if (in_scope.find(src_gate) == in_scope.end())
108 for (
const auto* dst_ep :
net->get_destinations())
110 auto* dst_gate = dst_ep->get_gate();
111 if (in_scope.find(dst_gate) == in_scope.end())
116 edges.push_back({src_gate, dst_gate});
117 has_incoming_edge.insert(dst_gate);
125 std::unordered_map<Gate*, u32> shadow_of;
126 for (
auto* g : gates)
128 if (split_gates.find(g) == split_gates.end() || has_incoming_edge.find(g) == has_incoming_edge.end())
133 const u32 shadow_node = node_counter++;
134 graph->m_nodes_to_gates[shadow_node] = g;
135 graph->m_shadow_nodes_to_nodes[shadow_node] = graph->m_gates_to_nodes.at(g);
136 shadow_of[g] = shadow_node;
139 igraph_vector_int_t igraph_edges;
140 auto err = igraph_vector_int_init(&igraph_edges, 2 * edges.size());
141 if (err != IGRAPH_SUCCESS)
143 return ERR(igraph_strerror(err));
149 for (
const auto& [src_gate, dst_gate] : edges)
151 const auto shadow_it = shadow_of.find(dst_gate);
152 VECTOR(igraph_edges)[edge_index++] = graph->m_gates_to_nodes.at(src_gate);
153 VECTOR(igraph_edges)[edge_index++] = (shadow_it != shadow_of.end()) ? shadow_it->second : graph->m_gates_to_nodes.at(dst_gate);
156 graph->m_graph_ptr = &(graph->m_graph);
157 err = igraph_create(graph->m_graph_ptr, &igraph_edges, node_counter, IGRAPH_DIRECTED);
159 igraph_vector_int_destroy(&igraph_edges);
161 if (err != IGRAPH_SUCCESS)
163 return ERR(igraph_strerror(err));
166 graph->m_graph_initialized =
true;
168 return OK(std::move(graph));
175 return ERR(
"netlist is a nullptr");
178 auto graph = std::unique_ptr<NetlistGraph>(
new NetlistGraph(nl));
181 u32 edge_counter = 0;
182 for (
const auto*
net : graph->m_nl->get_nets(filter))
184 std::vector<Gate*> src_gates;
185 for (
const auto* src_ep :
net->get_sources())
187 src_gates.push_back(src_ep->get_gate());
190 std::vector<Gate*> dst_gates;
191 for (
const auto* dst_ep :
net->get_destinations())
193 dst_gates.push_back(dst_ep->get_gate());
196 if (src_gates.empty() && create_dummy_vertices)
200 edge_counter += dst_gates.size();
202 else if (dst_gates.empty() && create_dummy_vertices)
206 edge_counter += src_gates.size();
211 edge_counter += dst_gates.size() * src_gates.size();
216 igraph_vector_int_t edges;
217 auto err = igraph_vector_int_init(&edges, 2 * edge_counter);
218 if (err != IGRAPH_SUCCESS)
220 return ERR(igraph_strerror(err));
224 u32 node_counter = 0;
227 for (
auto* g : graph->m_nl->get_gates())
229 const u32 node = node_counter++;
230 graph->m_gates_to_nodes[g] = node;
231 graph->m_nodes_to_gates[node] = g;
234 for (
const auto*
net : graph->m_nl->get_nets(filter))
236 std::vector<Gate*> src_gates;
237 for (
const auto* src_ep :
net->get_sources())
239 src_gates.push_back(src_ep->get_gate());
242 std::vector<Gate*> dst_gates;
243 for (
const auto* dst_ep :
net->get_destinations())
245 dst_gates.push_back(dst_ep->get_gate());
248 if (src_gates.empty() && create_dummy_vertices)
251 const u32 dummy_node = node_counter++;
252 graph->m_nodes_to_gates[dummy_node] =
nullptr;
253 for (
auto* dst_gate : dst_gates)
255 VECTOR(edges)[edge_index++] = dummy_node;
256 VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(dst_gate);
259 else if (dst_gates.empty() && create_dummy_vertices)
262 const u32 dummy_node = node_counter++;
263 graph->m_nodes_to_gates[dummy_node] =
nullptr;
264 for (
auto* src_gate : src_gates)
266 VECTOR(edges)[edge_index++] = dummy_node;
267 VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(src_gate);
272 for (
auto* dst_gate : dst_gates)
274 for (
auto* src_gate : src_gates)
276 VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(src_gate);
277 VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(dst_gate);
283 graph->m_graph_ptr = &(graph->m_graph);
284 err = igraph_create(graph->m_graph_ptr, &edges, node_counter, IGRAPH_DIRECTED);
286 igraph_vector_int_destroy(&edges);
288 if (err != IGRAPH_SUCCESS)
290 return ERR(igraph_strerror(err));
293 graph->m_graph_initialized =
true;
295 return OK(std::move(graph));
302 return ERR(
"netlist is a nullptr");
305 auto graph = std::unique_ptr<NetlistGraph>(
new NetlistGraph(nl));
307 const auto& graph_gates = gates.empty() ? graph->m_nl->get_gates() : gates;
309 u32 node_counter = 0;
310 for (
auto* g : graph_gates)
312 const u32 node = node_counter++;
313 graph->m_gates_to_nodes[g] = node;
314 graph->m_nodes_to_gates[node] = g;
317 graph->m_graph_ptr = &(graph->m_graph);
318 auto err = igraph_empty(graph->m_graph_ptr, node_counter, IGRAPH_DIRECTED);
319 if (err != IGRAPH_SUCCESS)
321 return ERR(igraph_strerror(err));
324 graph->m_graph_initialized =
true;
326 return OK(std::move(graph));
331 auto graph = std::unique_ptr<NetlistGraph>(
new NetlistGraph(m_nl));
333 if (
const auto res = igraph_copy(&(graph->m_graph), &(this->m_graph)); res != IGRAPH_SUCCESS)
335 return ERR(igraph_strerror(res));
338 graph->m_graph_initialized =
true;
339 graph->m_graph_ptr = &(graph->m_graph);
340 graph->m_gates_to_nodes = this->m_gates_to_nodes;
341 graph->m_nodes_to_gates = this->m_nodes_to_gates;
343 return OK(std::move(graph));
358 std::vector<Gate*> res;
359 for (
const auto& vertex : vertices)
361 if (
const auto it = m_nodes_to_gates.find(vertex); it != m_nodes_to_gates.end())
363 Gate* g = it->second;
368 log_warning(
"graph_algorithm",
"no gate exists for dummy vertex {}, added nullptr", vertex);
373 return ERR(
"no gate for vertex " + std::to_string(vertex) +
" exists in netlist with ID " + std::to_string(m_nl->
get_id()));
381 std::vector<Gate*> res;
382 for (
const auto& vertex : vertices)
384 if (
const auto it = m_nodes_to_gates.find(vertex); it != m_nodes_to_gates.end())
386 Gate* g = it->second;
391 log_warning(
"graph_algorithm",
"no gate exists for dummy vertex {}, added nullptr", vertex);
396 return ERR(
"no gate for vertex " + std::to_string(vertex) +
" exists in netlist with ID " + std::to_string(m_nl->
get_id()));
404 std::vector<Gate*> res;
405 const u32 num_vertices = igraph_vector_int_size(vertices);
406 for (
u32 i = 0; i < num_vertices; i++)
408 u32 vertex = VECTOR(*vertices)[i];
409 if (
const auto it = m_nodes_to_gates.find(vertex); it != m_nodes_to_gates.end())
411 Gate* g = it->second;
416 log_warning(
"graph_algorithm",
"no gate exists for dummy vertex {}, added nullptr", vertex);
421 return ERR(
"no gate for vertex " + std::to_string(vertex) +
" exists in netlist with ID " + std::to_string(m_nl->
get_id()));
430 for (
const auto& vertex : vertices)
432 if (
const auto it = m_nodes_to_gates.find(vertex); it != m_nodes_to_gates.end())
434 Gate* g = it->second;
438 log_warning(
"graph_algorithm",
"no gate exists for dummy vertex {}, skipping vertex", vertex);
445 return ERR(
"no gate for vertex " + std::to_string(vertex) +
" exists in netlist with ID " + std::to_string(m_nl->
get_id()));
454 for (
const auto& vertex : vertices)
456 if (
const auto it = m_nodes_to_gates.find(vertex); it != m_nodes_to_gates.end())
458 Gate* g = it->second;
462 log_warning(
"graph_algorithm",
"no gate exists for dummy vertex {}, skipping vertex", vertex);
469 return ERR(
"no gate for vertex " + std::to_string(vertex) +
" exists in netlist with ID " + std::to_string(m_nl->
get_id()));
478 const u32 num_vertices = igraph_vector_int_size(vertices);
479 for (
u32 i = 0; i < num_vertices; i++)
481 u32 vertex = VECTOR(*vertices)[i];
482 if (
const auto it = m_nodes_to_gates.find(vertex); it != m_nodes_to_gates.end())
484 Gate* g = it->second;
488 log_warning(
"graph_algorithm",
"no gate exists for dummy vertex {}, skipping vertex", vertex);
495 return ERR(
"no gate for vertex " + std::to_string(vertex) +
" exists in netlist with ID " + std::to_string(m_nl->
get_id()));
506 return ERR(res.get_error());
509 return OK(res.get().front());
514 std::vector<u32> res;
515 for (
u32 i = 0; i < gates.size(); i++)
517 auto* g = gates.at(i);
521 return ERR(
"gate at index " + std::to_string(i) +
" is a nullptr");
524 if (
const auto it = m_gates_to_nodes.find(g); it != m_gates_to_nodes.end())
526 res.push_back(it->second);
530 return ERR(
"no node for gate '" + g->get_name() +
"' with ID " + std::to_string(g->get_id()) +
" exists in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
538 std::vector<u32> res;
539 for (
auto* g : gates)
543 return ERR(
"set of gates contains a nullptr");
546 if (
const auto it = m_gates_to_nodes.find(g); it != m_gates_to_nodes.end())
548 res.push_back(it->second);
552 return ERR(
"no node for gate '" + g->get_name() +
"' with ID " + std::to_string(g->get_id()) +
" exists in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
560 igraph_vector_int_t out;
561 if (
auto res = igraph_vector_int_init(&out, gates.size()); res != IGRAPH_SUCCESS)
563 return ERR(igraph_strerror(res));
566 for (
u32 i = 0; i < gates.size(); i++)
568 auto* g = gates.at(i);
572 return ERR(
"gate at index " + std::to_string(i) +
" is a nullptr");
575 if (
const auto it = m_gates_to_nodes.find(g); it != m_gates_to_nodes.end())
577 VECTOR(out)[i] = it->second;
581 return ERR(
"no node for gate '" + g->get_name() +
"' with ID " + std::to_string(g->get_id()) +
" exists in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
584 return OK(std::move(out));
589 igraph_vector_int_t out;
590 if (
auto res = igraph_vector_int_init(&out, gates.size()); res != IGRAPH_SUCCESS)
592 return ERR(igraph_strerror(res));
596 for (
auto gates_it = gates.begin(); gates_it != gates.end(); gates_it++)
602 return ERR(
"gate at index " + std::to_string(i) +
" is a nullptr");
605 if (
const auto nodes_it = m_gates_to_nodes.find(g); nodes_it != m_gates_to_nodes.end())
607 VECTOR(out)[i] = nodes_it->second;
611 return ERR(
"no node for gate '" + g->get_name() +
"' with ID " + std::to_string(g->get_id()) +
" exists in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
616 return OK(std::move(out));
624 return ERR(res.get_error());
627 return OK(res.get().front());
632 return m_shadow_nodes_to_nodes.find(vertex) != m_shadow_nodes_to_nodes.end();
637 const auto node_it = m_gates_to_nodes.find(g);
638 if (node_it == m_gates_to_nodes.end())
640 return ERR(
"no vertex exists for gate '" + g->
get_name() +
"' with ID " + std::to_string(g->
get_id()));
643 std::vector<u32> res = {node_it->second};
644 for (
const auto& [shadow_node, node] : m_shadow_nodes_to_nodes)
646 if (node == node_it->second)
648 res.push_back(shadow_node);
656 u32 num_vertices = igraph_vcount(&m_graph);
664 u32 num_connected_vertices = 0;
666 igraph_vector_int_t degrees;
667 igraph_vector_int_init(°rees, num_vertices);
669 igraph_vs_t v_sel = igraph_vss_all();
670 igraph_degree(&m_graph, °rees, v_sel, IGRAPH_ALL, IGRAPH_LOOPS);
672 for (
u32 i = 0; i < num_vertices; i++)
674 if (VECTOR(degrees)[i] != 0)
676 num_connected_vertices++;
680 igraph_vector_int_destroy(°rees);
681 igraph_vs_destroy(&v_sel);
683 return num_connected_vertices;
689 return igraph_ecount(&m_graph);
694 u32 num_vertices = igraph_vcount(&m_graph);
698 std::vector<u32> vertices(num_vertices);
699 for (
u32 i = 0; i < num_vertices; i++)
707 std::vector<u32> vertices;
709 igraph_vector_int_t degrees;
710 if (
auto res = igraph_vector_int_init(°rees, num_vertices); res != IGRAPH_SUCCESS)
712 return ERR(igraph_strerror(res));
715 igraph_vs_t v_sel = igraph_vss_all();
716 if (
auto res = igraph_degree(&m_graph, °rees, v_sel, IGRAPH_ALL, IGRAPH_LOOPS); res != IGRAPH_SUCCESS)
718 igraph_vs_destroy(&v_sel);
719 igraph_vector_int_destroy(°rees);
720 return ERR(igraph_strerror(res));
723 for (
u32 i = 0; i < num_vertices; i++)
725 if (VECTOR(degrees)[i] != 0)
727 vertices.push_back(i);
731 igraph_vector_int_destroy(°rees);
732 igraph_vs_destroy(&v_sel);
740 const u32 ecount = igraph_ecount(&m_graph);
742 igraph_vector_int_t edges;
743 if (
auto res = igraph_vector_int_init(&edges, 2 * ecount); res != IGRAPH_SUCCESS)
745 return ERR(igraph_strerror(res));
748 if (
auto res = igraph_get_edgelist(&m_graph, &edges,
false); res != IGRAPH_SUCCESS)
750 igraph_vector_int_destroy(&edges);
751 return ERR(igraph_strerror(res));
754 std::vector<std::pair<u32, u32>> e_vec(ecount);
755 for (
u32 i = 0; i < ecount; i++)
757 const u32 src_vertex = (
u32)VECTOR(edges)[2 * i];
758 const u32 dst_vertex = (
u32)VECTOR(edges)[2 * i + 1];
760 e_vec[i] = std::make_pair(src_vertex, dst_vertex);
768 const u32 ecount = igraph_ecount(&m_graph);
770 igraph_vector_int_t edges;
771 if (
auto res = igraph_vector_int_init(&edges, 2 * ecount); res != IGRAPH_SUCCESS)
773 return ERR(igraph_strerror(res));
776 if (
auto res = igraph_get_edgelist(&m_graph, &edges,
false); res != IGRAPH_SUCCESS)
778 igraph_vector_int_destroy(&edges);
779 return ERR(igraph_strerror(res));
782 std::vector<std::pair<Gate*, Gate*>> e_vec(ecount);
783 for (
u32 i = 0; i < ecount; i++)
785 const u32 src_vertex = (
u32)VECTOR(edges)[2 * i];
786 const u32 dst_vertex = (
u32)VECTOR(edges)[2 * i + 1];
787 Gate *src_gate, *dst_gate;
789 if (
const auto it = m_nodes_to_gates.find(src_vertex); it != m_nodes_to_gates.end())
791 src_gate = it->second;
792 if (src_gate ==
nullptr)
795 "ignored edge (" + std::to_string(src_vertex) +
"," + std::to_string(dst_vertex) +
") at dummy source vertex '" + std::to_string(src_vertex) +
"'");
800 if (
const auto it = m_nodes_to_gates.find(dst_vertex); it != m_nodes_to_gates.end())
802 dst_gate = it->second;
803 if (dst_gate ==
nullptr)
806 "ignored edge (" + std::to_string(src_vertex) +
"," + std::to_string(dst_vertex) +
") at dummy destination vertex '" + std::to_string(dst_vertex) +
"'");
811 e_vec[i] = std::make_pair(src_gate, dst_gate);
819 igraph_vector_int_t e_vec;
820 if (
auto res = igraph_vector_int_init(&e_vec, 2 * edges.size()); res != IGRAPH_SUCCESS)
822 return ERR(igraph_strerror(res));
826 for (
const auto& [src_gate, dst_gate] : edges)
828 if (
auto it = m_gates_to_nodes.find(src_gate); it != m_gates_to_nodes.end())
830 VECTOR(e_vec)[edge_index++] = it->second;
834 igraph_vector_int_destroy(&e_vec);
835 return ERR(
"no node for gate '" + src_gate->get_name() +
"' with ID " + std::to_string(src_gate->get_id()) +
" exists in graph for netlist with ID "
836 + std::to_string(m_nl->
get_id()));
839 if (
auto it = m_gates_to_nodes.find(dst_gate); it != m_gates_to_nodes.end())
841 VECTOR(e_vec)[edge_index++] = it->second;
845 igraph_vector_int_destroy(&e_vec);
846 return ERR(
"no node for gate '" + dst_gate->get_name() +
"' with ID " + std::to_string(dst_gate->get_id()) +
" exists in graph for netlist with ID "
847 + std::to_string(m_nl->
get_id()));
851 if (
auto res = igraph_add_edges(&m_graph, &e_vec,
nullptr); res != IGRAPH_SUCCESS)
853 igraph_vector_int_destroy(&e_vec);
854 return ERR(igraph_strerror(res));
862 igraph_vector_int_t e_vec;
863 if (
auto err = igraph_vector_int_init(&e_vec, 2 * edges.size()); err != IGRAPH_SUCCESS)
865 return ERR(igraph_strerror(err));
868 u32 vcount = igraph_vcount(&m_graph);
871 for (
const auto& [src_vertex, dst_vertex] : edges)
873 if (src_vertex >= vcount)
875 igraph_vector_int_destroy(&e_vec);
876 return ERR(
"source vertex '" + std::to_string(src_vertex) +
"' does not exist in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
878 if (dst_vertex >= vcount)
880 igraph_vector_int_destroy(&e_vec);
881 return ERR(
"destination vertex '" + std::to_string(dst_vertex) +
"' does not exist in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
884 VECTOR(e_vec)[edge_index++] = src_vertex;
885 VECTOR(e_vec)[edge_index++] = dst_vertex;
888 if (
auto err = igraph_add_edges(&m_graph, &e_vec,
nullptr); err != IGRAPH_SUCCESS)
890 igraph_vector_int_destroy(&e_vec);
891 return ERR(igraph_strerror(err));
900 for (
const auto& [_, dst_gates] : edges)
902 edge_count += dst_gates.size();
905 igraph_vector_int_t e_vec;
906 if (
auto err = igraph_vector_int_init(&e_vec, 2 * edge_count); err != IGRAPH_SUCCESS)
908 return ERR(igraph_strerror(err));
912 for (
const auto& [src_gate, dst_gates] : edges)
915 if (
auto it = m_gates_to_nodes.find(src_gate); it != m_gates_to_nodes.end())
917 src_vertex = it->second;
921 igraph_vector_int_destroy(&e_vec);
922 return ERR(
"no node for gate '" + src_gate->get_name() +
"' with ID " + std::to_string(src_gate->get_id()) +
" exists in graph for netlist with ID "
923 + std::to_string(m_nl->
get_id()));
926 for (
auto* dst_gate : dst_gates)
928 if (
auto it = m_gates_to_nodes.find(dst_gate); it != m_gates_to_nodes.end())
930 VECTOR(e_vec)[edge_index++] = src_vertex;
931 VECTOR(e_vec)[edge_index++] = it->second;
935 igraph_vector_int_destroy(&e_vec);
936 return ERR(
"no node for gate '" + dst_gate->get_name() +
"' with ID " + std::to_string(dst_gate->get_id()) +
" exists in graph for netlist with ID "
937 + std::to_string(m_nl->
get_id()));
942 if (
auto err = igraph_add_edges(&m_graph, &e_vec,
nullptr); err != IGRAPH_SUCCESS)
944 igraph_vector_int_destroy(&e_vec);
945 return ERR(igraph_strerror(err));
953 igraph_vector_int_t e_vec;
954 if (
auto err = igraph_vector_int_init(&e_vec, 2 * edges.size()); err != IGRAPH_SUCCESS)
956 return ERR(igraph_strerror(err));
959 u32 vcount = igraph_vcount(&m_graph);
962 for (
const auto& [src_gate, dst_gate] : edges)
964 if (
auto it = m_gates_to_nodes.find(src_gate); it != m_gates_to_nodes.end())
966 VECTOR(e_vec)[edge_index++] = it->second;
970 igraph_vector_int_destroy(&e_vec);
971 return ERR(
"no node for gate '" + src_gate->get_name() +
"' with ID " + std::to_string(src_gate->get_id()) +
" exists in graph for netlist with ID "
972 + std::to_string(m_nl->
get_id()));
975 if (
auto it = m_gates_to_nodes.find(dst_gate); it != m_gates_to_nodes.end())
977 VECTOR(e_vec)[edge_index++] = it->second;
981 igraph_vector_int_destroy(&e_vec);
982 return ERR(
"no node for gate '" + dst_gate->get_name() +
"' with ID " + std::to_string(dst_gate->get_id()) +
" exists in graph for netlist with ID "
983 + std::to_string(m_nl->
get_id()));
988 if (
auto res = igraph_es_pairs(&e_sel, &e_vec, IGRAPH_DIRECTED); res != IGRAPH_SUCCESS)
990 igraph_vector_int_destroy(&e_vec);
991 return ERR(igraph_strerror(res));
994 if (
auto res = igraph_delete_edges(&m_graph, e_sel); res != IGRAPH_SUCCESS)
996 igraph_es_destroy(&e_sel);
997 igraph_vector_int_destroy(&e_vec);
998 return ERR(igraph_strerror(res));
1001 igraph_es_destroy(&e_sel);
1002 igraph_vector_int_destroy(&e_vec);
1009 igraph_vector_int_t e_vec;
1010 if (
auto err = igraph_vector_int_init(&e_vec, 2 * edges.size()); err != IGRAPH_SUCCESS)
1012 return ERR(igraph_strerror(err));
1015 u32 vcount = igraph_vcount(&m_graph);
1018 for (
const auto& [src_vertex, dst_vertex] : edges)
1020 if (src_vertex >= vcount)
1022 igraph_vector_int_destroy(&e_vec);
1023 return ERR(
"source vertex '" + std::to_string(src_vertex) +
"' does not exist in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
1025 if (dst_vertex >= vcount)
1027 igraph_vector_int_destroy(&e_vec);
1028 return ERR(
"destination vertex '" + std::to_string(dst_vertex) +
"' does not exist in graph for netlist with ID " + std::to_string(m_nl->
get_id()));
1031 VECTOR(e_vec)[edge_index++] = src_vertex;
1032 VECTOR(e_vec)[edge_index++] = dst_vertex;
1036 if (
auto res = igraph_es_pairs(&e_sel, &e_vec, IGRAPH_DIRECTED); res != IGRAPH_SUCCESS)
1038 igraph_vector_int_destroy(&e_vec);
1039 return ERR(igraph_strerror(res));
1042 if (
auto res = igraph_delete_edges(&m_graph, e_sel); res != IGRAPH_SUCCESS)
1044 igraph_es_destroy(&e_sel);
1045 igraph_vector_int_destroy(&e_vec);
1046 return ERR(igraph_strerror(res));
1049 igraph_es_destroy(&e_sel);
1050 igraph_vector_int_destroy(&e_vec);
1057 igraph_write_graph_edgelist(&m_graph, stdout);
const std::string & get_name() const
A directed graph corresponding to a netlist.
Netlist * get_netlist() const
Get the netlist associated with the netlist graph.
u32 get_num_vertices(bool only_connected=false) const
Get the number of vertices in the netlist graph.
bool is_shadow_vertex(const u32 vertex) const
Check whether the specified vertex is a shadow vertex.
Result< std::vector< Gate * > > get_gates_from_vertices(const std::vector< u32 > &vertices) const
Get the gates corresponding to the specified vertices.
static Result< std::unique_ptr< NetlistGraph > > from_netlist(Netlist *nl, bool create_dummy_vertices=false, const std::function< bool(const Net *)> &filter=nullptr)
Create a directed graph from a netlist.
Result< Gate * > get_gate_from_vertex(const u32 vertex) const
Get the gate corresponding to the specified vertex.
Result< std::unique_ptr< NetlistGraph > > copy() const
Create a deep copy of the netlist graph.
Result< std::set< Gate * > > get_gates_set_from_vertices(const std::vector< u32 > &vertices) const
Get the gates corresponding to the specified vertices.
~NetlistGraph()
Default destructor for NetlistGraph.
Result< std::set< Gate * > > get_gates_set_from_vertices_igraph(const igraph_vector_int_t *vertices) const
Get the gates corresponding to the specified vertices.
@ ALL
Explore in both directions, i.e., treat the graph as undirected.
@ NONE
No direction, invalid default setting.
@ IN
Explore through the inputs of the current node, i.e., traverse backwards.
@ OUT
Explore through the outputs of the current node, i.e., traverse forwards.
Result< u32 > get_vertex_from_gate(Gate *g) const
Get the vertex corresponding to the specified gate.
Result< igraph_vector_int_t > get_vertices_from_gates_igraph(const std::vector< Gate * > &gates) const
Get the vertices corresponding to the specified gates.
Result< std::vector< u32 > > get_vertices_from_gates(const std::vector< Gate * > &gates) const
Get the vertices corresponding to the specified gates.
static Result< std::unique_ptr< NetlistGraph > > from_gates(const std::vector< Gate * > &gates, const std::set< Gate * > &split_gates={}, const std::function< bool(const Net *)> &filter=nullptr)
Create a directed graph from a subset of the gates of a netlist.
Result< std::monostate > add_edges(const std::vector< std::pair< Gate *, Gate * >> &edges)
Add edges between the specified pairs of source and destination gates to the netlist graph.
void print() const
Print the edge list of the graph to stdout.
Result< std::vector< Gate * > > get_gates_from_vertices_igraph(const igraph_vector_int_t *vertices) const
Get the gates corresponding to the specified vertices.
Result< std::vector< std::pair< u32, u32 > > > get_edges() const
Get the edges between vertices in the netlist graph.
u32 get_num_edges() const
Get the number of edges in the netlist graph.
Result< std::vector< std::pair< Gate *, Gate * > > > get_edges_in_netlist() const
Get the edges between gates in the netlist corresponding to the netlist graph.
Result< std::monostate > delete_edges(const std::vector< std::pair< Gate *, Gate * >> &edges)
Delete edges between the specified pairs of source and destination gates from the netlist graph.
Result< std::vector< u32 > > get_vertices(bool only_connected=false) const
Get the vertices in the netlist graph.
static Result< std::unique_ptr< NetlistGraph > > from_netlist_no_edges(Netlist *nl, const std::vector< Gate * > &gates={})
Create an empty directed graph from a netlist.
Result< std::vector< u32 > > get_all_vertices_from_gate(Gate *g) const
Get all vertices corresponding to the specified gate, i.e., its primary vertex and,...
igraph_t * get_graph() const
Get the graph object of the netlist graph.
#define log_warning(channel,...)
This file contains the class that holds a netlist graph.