DG-CPP 0.1.0
Directed Graph in C++
All Classes Namespaces Files Functions Variables Typedefs Pages Concepts
base.hpp
Go to the documentation of this file.
1
12#ifndef _DG_BASE_HPP_
13#define _DG_BASE_HPP_
14
15#include "common.hpp"
16#include "edge.hpp"
17#include "except.hpp"
18#include <functional>
19#include <map>
20#include <set>
21#include <stack>
22#include <string>
23#include <unordered_map>
24#include <unordered_set>
25#include <vector>
26
35namespace dg {
43template <typename EdgeT = void, IDVT IDT = std::string>
45 protected:
46 using _ET = Edge<EdgeT>;
47 using _CN = std::map<IDT, _ET>;
56 template <typename T = EdgeT>
57 using EdgeT__ = typename std::conditional<std::is_void_v<T>, int, T>::type;
58
66 template <typename T = EdgeT>
67 using EdgeT_R_ = typename std::conditional<std::is_void_v<T>, int, T>::type&;
68
76 template <typename T = EdgeT>
77 using EdgeT_CR_ = const typename std::conditional<std::is_void_v<T>, int, T>::type&;
78
79 using EdgeT_ = EdgeT__<>;
83 public:
89 DGraphBase() = default;
90
98 bool hasNode(IDT id) const noexcept;
99
109 bool hasEdge(IDT from_id, IDT to_id) const noexcept;
110
116 size_t numNodes() const noexcept;
117
123 size_t numEdges() const noexcept;
124
131 size_t size() const noexcept;
132
141 EdgeT edge(IDT from_id, IDT to_id) const
142 requires EdgeVT<EdgeT>;
143
151 EdgeT_R edge(IDT from_id, IDT to_id)
152 requires EdgeVT<EdgeT>;
153
176 template <typename Ret, NonFunc Fn, typename... Args>
177 Ret edge(IDT from_id, IDT to_id, Fn func, Args... args) const
178 requires EdgeVT<EdgeT>;
179
200 template <typename Ret, typename... Args>
201 Ret edge(IDT from_id, IDT to_id, std::function<Ret(EdgeT_, Args...)> func, Args... args) const
202 requires EdgeVT<EdgeT>;
203
212 bool strictCheck() const;
213
219 std::vector<IDT> nodesID() const;
220
226 std::vector<std::pair<IDT, IDT>> edges() const;
227
235 void insertNode(IDT id);
236
237 protected:
245 void insertNode(IDT id, const _CN& cn, bool nodes_exist = false);
246
247 public:
263 void insertNode(IDT id, const std::map<IDT, EdgeT>& map, bool nodes_exist = false)
264 requires EdgeVT<EdgeT>;
265
274 void removeNode(IDT id, bool keep_edge = false);
275
283 void removeNodeIfExists(IDT id, bool keep_edge = false);
284
285 void insertEdgeToExists(IDT from_id, IDT to_id)
286 requires std::is_void_v<EdgeT>;
287
288 void insertEdgeToExists(IDT from_id, IDT to_id, EdgeT_CR data)
289 requires EdgeVT<EdgeT>;
290
300 void insertEdge(IDT from_id, IDT to_id, bool to_exists = false)
301 requires std::is_void_v<EdgeT>;
302
313 void insertEdge(IDT from_id, IDT to_id, EdgeT_CR data, bool to_exists = false)
314 requires EdgeVT<EdgeT>;
315
324 bool isConnected(IDT from_id, IDT to_id) const;
325
345 std::pair<EdgeT_, std::vector<IDT>> maxWeightPath(IDT from_id, IDT to_id) const
346 requires EdgeVT<EdgeT> && std::is_arithmetic_v<EdgeT>;
347
375 template <typename Ret, NonFunc Fn, typename... Args>
376 std::pair<Ret, std::vector<IDT>> maxWeightPath(IDT from_id, IDT to_id, Fn func, Args... args) const
377 requires EdgeVT<EdgeT>;
378
392 template <typename Ret, typename... Args>
393 std::pair<Ret, std::vector<IDT>> maxWeightPath(IDT from_id, IDT to_id, std::function<Ret(EdgeT_, Args...)> func,
394 Args... args) const
395 requires EdgeVT<EdgeT>;
396
408 std::pair<EdgeT_, std::vector<IDT>> minWeightPath(IDT from_id, IDT to_id) const
409 requires EdgeVT<EdgeT> && std::is_arithmetic_v<EdgeT>;
410
426 template <typename Ret, NonFunc Fn, typename... Args>
427 std::pair<Ret, std::vector<IDT>> minWeightPath(IDT from_id, IDT to_id, Fn func, Args... args) const
428 requires EdgeVT<EdgeT>;
429
443 template <typename Ret, typename... Args>
444 std::pair<Ret, std::vector<IDT>> minWeightPath(IDT from_id, IDT to_id, std::function<Ret(EdgeT_, Args...)> func,
445 Args... args) const
446 requires EdgeVT<EdgeT>;
447
448 private:
461 template <typename Ret, typename... Args>
462 std::pair<Ret, std::vector<IDT>> minOrMaxWeightPath(bool min, IDT from_id, IDT to_id,
463 std::function<Ret(EdgeT_, Args...)> func, Args... args) const
464 requires EdgeVT<EdgeT>;
465
466 public:
473 void insertSubGraph(const DGraphBase<EdgeT, IDT>& dg);
474
482 void insertSubGraph(const DGraphBase<EdgeT, IDT>& dg, IDT id);
483
489 void merge(const DGraphBase<EdgeT, IDT>& dg);
490
496 void clear();
497
503
512 bool operator==(const DGraphBase<EdgeT, IDT>& dg) const;
513
521 bool operator!=(const DGraphBase<EdgeT, IDT>& dg) const;
522
530 DGraphBase& operator+=(const DGraphBase<EdgeT, IDT>& dg);
531
540 EdgeT operator()(IDT from_id, IDT to_id) const
541 requires EdgeVT<EdgeT>;
542
550 EdgeT_R operator()(IDT from_id, IDT to_id)
551 requires EdgeVT<EdgeT>;
552
553 private:
561
562 protected:
568 const std::map<IDT, _CN>& graph() const;
569
575 std::map<IDT, _CN>& graph();
576
577 private:
578 std::map<IDT, _CN> g;
579};
580
581template <typename EdgeT, IDVT IDT>
582inline bool DGraphBase<EdgeT, IDT>::hasNode(IDT id) const noexcept {
583 return g.contains(id);
584}
585
586template <typename EdgeT, IDVT IDT>
587inline bool DGraphBase<EdgeT, IDT>::hasEdge(IDT from_id, IDT to_id) const noexcept {
588 auto&& from_n = g.find(from_id);
589 return from_n != g.end() && from_n->second.contains(to_id);
590}
591
592template <typename EdgeT, IDVT IDT>
593inline size_t DGraphBase<EdgeT, IDT>::numNodes() const noexcept {
594 return g.size();
595}
596
597template <typename EdgeT, IDVT IDT>
598inline size_t DGraphBase<EdgeT, IDT>::numEdges() const noexcept {
599 size_t s = 0;
600 for (auto&& cn : g) s += cn.second.size();
601 return s;
602}
603
604template <typename EdgeT, IDVT IDT>
605inline size_t DGraphBase<EdgeT, IDT>::size() const noexcept {
606 return numNodes();
607}
608
609template <typename EdgeT, IDVT IDT>
610EdgeT DGraphBase<EdgeT, IDT>::edge(IDT from_id, IDT to_id) const
611 requires EdgeVT<EdgeT> {
612 auto&& from_n = g.find(from_id);
613 if (from_n == g.end()) [[unlikely]]
614 throw node_not_exists("from_id does not exist in method 'edge'");
615 auto&& to_n = from_n->second.find(to_id);
616 if (to_n == from_n->second.end()) [[unlikely]]
617 throw node_not_exists("to_id does not exist in method 'edge'");
618 return to_n->second;
619}
620
621template <typename EdgeT, IDVT IDT>
623 requires EdgeVT<EdgeT> {
624 auto&& from_n = g.find(from_id);
625 if (from_n == g.end()) [[unlikely]]
626 throw node_not_exists("from_id does not exist in method 'edge'");
627 auto&& to_n = from_n->second.find(to_id);
628 if (to_n == from_n->second.end()) [[unlikely]]
629 throw node_not_exists("to_id does not exist in method 'edge'");
630 return to_n->second;
631}
632
633template <typename EdgeT, IDVT IDT>
634template <typename Ret, NonFunc Fn, typename... Args>
635inline Ret DGraphBase<EdgeT, IDT>::edge(IDT from_id, IDT to_id, Fn func, Args... args) const
636 requires EdgeVT<EdgeT> {
637 static_assert(std::is_invocable_r_v<Ret, Fn, DGraphBase<EdgeT, IDT>::EdgeT_, Args...>,
638 "3rd argument (non std::function) must be invocable in method 'edge'.");
639 return func(edge(from_id, to_id), args...);
640}
641
642template <typename EdgeT, IDVT IDT>
643template <typename Ret, typename... Args>
644inline Ret DGraphBase<EdgeT, IDT>::edge(IDT from_id, IDT to_id, std::function<Ret(EdgeT_, Args...)> func,
645 Args... args) const
646 requires EdgeVT<EdgeT> {
647 return func(edge(from_id, to_id), args...);
648}
649
650template <typename EdgeT, IDVT IDT>
652 auto nodes = nodesID();
653 std::vector<IDT> cn_nodes;
654 for (auto&& cn : g)
655 for (auto&& n : cn.second) cn_nodes.push_back(n.first);
656 std::sort(cn_nodes.begin(), cn_nodes.end());
657 cn_nodes.erase(std::unique(cn_nodes.begin(), cn_nodes.end()), cn_nodes.end());
658 return std::includes(nodes.begin(), nodes.end(), cn_nodes.begin(), cn_nodes.end());
659}
660
661template <typename EdgeT, IDVT IDT>
662std::vector<IDT> DGraphBase<EdgeT, IDT>::nodesID() const {
663 std::vector<IDT> keys;
664 std::transform(g.begin(), g.end(), std::back_inserter(keys), [](const auto& pair) { return pair.first; });
665 return keys;
666}
667
668template <typename EdgeT, IDVT IDT>
669inline std::vector<std::pair<IDT, IDT>> DGraphBase<EdgeT, IDT>::edges() const {
670 std::vector<std::pair<IDT, IDT>> e;
671 for (auto&& [from_id, cn] : g) {
672 for (auto&& edge : cn) e.push_back({ from_id, edge.second });
673 }
674 return e;
675}
676
677template <typename EdgeT, IDVT IDT>
679 g[id] = _CN();
680}
681
682template <typename EdgeT, IDVT IDT>
683void DGraphBase<EdgeT, IDT>::insertNode(IDT id, const _CN& cn, bool nodes_exist) {
684 g[id] = cn;
685 if (!nodes_exist) {
686 // update graph nodes
687 for (auto&& n : cn)
688 if (auto&& key = n.first; !g.contains(key)) g[key] = _CN();
689 }
690}
691
692template <typename EdgeT, IDVT IDT>
693void DGraphBase<EdgeT, IDT>::insertNode(IDT id, const std::map<IDT, EdgeT>& map, bool nodes_exist)
694 requires EdgeVT<EdgeT> {
695 insertNode(id, _protected::mapAsEdgeMap(map), nodes_exist);
696}
697
698template <typename EdgeT, IDVT IDT>
699void DGraphBase<EdgeT, IDT>::removeNode(IDT id, bool keep_edge) {
700 if (!g.erase(id)) throw node_not_exists("remove a non-existent node");
701 if (!keep_edge) removeNodeConnectedEdges(id);
702}
703
704template <typename EdgeT, IDVT IDT>
705void DGraphBase<EdgeT, IDT>::removeNodeIfExists(IDT id, bool keep_edge) {
706 g.erase(id);
707 if (!keep_edge) removeNodeConnectedEdges(id);
708}
709
710template <typename EdgeT, IDVT IDT>
711inline void DGraphBase<EdgeT, IDT>::insertEdgeToExists(IDT from_id, IDT to_id)
712 requires std::is_void_v<EdgeT> {
713 g[from_id][to_id] = Edge<void>();
714}
715
716template <typename EdgeT, IDVT IDT>
717inline void DGraphBase<EdgeT, IDT>::insertEdgeToExists(IDT from_id, IDT to_id, EdgeT_CR data)
718 requires EdgeVT<EdgeT> {
719 g[from_id][to_id] = data;
720}
721
722template <typename EdgeT, IDVT IDT>
723void DGraphBase<EdgeT, IDT>::insertEdge(IDT from_id, IDT to_id, bool to_exists)
724 requires std::is_void_v<EdgeT> {
725 insertEdgeToExists(from_id, to_id);
726 if (!to_exists && !g.contains(to_id)) g[to_id] = _CN();
727}
728
729template <typename EdgeT, IDVT IDT>
730void DGraphBase<EdgeT, IDT>::insertEdge(IDT from_id, IDT to_id, typename DGraphBase<EdgeT, IDT>::EdgeT_CR data,
731 bool to_exists)
732 requires EdgeVT<EdgeT> {
733 insertEdgeToExists(from_id, to_id, data);
734 if (!to_exists && !g.contains(to_id)) g[to_id] = _CN();
735}
736
737template <typename EdgeT, IDVT IDT>
738inline bool DGraphBase<EdgeT, IDT>::isConnected(IDT from_id, IDT to_id) const {
739 // check if nodes exist
740 if (!hasNode(from_id) || !hasNode(to_id)) return false;
741 // use DFS to search for path from 'from_id' to 'to_id'
742 std::unordered_set<IDT> visited; // set of visited nodes
743 std::stack<IDT> s; // stack for DFS
744 visited.insert(from_id);
745 s.push(from_id);
746 while (!s.empty()) {
747 IDT node = s.top();
748 s.pop();
749 auto& edges = g.at(node);
750 for (auto& [neighbor, edge] : edges) {
751 if (neighbor == to_id) return true; // found path
752 if (!visited.count(neighbor)) {
753 visited.insert(neighbor);
754 s.push(neighbor);
755 }
756 }
757 }
758 return false; // no path found
759}
760
761template <typename EdgeT, IDVT IDT>
762inline std::pair<typename DGraphBase<EdgeT, IDT>::EdgeT_, std::vector<IDT>>
763DGraphBase<EdgeT, IDT>::maxWeightPath(IDT from_id, IDT to_id) const
764 requires EdgeVT<EdgeT> && std::is_arithmetic_v<EdgeT> {
765 return maxWeightPath<EdgeT>(from_id, to_id, [](EdgeT e) { return e; }); // call the lambda one
766}
767
768template <typename EdgeT, IDVT IDT>
769template <typename Ret, NonFunc Fn, typename... Args>
770inline std::pair<Ret, std::vector<IDT>> DGraphBase<EdgeT, IDT>::maxWeightPath(IDT from_id, IDT to_id, Fn func,
771 Args... args) const
772 requires EdgeVT<EdgeT> {
773 // check if Fn is valid
774 static_assert(std::is_invocable_r_v<Ret, Fn, EdgeT_, Args...>,
775 "3rd argument (non std::function) must be invocable in method 'maxWeightPath'.");
776 // call the std::function one
777 return maxWeightPath<Ret>(from_id, to_id, std::function<Ret(EdgeT_, Args...)>(func), args...);
778}
779
780template <typename EdgeT, IDVT IDT>
781template <typename Ret, typename... Args>
782inline std::pair<Ret, std::vector<IDT>> DGraphBase<EdgeT, IDT>::maxWeightPath(IDT from_id, IDT to_id,
783 std::function<Ret(EdgeT_, Args...)> func,
784 Args... args) const
785 requires EdgeVT<EdgeT> {
786 return minOrMaxWeightPath<Ret>(false, from_id, to_id, func, args...);
787}
788
789template <typename EdgeT, IDVT IDT>
790inline std::pair<typename DGraphBase<EdgeT, IDT>::EdgeT_, std::vector<IDT>>
791DGraphBase<EdgeT, IDT>::minWeightPath(IDT from_id, IDT to_id) const
792 requires EdgeVT<EdgeT> && std::is_arithmetic_v<EdgeT> {
793 return minWeightPath<EdgeT>(from_id, to_id, [](EdgeT e) { return e; }); // call the lambda one
794}
795
796template <typename EdgeT, IDVT IDT>
797template <typename Ret, NonFunc Fn, typename... Args>
798inline std::pair<Ret, std::vector<IDT>> DGraphBase<EdgeT, IDT>::minWeightPath(IDT from_id, IDT to_id, Fn func,
799 Args... args) const
800 requires EdgeVT<EdgeT> {
801 // check if Fn is valid
802 static_assert(std::is_invocable_r_v<Ret, Fn, EdgeT_, Args...>,
803 "3rd argument (non std::function) must be invocable in method 'maxWeightPath'.");
804 // call the std::function one
805 return minWeightPath<Ret>(from_id, to_id, std::function<Ret(EdgeT_, Args...)>(func), args...);
806}
807
808template <typename EdgeT, IDVT IDT>
809template <typename Ret, typename... Args>
810inline std::pair<Ret, std::vector<IDT>> DGraphBase<EdgeT, IDT>::minWeightPath(IDT from_id, IDT to_id,
811 std::function<Ret(EdgeT_, Args...)> func,
812 Args... args) const
813 requires EdgeVT<EdgeT> {
814 return minOrMaxWeightPath<Ret>(true, from_id, to_id, func, args...);
815}
816
817template <typename EdgeT, IDVT IDT>
818template <typename Ret, typename... Args>
819inline std::pair<Ret, std::vector<IDT>>
820DGraphBase<EdgeT, IDT>::minOrMaxWeightPath(bool min, IDT from_id, IDT to_id, std::function<Ret(EdgeT_, Args...)> func,
821 Args... args) const
822 requires EdgeVT<EdgeT> {
823 // Check if both nodes exist in the graph
824 if (!hasNode(from_id) || !hasNode(to_id)) throw node_not_exists("node not found in graph");
825
826 // Check if the from_id is the to_id
827 if (from_id == to_id) return { func(g.at(from_id).at(to_id), args...), { from_id } };
828
829 // Calculate the maximum weight path from the source node to all other nodes using Dijkstra's algorithm
830 std::map<IDT, Ret> dist;
831 std::map<IDT, IDT> prev;
832 std::set<std::pair<Ret, IDT>> pq;
833
834 IDT default_ID;
835 if constexpr (std::is_same_v<IDT, std::string>) default_ID = "__default_ID";
836 else default_ID = IDT(-1);
837
838 // There can not be negative weights in Dijkstra's algorithm
839 Ret bound = min ? std::numeric_limits<Ret>::infinity() : Ret(0);
840
841 // Initialize distances and heap
842 for (auto&& [id, _] : g) {
843 dist[id] = bound;
844 prev[id] = default_ID;
845 pq.insert({ dist[id], id });
846 }
847 dist[from_id] = 0;
848 pq.erase({ bound, from_id });
849 pq.insert({ dist[from_id], from_id });
850
851 while (!pq.empty()) {
852 auto curr_id = pq.begin()->second;
853 pq.erase(pq.begin());
854
855 if (curr_id == to_id) break;
856
857 for (auto&& [nei_id, weight] : g.at(curr_id)) {
858 auto alt = dist[curr_id] + func(weight);
859 if (min ? (alt < dist[nei_id]) : (alt > dist[nei_id])) {
860 pq.erase({ dist[nei_id], nei_id });
861 dist[nei_id] = alt;
862 prev[nei_id] = curr_id;
863 pq.insert({ dist[nei_id], nei_id });
864 }
865 }
866 }
867
868 // Reconstruct the path by backtracking from the target to the source using the prev map
869 std::vector<IDT> path;
870 IDT curr_id = to_id;
871 while (curr_id != default_ID && prev.find(curr_id) != prev.end()) {
872 path.push_back(curr_id);
873 curr_id = prev[curr_id];
874 }
875 std::reverse(path.begin(), path.end());
876
877 // Check if a path was found
878 if (path.size() < 1) throw runtime_error("no path found between nodes in method");
879
880 return { dist[to_id], path };
881}
882
883template <typename EdgeT, IDVT IDT>
885 merge(dg);
886}
887
888template <typename EdgeT, IDVT IDT>
890 removeNode(id);
891 merge(dg);
892}
893
894template <typename EdgeT, IDVT IDT>
896 for (auto&& [id, cn] : dg.g) {
897 if (auto&& i = g.find(id); i == g.end()) g[id] = cn; // not previously existent in *this
898 else i->second.insert(cn.begin(), cn.end()); // the node previously exists, so the connected edges are merged
899 }
900}
901
902template <typename EdgeT, IDVT IDT>
904 g.clear();
905}
906
907template <typename EdgeT, IDVT IDT>
909 for (auto&& cn : g) cn.second.clear();
910}
911
912template <typename EdgeT, IDVT IDT>
914 return this->g == dg.g;
915}
916
917template <typename EdgeT, IDVT IDT>
919 return this->g != dg.g;
920}
921
922template <typename EdgeT, IDVT IDT>
924 merge(dg);
925 return *this;
926}
927
928template <typename EdgeT, IDVT IDT>
929inline EdgeT DGraphBase<EdgeT, IDT>::operator()(IDT from_id, IDT to_id) const
930 requires EdgeVT<EdgeT> {
931 return edge(from_id, to_id);
932}
933
934template <typename EdgeT, IDVT IDT>
936 requires EdgeVT<EdgeT> {
937 return edge(from_id, to_id);
938}
939
940template <typename EdgeT, IDVT IDT>
942 size_t s = 0;
943 for (auto&& cn : g) s += cn.second.erase(id);
944 return s;
945}
946
947template <typename EdgeT, IDVT IDT>
948inline const std::map<IDT, typename DGraphBase<EdgeT, IDT>::_CN>& DGraphBase<EdgeT, IDT>::graph() const {
949 return g;
950}
951
952template <typename EdgeT, IDVT IDT>
953inline std::map<IDT, typename DGraphBase<EdgeT, IDT>::_CN>& DGraphBase<EdgeT, IDT>::graph() {
954 return g;
955}
956
957} // namespace dg
958
959#endif
Directed graph base class.
Definition: base.hpp:44
EdgeT_CR_<> EdgeT_CR
Definition: base.hpp:81
bool hasEdge(IDT from_id, IDT to_id) const noexcept
Check if the graph has an edge linking from_id and to_id.
Definition: base.hpp:587
void merge(const DGraphBase< EdgeT, IDT > &dg)
Merge a graph into the main graph.
Definition: base.hpp:895
EdgeT_R_<> EdgeT_R
Definition: base.hpp:80
size_t size() const noexcept
The total number of nodes in the graph.
Definition: base.hpp:605
std::pair< Ret, std::vector< IDT > > minOrMaxWeightPath(bool min, IDT from_id, IDT to_id, std::function< Ret(EdgeT_, Args...)> func, Args... args) const
Obtain the minimum/maximum weight and its corresponding path between two nodes.
Definition: base.hpp:820
size_t numEdges() const noexcept
The total number of edges in the graph.
Definition: base.hpp:598
std::pair< EdgeT_, std::vector< IDT > > minWeightPath(IDT from_id, IDT to_id) const
Obtain the minimum weight and its corresponding path between two nodes.
Definition: base.hpp:791
const std::map< IDT, _CN > & graph() const
Return the const reference to the graph map.
Definition: base.hpp:948
void removeNode(IDT id, bool keep_edge=false)
Remove the node from the graph.
Definition: base.hpp:699
size_t numNodes() const noexcept
The total number of nodes in the graph.
Definition: base.hpp:593
bool isConnected(IDT from_id, IDT to_id) const
Check whether to node are connected.
Definition: base.hpp:738
DGraphBase & operator+=(const DGraphBase< EdgeT, IDT > &dg)
Merge two graphs.
Definition: base.hpp:923
std::vector< std::pair< IDT, IDT > > edges() const
Get all edge connections in the graph.
Definition: base.hpp:669
std::vector< IDT > nodesID() const
Get all nodes IS in the graph.
Definition: base.hpp:662
void clear()
Clear the whole graph.
Definition: base.hpp:903
bool strictCheck() const
Check if the graph is strictly valid.
Definition: base.hpp:651
DGraphBase()=default
Construct a new DGraphBase object.
std::map< IDT, _ET > _CN
Definition: base.hpp:47
EdgeT edge(IDT from_id, IDT to_id) const
Get the edge data between two nodes.
Definition: base.hpp:610
bool operator==(const DGraphBase< EdgeT, IDT > &dg) const
Check if two graphs are identical.
Definition: base.hpp:913
void insertNode(IDT id)
Insert a node.
Definition: base.hpp:678
std::map< IDT, _CN > g
Definition: base.hpp:578
void insertEdgeToExists(IDT from_id, IDT to_id)
Definition: base.hpp:711
void insertSubGraph(const DGraphBase< EdgeT, IDT > &dg)
Insert subgraph into the main graph.
Definition: base.hpp:884
EdgeT operator()(IDT from_id, IDT to_id) const
Get the edge data between two nodes.
Definition: base.hpp:929
EdgeT__<> EdgeT_
Definition: base.hpp:79
typename std::conditional< std::is_void_v< T >, int, T >::type & EdgeT_R_
Reference to edge type that avoids void.
Definition: base.hpp:67
void removeNodeIfExists(IDT id, bool keep_edge=false)
Remove the node from the graph if it exists.
Definition: base.hpp:705
bool operator!=(const DGraphBase< EdgeT, IDT > &dg) const
Check if two graphs are different.
Definition: base.hpp:918
size_t removeNodeConnectedEdges(IDT id)
Remove edges connected to a node.
Definition: base.hpp:941
bool hasNode(IDT id) const noexcept
Check if the graph has a node with id.
Definition: base.hpp:582
void insertEdge(IDT from_id, IDT to_id, bool to_exists=false)
Insert an edge to the graph without data.
Definition: base.hpp:723
void clearEdges()
Clear all edges of the graph.
Definition: base.hpp:908
const typename std::conditional< std::is_void_v< T >, int, T >::type & EdgeT_CR_
Const reference to edge type that avoids void.
Definition: base.hpp:77
std::pair< EdgeT_, std::vector< IDT > > maxWeightPath(IDT from_id, IDT to_id) const
Obtain the maximum weight and its corresponding path between two nodes.
Definition: base.hpp:763
typename std::conditional< std::is_void_v< T >, int, T >::type EdgeT__
Edge type that avoids void.
Definition: base.hpp:57
Definition: except.hpp:14
Definition: except.hpp:11
Common Utilities for DG-CPP.
Definition: common.hpp:25
Definition: common.hpp:19
Definition: common.hpp:27
static std::map< IDT, Edge< EdgeT > > mapAsEdgeMap(const std::map< IDT, EdgeT > &map)
Definition: edge.hpp:48
Directed Graph namespace.
Definition: base.hpp:35
Definition: edge.hpp:26
Definition: edge.hpp:12