6#ifndef NURI_CORE_GRAPH_SUBGRAPH_H_
7#define NURI_CORE_GRAPH_SUBGRAPH_H_
17#include <boost/iterator/iterator_facade.hpp>
30 template <
class SGT,
bool is_const>
31 class SubNodeWrapper {
33 using DT =
typename SGT::node_data_type;
35 using parent_type = const_if_t<is_const, SGT>;
36 using value_type = const_if_t<is_const, DT>;
38 using adjacency_iterator =
39 std::conditional_t<is_const,
typename SGT::const_adjacency_iterator,
40 typename SGT::adjacency_iterator>;
42 template <
bool other_const>
43 using Other = SubNodeWrapper<SGT, other_const>;
45 static_assert(!GraphTraits<SGT>::is_const || is_const,
46 "Cannot create non-const SubNodeWrapper from const "
49 constexpr SubNodeWrapper(
int idx, parent_type &subgraph) noexcept
50 : idx_(idx), subgraph_(&subgraph) { }
52 template <
bool other_const,
53 std::enable_if_t<is_const && !other_const, int> = 0>
54 constexpr SubNodeWrapper(
const Other<other_const> &other) noexcept
55 : idx_(other.idx_), subgraph_(other.subgraph_) { }
57 constexpr int id() const noexcept {
return idx_; }
59 constexpr value_type &data() const noexcept {
60 return subgraph_->node_data(idx_);
63 constexpr int degree() const noexcept {
return subgraph_->degree(idx_); }
65 adjacency_iterator begin() const noexcept {
66 return subgraph_->adj_begin(idx_);
69 adjacency_iterator end() const noexcept {
return subgraph_->adj_end(idx_); }
72 find_adjacent(SubNodeWrapper<SGT, true> node)
const noexcept {
73 return subgraph_->find_adjacent(*
this, node);
76 constexpr Other<true> as_const() const noexcept {
return *
this; }
78 NodeWrapper<typename SGT::graph_type, is_const> as_parent() const noexcept {
79 return subgraph_->parent_node(idx_);
83 template <
class,
bool>
84 friend class SubNodeWrapper;
87 parent_type *subgraph_;
90 template <
class SGT,
bool is_const>
92 :
public DataIteratorBase<SubNodeIterator<SGT, is_const>, SGT,
93 SubNodeWrapper<SGT, is_const>, is_const> {
94 using Base =
typename SubNodeIterator::Parent;
97 using typename Base::difference_type;
98 using typename Base::iterator_category;
99 using typename Base::pointer;
100 using typename Base::reference;
101 using typename Base::value_type;
103 static_assert(!GraphTraits<SGT>::is_const || is_const,
104 "Cannot create non-const SubNodeIterator from const "
114 class SGU,
bool other_const,
116 !std::is_same_v<SGT, SGU> || (is_const && !other_const),
int> = 0>
117 constexpr SubNodeIterator(
118 const SubNodeIterator<SGU, other_const> &other) noexcept
120 static_assert(std::is_same_v<SGT, SGU>,
121 "Cannot copy-construct SubNodeIterator from different "
126 class SGU,
bool other_const,
128 !std::is_same_v<SGT, SGU> || (is_const && !other_const),
int> = 0>
129 constexpr SubNodeIterator &
130 operator=(
const SubNodeIterator<SGU, other_const> &other)
noexcept {
131 static_assert(std::is_same_v<SGT, SGU>,
132 "Cannot copy-assign SubNodeIterator from different "
135 Base::operator=(other);
142 friend class boost::iterator_core_access;
144 template <
class,
bool>
145 friend class SubNodeIterator;
147 constexpr reference dereference() const noexcept {
148 return this->graph().node(this->index());
151 template <
class SGU,
bool other_const,
152 std::enable_if_t<std::is_same_v<
typename SGT::graph_type,
153 typename SGU::graph_type>,
156 equal(
const SubNodeIterator<SGU, other_const> &other)
const noexcept {
157 return this->index() == other.index();
160 template <
class SGU,
bool other_const,
161 std::enable_if_t<std::is_same_v<
typename SGT::graph_type,
162 typename SGU::graph_type>,
164 constexpr difference_type
165 distance_to(
const SubNodeIterator<SGU, other_const> &other)
const noexcept {
166 return other.index() - this->index();
170 template <
class SGT,
bool is_const>
171 class SubAdjWrapper {
173 using edge_value_type = const_if_t<is_const, typename SGT::edge_data_type>;
174 using parent_type = const_if_t<is_const, SGT>;
176 template <
bool other_const>
177 using Other = SubAdjWrapper<SGT, other_const>;
179 constexpr SubAdjWrapper(parent_type &graph,
int src,
int dst,
181 : src_(src), dst_(dst), eid_(eid), graph_(&graph) { }
183 template <
bool other_const,
184 std::enable_if_t<is_const && !other_const, int> = 0>
185 constexpr SubAdjWrapper(
const Other<other_const> &other) noexcept
186 : src_(other.src_), dst_(other.dst_), eid_(other.eid_),
187 graph_(other.graph_) { }
189 constexpr auto src() const noexcept {
return graph_->node(src_); }
190 constexpr auto dst() const noexcept {
return graph_->node(dst_); }
192 constexpr int eid() const noexcept {
return eid_; }
193 constexpr edge_value_type &edge_data() const noexcept {
194 return graph_->edge_data(eid_);
197 constexpr Other<true> as_const() const noexcept {
return *
this; }
199 constexpr auto as_parent() const noexcept {
200 return internal::AdjWrapper<typename SGT::graph_type, is_const>(
201 graph_->parent(), graph_->parent_node(src_).id(),
202 graph_->parent_node(dst_).id(), graph_->parent_edge(eid_).id());
206 template <
class,
bool>
207 friend class SubAdjWrapper;
209 template <
class,
bool>
210 friend class SubAdjIterator;
220 template <
class SGT,
bool is_const>
222 :
public ProxyIterator<SubAdjIterator<SGT, is_const>,
223 SubAdjWrapper<SGT, is_const>,
224 std::bidirectional_iterator_tag, int> {
225 using parent_nonconst_adjacency_iterator =
226 typename SGT::graph_type::adjacency_iterator;
227 using parent_const_adjacency_iterator =
228 typename SGT::graph_type::const_adjacency_iterator;
230 using parent_adjacency_iterator =
231 std::conditional_t<is_const, parent_const_adjacency_iterator,
232 parent_nonconst_adjacency_iterator>;
235 std::iterator_traits<typename SubAdjIterator::iterator_facade_>;
238 using parent_type = const_if_t<is_const, SGT>;
240 using iterator_category =
typename Traits::iterator_category;
241 using value_type =
typename Traits::value_type;
242 using difference_type =
typename Traits::difference_type;
243 using pointer =
typename Traits::pointer;
244 using reference =
typename Traits::reference;
246 static_assert(!GraphTraits<SGT>::is_const || is_const,
247 "Cannot create non-const SubAdjIterator from const "
250 constexpr SubAdjIterator() =
default;
252 constexpr SubAdjIterator(parent_type &subgraph,
int src,
253 int parent_idx) noexcept
254 : subgraph_(&subgraph), src_(src), parent_idx_(parent_idx) {
263 class SGU,
bool other_const,
265 !std::is_same_v<SGT, SGU> || (is_const && !other_const),
int> = 0>
266 constexpr SubAdjIterator(
267 const SubAdjIterator<SGU, other_const> &other) noexcept
268 : subgraph_(other.subgraph_), src_(other.src_), dst_(other.dst_),
269 eid_(other.eid_), parent_idx_(other.parent_idx_) {
270 static_assert(std::is_same_v<SGT, SGU>,
271 "Cannot copy-construct SubAdjIterator from different "
276 class SGU,
bool other_const,
278 !std::is_same_v<SGT, SGU> || (is_const && !other_const),
int> = 0>
279 constexpr SubAdjIterator &
280 operator=(
const SubAdjIterator<SGU, other_const> &other)
noexcept {
281 static_assert(std::is_same_v<SGT, SGU>,
282 "Cannot copy-assign SubAdjIterator from different "
285 subgraph_ = other.subgraph_;
289 parent_idx_ = other.parent_idx_;
293 bool begin() const noexcept {
return parent_idx_ <= 0; }
295 bool end() const noexcept {
296 return parent_idx_ >= subgraph_->parent_node(src_).degree();
302 template <
class,
bool>
303 friend class SubAdjIterator;
305 friend class boost::iterator_core_access;
307 constexpr SubAdjIterator(parent_type &subgraph,
int src,
int dst,
int eid,
308 int parent_idx) noexcept
309 : subgraph_(&subgraph), src_(src), dst_(dst), eid_(eid),
310 parent_idx_(parent_idx) { }
312 auto parent_iter()
const {
313 return subgraph_->parent_node(src_).begin() + parent_idx_;
319 for (
auto ait = parent_iter(); !ait.end(); ++ait, ++parent_idx_) {
320 auto nit = subgraph_->find_node(ait->dst());
321 auto eit = subgraph_->find_edge(ait->eid());
322 if (nit != subgraph_->node_end() && eit != subgraph_->edge_end()) {
330 reference dereference() const noexcept {
331 return { *subgraph_, src_, dst_, eid_ };
334 template <
class SGU,
bool other_const>
335 bool equal(
const SubAdjIterator<SGU, other_const> &other)
const noexcept {
336 return parent_idx_ == other.parent_idx_;
346 for (
auto ait = parent_iter(); parent_idx_ >= 0; --ait, --parent_idx_) {
347 auto nit = subgraph_->find_node(ait->dst());
348 auto eit = subgraph_->find_edge(ait->eid());
349 if (nit != subgraph_->node_end() && eit != subgraph_->edge_end()) {
357 parent_type *subgraph_;
364 template <
class SGT,
bool is_const>
365 class SubEdgeWrapper {
367 using DT =
typename SGT::edge_data_type;
369 using parent_type = const_if_t<is_const, SGT>;
370 using value_type = const_if_t<is_const, DT>;
372 template <
bool other_const>
373 using Other = SubEdgeWrapper<SGT, other_const>;
375 static_assert(!GraphTraits<SGT>::is_const || is_const,
376 "Cannot create non-const SubEdgeWrapper from const "
379 constexpr SubEdgeWrapper(
int src,
int dst,
int eid,
380 parent_type &subgraph) noexcept
381 : src_(src), dst_(dst), eid_(eid), subgraph_(&subgraph) { }
383 template <
bool other_const,
384 std::enable_if_t<is_const && !other_const, int> = 0>
385 constexpr SubEdgeWrapper(
const Other<other_const> &other) noexcept
386 : src_(other.src_), dst_(other.dst_), eid_(other.eid_),
387 subgraph_(other.subgraph_) { }
389 constexpr auto id() const noexcept {
return eid_; }
391 constexpr auto src() const noexcept {
return subgraph_->node(src_); }
392 constexpr auto dst() const noexcept {
return subgraph_->node(dst_); }
394 constexpr value_type &data() const noexcept {
395 return subgraph_->edge_data(eid_);
398 constexpr Other<true> as_const() const noexcept {
return *
this; }
400 EdgeWrapper<typename SGT::graph_type, is_const> as_parent() const noexcept {
401 return subgraph_->parent_edge(eid_);
405 template <
class,
bool>
406 friend class SubEdgeWrapper;
408 template <
class,
bool>
409 friend class SubEdgeIterator;
414 parent_type *subgraph_;
417 template <
class SGT,
bool is_const>
418 class SubEdgeIterator
419 :
public DataIteratorBase<SubEdgeIterator<SGT, is_const>, SGT,
420 SubEdgeWrapper<SGT, is_const>, is_const> {
421 using Base =
typename SubEdgeIterator::Parent;
424 using typename Base::difference_type;
425 using typename Base::iterator_category;
426 using typename Base::pointer;
427 using typename Base::reference;
428 using typename Base::value_type;
430 static_assert(!GraphTraits<SGT>::is_const || is_const,
431 "Cannot create non-const SubEdgeIterator from const "
441 class SGU,
bool other_const,
443 !std::is_same_v<SGT, SGU> || (is_const && !other_const),
int> = 0>
444 constexpr SubEdgeIterator(
445 const SubEdgeIterator<SGU, other_const> &other) noexcept
447 static_assert(std::is_same_v<SGT, SGU>,
448 "Cannot copy-construct SubEdgeIterator from different "
453 class SGU,
bool other_const,
455 !std::is_same_v<SGT, SGU> || (is_const && !other_const),
int> = 0>
456 constexpr SubEdgeIterator &
457 operator=(
const SubEdgeIterator<SGU, other_const> &other)
noexcept {
458 static_assert(std::is_same_v<SGT, SGU>,
459 "Cannot copy-assign SubEdgeIterator from different "
462 Base::operator=(other);
469 friend class boost::iterator_core_access;
471 template <
class,
bool>
472 friend class SubEdgeIterator;
474 template <
class SGU,
bool other_const,
475 std::enable_if_t<std::is_same_v<
typename SGT::graph_type,
476 typename SGU::graph_type>,
479 equal(
const SubEdgeIterator<SGU, other_const> &other)
const noexcept {
480 return this->index() == other.index();
483 template <
class SGU,
bool other_const,
484 std::enable_if_t<std::is_same_v<
typename SGT::graph_type,
485 typename SGU::graph_type>,
487 constexpr difference_type
488 distance_to(
const SubEdgeIterator<SGU, other_const> &other)
const noexcept {
489 return other.index() - this->index();
492 reference dereference() const noexcept {
493 return this->graph().edge(this->index());
498 IndexSet find_nodes(GT &parent,
const IndexSet &
edges) {
499 std::vector<int> nodes;
500 nodes.reserve(
static_cast<size_t>(
edges.size()) * 2);
502 for (
auto i:
edges) {
503 nodes.push_back(parent.edge(i).src().id());
504 nodes.push_back(parent.edge(i).dst().id());
507 return IndexSet(std::move(nodes));
511 IndexSet find_edges(GT &parent,
const IndexSet &nodes) {
512 std::vector<int>
edges;
513 std::stack<int, std::vector<int>> stack;
514 ArrayXb visited = ArrayXb::Zero(
static_cast<int>(nodes.size()));
516 for (
int i = 0; i < nodes.size(); ++i) {
524 int u = nodes[stack.top()];
527 for (
auto nei: parent[u]) {
528 int v = nei.dst().id();
529 int j = nodes.find_index(v);
530 if (j >= nodes.size())
534 edges.push_back(nei.eid());
541 }
while (!stack.empty());
544 return IndexSet(std::move(
edges));
574template <
class NT,
class ET,
bool is_const = false>
583 using iterator = internal::SubNodeIterator<Subgraph, is_const>;
587 using NodeRef = internal::SubNodeWrapper<Subgraph, is_const>;
592 using EdgeRef = internal::SubEdgeWrapper<Subgraph, is_const>;
599 using AdjRef = internal::SubAdjWrapper<Subgraph, is_const>;
602 static_assert(std::is_same_v<typename iterator::reference, NodeRef>);
604 std::is_same_v<typename const_iterator::reference, ConstNodeRef>);
605 static_assert(std::is_same_v<typename edge_iterator::reference, EdgeRef>);
607 std::is_same_v<typename const_edge_iterator::reference, ConstEdgeRef>);
608 static_assert(std::is_same_v<typename adjacency_iterator::reference, AdjRef>);
610 std::is_same_v<typename const_adjacency_iterator::reference, ConstAdjRef>);
612 template <
bool other_const>
640 internal::IndexSet &&
edges) {
641 Subgraph subgraph(graph, std::move(nodes), {});
642 subgraph.add_edges(
edges);
660 internal::IndexSet
edges = internal::find_edges(graph, nodes);
661 Subgraph subgraph(graph, std::move(nodes), std::move(
edges));
676 internal::IndexSet nodes = internal::find_nodes(graph,
edges);
677 Subgraph subgraph(graph, std::move(nodes), std::move(
edges));
687 template <
bool other_const,
688 std::enable_if_t<is_const && !other_const, int> = 0>
690 : parent_(other.parent_), nodes_(other.nodes_), edges_(other.edges_) { }
698 template <
bool other_const,
699 std::enable_if_t<is_const && !other_const, int> = 0>
701 : parent_(other.parent_), nodes_(std::move(other.nodes_)),
702 edges_(std::move(other.edges_)) { }
710 template <
bool other_const,
711 std::enable_if_t<is_const && !other_const, int> = 0>
713 parent_ = other.parent_;
714 nodes_ = other.nodes_;
715 edges_ = other.edges_;
725 template <
bool other_const,
726 std::enable_if_t<is_const && !other_const, int> = 0>
728 parent_ = other.parent_;
729 nodes_ = std::move(other.nodes_);
730 edges_ = std::move(other.edges_);
739 bool empty()
const {
return nodes_.empty(); }
753 int num_nodes()
const {
return static_cast<int>(nodes_.size()); }
760 int num_edges()
const {
return static_cast<int>(edges_.size()); }
773 void update(internal::IndexSet &&nodes, internal::IndexSet &&
edges) {
774 nodes_ = std::move(nodes);
789 nodes_ = std::move(nodes);
790 edges_ = internal::find_edges(*parent_, nodes_);
803 edges_ = std::move(
edges);
804 nodes_ = internal::find_nodes(*parent_, edges_);
871 auto [_, added] = edges_.insert(
id);
873 auto edge = parent_->edge(
id);
874 nodes_.insert(
edge.src().id());
875 nodes_.insert(
edge.dst().id());
886 void add_nodes(
const internal::IndexSet &nodes) { nodes_.union_with(nodes); }
897 edges_.union_with(
edges);
899 auto new_nodes = internal::find_nodes(*parent_,
edges);
900 nodes_.union_with(new_nodes);
912 auto new_edges = internal::find_edges(*parent_, nodes);
913 edges_.union_with(new_edges);
1000 int src = nodes_.find_index(pedge.src().id()),
1001 dst = nodes_.find_index(pedge.dst().id());
1002 return { src, dst, idx, *
this };
1015 int src = nodes_.find_index(pedge.src().id()),
1016 dst = nodes_.find_index(pedge.dst().id());
1017 return { src, dst, idx, *
this };
1027 return parent_->node_data(nodes_[idx]);
1036 const NT &
node_data(
int idx)
const {
return parent_->node_data(nodes_[idx]); }
1045 return parent_->edge_data(edges_[idx]);
1054 const ET &
edge_data(
int idx)
const {
return parent_->edge_data(edges_[idx]); }
1062 std::conditional_t<is_const,
typename parent_type::ConstNodeRef,
1063 typename parent_type::NodeRef>
1065 return parent_->node(nodes_[idx]);
1075 return parent_->node(nodes_[idx]);
1084 std::conditional_t<is_const,
typename parent_type::ConstEdgeRef,
1085 typename parent_type::EdgeRef>
1087 return parent_->edge(edges_[idx]);
1097 return parent_->edge(edges_[idx]);
1129 return begin() + nodes_.find_index(
id);
1199 std::vector<int> erased_edges;
1200 for (
auto nei:
node(idx))
1201 erased_edges.push_back(nei.as_parent().eid());
1202 nodes_.erase(nodes_.begin() + idx);
1203 edges_.difference(internal::IndexSet(std::move(erased_edges)));
1243 std::vector<int> erased_edges;
1244 for (
auto it =
begin; it !=
end; ++it)
1246 erased_edges.push_back(nei.as_parent().eid());
1248 nodes_.erase(
begin - this->
begin() + nodes_.begin(),
1249 end - this->begin() + nodes_.begin());
1250 edges_.difference(internal::IndexSet(std::move(erased_edges)));
1262 end - this->edge_begin() + edges_.begin());
1274 int idx = nodes_.find_index(
id);
1319 template <
class UnaryPred>
1321 std::vector<int> erased_nodes, erased_edges;
1324 if (!pred(nodes_[i]))
1327 erased_nodes.push_back(nodes_[i]);
1328 for (
auto nei:
node(i))
1329 erased_edges.push_back(nei.as_parent().eid());
1332 nodes_.difference(internal::IndexSet(std::move(erased_nodes)));
1333 edges_.difference(internal::IndexSet(std::move(erased_edges)));
1343 template <
class UnaryPred>
1345 edges_.erase_if(std::forward<UnaryPred>(pred));
1359 void remap(
const std::vector<int> &node_map,
1360 const std::vector<int> &edge_map) {
1361 nodes_.remap(node_map);
1362 edges_.remap(edge_map);
1376 void remap_nodes(
const std::vector<int> &node_map) { nodes_.remap(node_map); }
1387 edges_.remap(old_to_new);
1426 const std::vector<int> &
node_ids()
const {
return nodes_.sequence(); }
1433 const std::vector<int> &
edge_ids()
const {
return edges_.sequence(); }
1486 if (sit ==
end() || dit ==
end())
1505 if (sit ==
end() || dit ==
end())
1548 return { *
this, idx, 0 };
1565 friend class Subgraph<NT, ET, true>;
1567 template <
class,
bool>
1568 friend class internal::SubAdjWrapper;
1569 template <
class,
bool>
1570 friend class internal::SubEdgeWrapper;
1573 internal::IndexSet &&
edges) noexcept
1574 : parent_(&graph), nodes_(std::move(nodes)), edges_(std::move(
edges)) { }
1588 const graph_type &parent()
const {
return *parent_; }
1591 return find_edge_helper(*
this, src, dst);
1595 return find_edge_helper(*
this, src, dst);
1599 return find_adj_helper<adjacency_iterator>(*
this, src, dst);
1603 return find_adj_helper<const_adjacency_iterator>(*
this, src, dst);
1606 template <
class SGT>
1607 static auto find_edge_helper(SGT &graph,
int src,
int dst) {
1608 if (graph.parent_node(src).degree() > graph.parent_node(dst).degree())
1609 std::swap(src, dst);
1611 auto ait = graph.find_adjacent(src, dst);
1613 return graph.edge_end();
1615 return graph.edge_begin() + ait->eid();
1618 template <
class AIT,
class SGT>
1619 static AIT find_adj_helper(SGT &graph,
int src,
int dst) {
1620 auto pait = graph.parent_node(src).find_adjacent(graph.parent_node(dst));
1622 return graph.adj_end(src);
1624 auto eit = graph.find_edge(pait->eid());
1625 if (eit == graph.edge_end())
1626 return graph.adj_end(src);
1628 return { graph, src, dst, eit->id(),
1629 pait - graph.parent_node(src).begin() };
1633 internal::IndexSet nodes_;
1634 internal::IndexSet edges_;
1639template <
class NT,
class ET>
1642template <
class NT,
class ET>
1646template <
class NT,
class ET>
1650template <
class NT,
class ET>
1653template <
class NT,
class ET>
1657template <
class NT,
class ET>
1665 struct SubgraphTypeHelper;
1668 struct SubgraphTypeHelper<T &&> { };
1671 struct SubgraphTypeHelper<T &> {
1672 using type =
typename SubgraphTypeHelper<T>::type;
1675 template <
template <
class,
class>
class GT,
class NT,
class ET>
1676 struct SubgraphTypeHelper<GT<NT, ET>> {
1680 template <
template <
class,
class>
class GT,
class NT,
class ET>
1681 struct SubgraphTypeHelper<const GT<NT, ET>> {
1687using SubgraphOf =
typename internal::SubgraphTypeHelper<GT>::type;
1697 return { std::forward<GT>(graph) };
1714 internal::IndexSet &&
edges) {
1751 template <
class NT,
class ET,
bool subg_const>
1752 struct GraphTraits<
Subgraph<NT, ET, subg_const>> {
1753 constexpr static bool is_const = subg_const;
1754 constexpr static bool is_degree_constant_time =
false;
Class for very sparse graphs, especially designed for the molecular graphs.
Definition graph.h:475
internal::NodeWrapper< Graph, true > ConstNodeRef
Definition graph.h:497
internal::EdgeWrapper< Graph, true > ConstEdgeRef
Definition graph.h:502
A subgraph of a graph.
Definition subgraph.h:575
const_adjacency_iterator adj_cbegin(int idx) const
Definition subgraph.h:1547
internal::SubEdgeWrapper< Subgraph, is_const > EdgeRef
Definition subgraph.h:592
const_edge_iterator edge_begin() const
Definition subgraph.h:1415
internal::SubNodeIterator< Subgraph, is_const > iterator
Definition subgraph.h:583
int size() const
Count number of nodes in the subgraph.
Definition subgraph.h:746
ConstNodeRef operator[](int idx) const
Get a node in the subgraph.
Definition subgraph.h:972
void add_node(int id)
Add a node to the subgraph.
Definition subgraph.h:859
Subgraph & operator=(Other< other_const > &&other) noexcept
Converting assignment operator to allow implicit conversion from a non-const subgraph to a const subg...
Definition subgraph.h:727
ConstNodeRef node(int idx) const
Get a node in the subgraph.
Definition subgraph.h:988
void erase_node_of(typename graph_type::ConstNodeRef node)
Erase a node with given id from the subgraph. Corresponding edges will also be removed.
Definition subgraph.h:1287
const_adjacency_iterator adj_cend(int idx) const
Definition subgraph.h:1550
internal::EdgesWrapper< Subgraph, true > ConstEdgesWrapper
Definition subgraph.h:595
int degree(int idx) const
Count in-subgraph neighbors of a node.
Definition subgraph.h:1443
const ET & edge_data(int idx) const
Get data of an edge in the subgraph.
Definition subgraph.h:1054
void erase_edge_of(typename graph_type::ConstEdgeRef edge)
Erase an edge with given id from the subgraph.
Definition subgraph.h:1307
internal::SubEdgeIterator< Subgraph, is_const > edge_iterator
Definition subgraph.h:590
NodeRef operator[](int idx)
Get a node in the subgraph.
Definition subgraph.h:964
void add_edge(int id)
Add an edge to the subgraph. Also adds the incident nodes.
Definition subgraph.h:870
parent_type::ConstNodeRef parent_node(int idx) const
Get a parent node of a node in the subgraph.
Definition subgraph.h:1074
const std::vector< int > & node_ids() const
Get all node ids in the subgraph.
Definition subgraph.h:1426
ET edge_data_type
Definition subgraph.h:581
const_adjacency_iterator find_adjacent(ConstNodeRef src, ConstNodeRef dst) const
Find adjacent node of a node.
Definition subgraph.h:1534
void clear() noexcept
Clear the subgraph.
Definition subgraph.h:824
internal::SubNodeWrapper< Subgraph, true > ConstNodeRef
Definition subgraph.h:588
bool contains_node(int id) const
Check if a node is in the subgraph.
Definition subgraph.h:923
const_edge_iterator edge_end() const
Definition subgraph.h:1416
std::conditional_t< is_const, typename parent_type::ConstNodeRef, typename parent_type::NodeRef > parent_node(int idx)
Get a parent node of a node in the subgraph.
Definition subgraph.h:1064
bool empty() const
Whether the subgraph is empty.
Definition subgraph.h:739
void remap(const std::vector< int > &node_map, const std::vector< int > &edge_map)
Re-map node/edge ids.
Definition subgraph.h:1359
internal::const_if_t< is_const, graph_type > parent_type
Definition subgraph.h:578
const_adjacency_iterator adj_end(int idx) const
Definition subgraph.h:1545
parent_type::ConstEdgeRef parent_edge(int idx) const
Get a parent edge of an edge in the subgraph.
Definition subgraph.h:1096
bool contains_node(typename graph_type::ConstNodeRef node) const
Check if a node is in the subgraph.
Definition subgraph.h:933
internal::SubAdjIterator< Subgraph, true > const_adjacency_iterator
Definition subgraph.h:598
Subgraph(graph_type &&graph)=delete
const_edge_iterator edge_cbegin() const
Definition subgraph.h:1418
internal::EdgesWrapper< Subgraph, is_const > EdgesWrapper
Definition subgraph.h:594
edge_iterator edge_end()
Definition subgraph.h:1413
void erase_nodes_if(UnaryPred pred)
Erase matching nodes from the subgraph. Corresponding edges will also be removed.
Definition subgraph.h:1320
iterator find_node(typename graph_type::ConstNodeRef node)
Find a node with the given id.
Definition subgraph.h:1117
const_iterator const_node_iterator
Definition subgraph.h:586
const_node_iterator node_begin() const
Definition subgraph.h:1402
ConstEdgeRef edge(int idx) const
Get an edge in the subgraph.
Definition subgraph.h:1013
internal::SubEdgeIterator< Subgraph, true > const_edge_iterator
Definition subgraph.h:591
const_node_iterator node_end() const
Definition subgraph.h:1403
const_iterator cend() const
Definition subgraph.h:1397
void update_edges(internal::IndexSet &&edges) noexcept
Change the set of edges in the subgraph.
Definition subgraph.h:802
edge_iterator find_edge(int id)
Find an edge with the given id.
Definition subgraph.h:1151
NodeRef node(int idx)
Definition subgraph.h:980
internal::SubNodeWrapper< Subgraph, is_const > NodeRef
Definition subgraph.h:587
iterator node_iterator
Definition subgraph.h:584
const_node_iterator node_cbegin() const
Definition subgraph.h:1405
const NT & node_data(int idx) const
Get data of a node in the subgraph.
Definition subgraph.h:1036
internal::SubEdgeWrapper< Subgraph, true > ConstEdgeRef
Definition subgraph.h:593
node_iterator node_end()
Definition subgraph.h:1400
const_iterator begin() const
Definition subgraph.h:1393
Graph< NT, ET > graph_type
Definition subgraph.h:577
Subgraph & operator=(const Other< other_const > &other)
Converting assignment operator to allow implicit conversion from a non-const subgraph to a const subg...
Definition subgraph.h:712
edge_iterator edge_begin()
Definition subgraph.h:1412
iterator end()
Definition subgraph.h:1391
void add_edges(const internal::IndexSet &edges)
Add edges to the subgraph. Also adds the incident nodes.
Definition subgraph.h:896
std::conditional_t< is_const, typename parent_type::ConstEdgeRef, typename parent_type::EdgeRef > parent_edge(int idx)
Get a parent edge of an edge in the subgraph.
Definition subgraph.h:1086
int num_nodes() const
Count number of nodes in the subgraph.
Definition subgraph.h:753
const_iterator find_node(int id) const
Find a node with the given id.
Definition subgraph.h:1128
const_adjacency_iterator adj_begin(int idx) const
Definition subgraph.h:1544
NT node_data_type
Definition subgraph.h:580
Subgraph< NT, ET, other_const > Other
Definition subgraph.h:613
iterator find_node(int id)
Find a node with the given id.
Definition subgraph.h:1107
const_edge_iterator edge_cend() const
Definition subgraph.h:1419
void erase_node(ConstNodeRef node)
Erase a node from the subgraph.
Definition subgraph.h:1213
adjacency_iterator find_adjacent(ConstNodeRef src, ConstNodeRef dst)
Find adjacent node of a node.
Definition subgraph.h:1520
const_iterator end() const
Definition subgraph.h:1394
internal::SubAdjIterator< Subgraph, is_const > adjacency_iterator
Definition subgraph.h:597
internal::SubNodeIterator< Subgraph, true > const_iterator
Definition subgraph.h:585
iterator begin()
Definition subgraph.h:1390
edge_iterator find_edge(ConstNodeRef src, ConstNodeRef dst)
Find edge between two nodes.
Definition subgraph.h:1456
void reserve_edges(int num_edges)
Reserve space for a number of edges.
Definition subgraph.h:848
void reserve_nodes(int num_nodes)
Reserve space for a number of nodes.
Definition subgraph.h:841
void erase_edges_if(UnaryPred &&pred)
Erase matching edges from the subgraph.
Definition subgraph.h:1344
Subgraph(parent_type &graph)
Construct an empty subgraph.
Definition subgraph.h:622
internal::const_if_t< is_const, ET > & edge_data(int idx)
Get data of an edge in the subgraph.
Definition subgraph.h:1044
void erase_edges(const_edge_iterator begin, const_edge_iterator end)
Erase range of edges from the subgraph.
Definition subgraph.h:1260
void remap_nodes(const std::vector< int > &node_map)
Re-map node ids.
Definition subgraph.h:1376
node_iterator node_begin()
Definition subgraph.h:1399
adjacency_iterator adj_begin(int idx)
Definition subgraph.h:1539
void erase_edge(int idx)
Erase an edge from the subgraph.
Definition subgraph.h:1222
bool contains_edge(int id) const
Check if an edge is in the subgraph.
Definition subgraph.h:944
void erase_node(int idx)
Erase a node from the subgraph. Corresponding edges will also be removed.
Definition subgraph.h:1198
bool contains_edge(typename graph_type::ConstEdgeRef edge) const
Check if an edge is in the subgraph.
Definition subgraph.h:954
const std::vector< int > & edge_ids() const
Get all edge ids in the subgraph.
Definition subgraph.h:1433
void erase_edge_of(int id)
Erase an edge with given id from the subgraph.
Definition subgraph.h:1298
EdgeRef edge(int idx)
Definition subgraph.h:998
edge_iterator find_edge(typename graph_type::ConstEdgeRef edge)
Find an edge with the given id.
Definition subgraph.h:1163
internal::SubAdjWrapper< Subgraph, true > ConstAdjRef
Definition subgraph.h:600
void update(internal::IndexSet &&nodes, internal::IndexSet &&edges)
Change the set of nodes and edges in the subgraph.
Definition subgraph.h:773
const_iterator cbegin() const
Definition subgraph.h:1396
EdgesWrapper edges()
Definition subgraph.h:1408
const_node_iterator node_cend() const
Definition subgraph.h:1406
void erase_edge(ConstEdgeRef edge)
Erase an edge from the subgraph.
Definition subgraph.h:1231
ConstEdgesWrapper edges() const
Definition subgraph.h:1410
void erase_node_of(int id)
Erase a node with given id from the subgraph. Corresponding edges will also be removed.
Definition subgraph.h:1273
void update_nodes(internal::IndexSet &&nodes) noexcept
Change the set of nodes in the subgraph.
Definition subgraph.h:788
void erase_nodes(const_iterator begin, const_iterator end)
Erase range of nodes from the subgraph. Corresponding edges will also be removed.
Definition subgraph.h:1242
int num_edges() const
Count number of edges in the subgraph.
Definition subgraph.h:760
Subgraph(Other< other_const > &&other) noexcept
Converting constructor to allow implicit conversion from a non-const subgraph to a const subgraph.
Definition subgraph.h:700
void rebind(parent_type &parent)
Re-bind the subgraph to a new parent graph.
Definition subgraph.h:1562
void add_nodes_with_edges(const internal::IndexSet &nodes)
Add nodes to the subgraph, and update the edges.
Definition subgraph.h:910
const_iterator find_node(typename graph_type::ConstNodeRef node) const
Find a node with the given id.
Definition subgraph.h:1140
internal::SubAdjWrapper< Subgraph, is_const > AdjRef
Definition subgraph.h:599
internal::const_if_t< is_const, NT > & node_data(int idx)
Get data of a node in the subgraph.
Definition subgraph.h:1026
static Subgraph from_edges(parent_type &graph, internal::IndexSet &&edges)
Construct a subgraph with the given edges and all nodes connected to the edges.
Definition subgraph.h:675
static Subgraph from_nodes(parent_type &graph, internal::IndexSet &&nodes)
Construct a subgraph with the given nodes and all edges connecting the nodes.
Definition subgraph.h:659
void refresh_edges()
Make this graph an induced subgraph of the parent graph.
Definition subgraph.h:815
const_edge_iterator find_edge(int id) const
Find an edge with the given id.
Definition subgraph.h:1174
const_edge_iterator find_edge(ConstNodeRef src, ConstNodeRef dst) const
Find edge between two nodes.
Definition subgraph.h:1469
edge_iterator find_edge(typename graph_type::ConstNodeRef src, typename graph_type::ConstNodeRef dst)
Find edge between two nodes.
Definition subgraph.h:1483
static Subgraph from_indices(parent_type &graph, internal::IndexSet &&nodes, internal::IndexSet &&edges)
Construct a subgraph with the given nodes and edges.
Definition subgraph.h:639
const_edge_iterator find_edge(typename graph_type::ConstNodeRef src, typename graph_type::ConstNodeRef dst) const
Find edge between two nodes.
Definition subgraph.h:1502
void add_nodes(const internal::IndexSet &nodes)
Add nodes to the subgraph.
Definition subgraph.h:886
Subgraph(const Other< other_const > &other)
Converting constructor to allow implicit conversion from a non-const subgraph to a const subgraph.
Definition subgraph.h:689
void clear_edges() noexcept
Clear the edges.
Definition subgraph.h:834
void remap_edges(const std::vector< int > &old_to_new)
Re-map edge ids.
Definition subgraph.h:1386
const_edge_iterator find_edge(typename graph_type::ConstEdgeRef edge) const
Find an edge with the given id.
Definition subgraph.h:1186
adjacency_iterator adj_end(int idx)
Definition subgraph.h:1540
SubgraphOf< GT > subgraph_from_nodes(GT &&graph, internal::IndexSet &&nodes)
Make a subgraph from list of nodes.
Definition subgraph.h:1730
SubgraphOf< GT > make_subgraph(GT &&graph)
Make an empty subgraph from a graph.
Definition subgraph.h:1696
auto edges(const Graph< NT, ET > &g)
Definition adaptor.h:273
SubgraphOf< GT > subgraph_from_edges(GT &&graph, internal::IndexSet &&edges)
Make a subgraph from list of edges.
Definition subgraph.h:1745
Subgraph(Graph< NT, ET > &graph) -> Subgraph< NT, ET, false >
typename internal::SubgraphTypeHelper< GT >::type SubgraphOf
Definition subgraph.h:1687