KrisLibrary  1.0.0
UndirectedGraph.h
1 #ifndef GRAPH_UNDIRECTED_GRAPH_H
2 #define GRAPH_UNDIRECTED_GRAPH_H
3 
4 #include <KrisLibrary/Logger.h>
5 #include "Graph.h"
6 #include "Callback.h"
7 
8 namespace Graph {
9 
16 template <class Node,class Edge>
17 class UndirectedGraph : public Graph<Node,Edge>
18 {
19 public:
20  typedef Graph<Node,Edge> P;
21  typedef typename Graph<Node,Edge>::Callback Callback;
23 
24  inline void Order(int& a, int& b) const { if(a>b) std::swap(a,b); }
25 
26  inline Edge& AddEdge(int i,int j) {
27  Order(i,j);
28  return P::AddEdge(i,j);
29  }
30 
31  inline Edge& AddEdge(int i,int j,const Edge& e) {
32  Order(i,j);
33  return P::AddEdge(i,j,e);
34  }
35 
36  inline bool HasEdge(int i,int j) const {
37  Order(i,j);
38  return P::HasEdge(i,j);
39  }
40 
41  inline Edge* FindEdge(int i,int j) const {
42  Order(i,j);
43  return P::FindEdge(i,j);
44  }
45 
46  inline void DeleteEdge(int i,int j) {
47  Order(i,j);
48  P::DeleteEdge(i,j);
49  }
50 
51  inline void DeleteIncomingEdges(int i) {
52  P::DeleteIncomingEdges(i);
53  P::DeleteOutgoingEdges(i);
54  }
55 
56  inline void DeleteNode(int n) {
57  P::DeleteNode(n);
58  //since the last node gets moved into n, the order of the edges
59  //has changed. need to order the edges outgoing/incoming to n
60  if(n < (int)P::nodes.size()) NormalizeEdges(n);
61  }
62 
63  inline void DeleteNodes(std::vector<int>& delnodes) {
64  P::DeleteNodes(delnodes);
65  //normalize the edges
66  for(size_t i=0;i<delnodes.size();i++)
67  if(delnodes[i]>=0 && delnodes[i] < (int)P::nodes.size() && delnodes[i]!=(int)i)
68  NormalizeEdges(delnodes[i]);
69  }
70 
71 
72  inline void DFS(Callback& f) { P::DFS(f,Iterator()); }
73  inline void BFS(Callback& f) { P::BFS(f,Iterator()); }
74  inline void SimpleDFS(Callback& f) { P::SimpleDFS(f,Iterator()); }
75  inline void SimpleBFS(Callback& f) { P::SimpleBFS(f,Iterator()); }
76  inline void GuidedDFS(Callback& f) { P::GuidedDFS(f,Iterator()); }
77  inline void GuidedBFS(Callback& f) { P::GuidedBFS(f,Iterator()); }
78 
80  inline void _DFS(int node,Callback& f)
81  { P::_DFS(node,f,Iterator()); }
82  inline void _BFS(int node,Callback& f)
83  { P::_BFS(node,f,Iterator()); }
84  inline void _SimpleDFS(int node,Callback& f)
85  { P::_SimpleDFS(node,f,Iterator()); }
86  inline void _SimpleBFS(int node,Callback& f)
87  { P::_SimpleBFS(node,f,Iterator()); }
88  inline void _GuidedDFS(int node,Callback& f)
89  { P::_GuidedDFS(node,f,Iterator()); }
90  inline void _GuidedBFS(int node,Callback& f)
91  { P::_GuidedBFS(node,f,Iterator()); }
92 
93  inline size_t Degree(int n) const { return P::edges[n].size()+P::co_edges[n].size(); }
94 
99  bool IsConnected(int n1,int n2);
101  std::list<int> TopologicalSort();
103  bool HasCycle();
104  bool IsValid() const;
105 
106  //helper that orders the edges (n,m) out of n such that n<m,
107  //and incoming edges (m,n) into n such that n>m
108  void NormalizeEdges(int n);
109 };
110 
111 template <class Node,class Edge>
112 bool UndirectedGraph<Node,Edge>::IsConnected(const int n1,const int n2)
113 {
114  Order(n1,n2);
115  FindCallback<int> findNode(n2);
116  return _SimpleDFS(n1,findNode);
117 }
118 
119 template <class Node,class Edge>
121 {
123  DFS(f);
124  return f.list;
125 }
126 
127 template <class Node,class Edge>
129 {
130  //TODO: this doesn't quite work because every edge has a cycle
132  DFS(f);
133  return f.hasCycle;
134 }
135 
136 template <class Node,class Edge>
138 {
139  if(!P::IsValid()) return false;
140  bool res=true;
141  typedef typename P::ConstEdgeListIterator ConstEdgeIterator;
142  for(size_t i=0;i<P::edges.size();i++) {
143  ConstEdgeIterator ebegin=P::edges[i].begin(),eend=P::edges[i].end();
144  for(ConstEdgeIterator e=ebegin;e!=eend;e++) {
145  if(e->first < (int)i) {
146  LOG4CXX_ERROR(KrisLibrary::logger(),"Undirected edge ("<<i<<","<<e->first);
147  res=false;
148  }
149  }
150  }
151  for(size_t i=0;i<P::co_edges.size();i++) {
152  ConstEdgeIterator ebegin=P::co_edges[i].begin(),eend=P::co_edges[i].end();
153  for(ConstEdgeIterator e=ebegin;e!=eend;e++) {
154  if(e->first > (int)i) {
155  LOG4CXX_ERROR(KrisLibrary::logger(),"Undirected co-edge ("<<e->first<<","<<i);
156  res=false;
157  }
158  }
159  }
160  return res;
161 }
162 
163 template <class Node,class Edge>
165 {
166  Assert(0 <= n && n < P::NumNodes());
167  typedef typename P::EdgeListIterator EdgeIterator;
168  typedef typename P::CoEdgeListIterator CoEdgeIterator;
169  typedef typename P::EdgeDataPtr EdgeDataPtr;
170  std::map<int,EdgeDataPtr> delEdges,delCoEdges;
171  EdgeIterator ebegin=P::edges[n].begin(),eend=P::edges[n].end();
172  for(EdgeIterator e=ebegin;e!=eend;e++) {
173  int tgt=e->first;
174  Assert(0 <= tgt && tgt < P::NumNodes());
175  if(tgt < n) //swap the edge
176  delEdges[tgt] = e->second;
177  }
178  CoEdgeIterator cbegin=P::co_edges[n].begin(),cend=P::co_edges[n].end();
179  for(CoEdgeIterator c=cbegin;c!=cend;c++) {
180  int src=c->first;
181  Assert(0 <= src && src < P::NumNodes());
182  if(src > n) //swap the edge
183  delCoEdges[src] = c->second;
184  }
185 
186  for(EdgeIterator e=delEdges.begin();e!=delEdges.end();e++) {
187  int tgt=e->first;
188  size_t num=P::edges[n].erase(tgt); Assert(num==1);
189  num=P::co_edges[tgt].erase(n); Assert(num==1);
190 
191  P::edges[tgt][n] = e->second;
192  P::co_edges[n][tgt] = e->second;
193  }
194  for(CoEdgeIterator c=delCoEdges.begin();c!=delCoEdges.end();c++) {
195  int src=c->first;
196  size_t num=P::co_edges[n].erase(src); Assert(num==1);
197  num=P::edges[src].erase(n); Assert(num==1);
198 
199  P::co_edges[src][n] = c->second;
200  P::edges[n][src] = c->second;
201  }
202 }
203 
204 
205 } //namespace Graph
206 
207 #endif
Definition: Edge.h:28
Compute if the graph has a cycle.
Definition: Callback.h:105
Abstract base class for an edge planner / edge checker (i.e., local planner).
Definition: EdgePlanner.h:49
bool HasCycle()
Returns true if there is any cycle, O(n) time.
Definition: UndirectedGraph.h:128
Definition: Edge.h:58
void DeleteNodes(std::vector< int > &delnodes)
Deletes several nodes at once.
void _DFS(int node, Callback &f)
NOTE: these do not call NewTraversal()
Definition: UndirectedGraph.h:80
bool IsConnected(int n1, int n2)
Definition: UndirectedGraph.h:112
std::list< int > TopologicalSort()
Returns the topological sort of the graph, O(n) time.
Definition: UndirectedGraph.h:120
void DeleteNode(int n)
Deletes node n.
The logging system used in KrisLibrary.
Namespace for all classes and functions in the Graph subdirectory.
Definition: ApproximateShortestPaths.h:7
Perform topological sort, when used with DFS.
Definition: Callback.h:115
Definition: Edge.h:88
void _DFS(int node, Callback &f, Iterator)
Find a particular node.
Definition: Callback.h:53
A specialization of a Graph to be an undirected graph.
Definition: UndirectedGraph.h:17