-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPathTree.h
205 lines (178 loc) · 4.54 KB
/
PathTree.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#pragma once
#include <iostream>
#include <boost/graph/graph_traits.hpp>
#include <egraph/routing/PathTreeNode.h>
#include <map>
#include <algorithm>
#include <limits>
#include <boost/assert.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/composite_key.hpp>
namespace egraph
{
namespace routing
{
/**
* @brief builds a shortest path tree
*/
template <typename G>
class PathTree
{
public:
typedef typename boost::graph_traits<G>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<G>::edge_descriptor edge_descriptor;
typedef PathTreeNode<G> node_type;
/**
* @brief A set of PathTreeNode with an additional index on (visited,cost) pair
*/
typedef typename boost::multi_index_container<
node_type,
boost::multi_index::indexed_by<
/* index by identity ( < operator ) */
boost::multi_index::ordered_unique<boost::multi_index::identity<node_type>>,
/* index by (visited,cost) */
boost::multi_index::ordered_non_unique<
boost::multi_index::composite_key<
node_type,
boost::multi_index::member< node_type, bool, &node_type::visited>,
boost::multi_index::member< node_type, double, &node_type::cost>
>
>
>
> node_set;
typedef typename node_set::template nth_index<0>::type reached_index_t;
typedef typename reached_index_t::iterator reached_iterator;
typedef typename reached_index_t::const_iterator const_reached_iterator;
typedef typename node_set::template nth_index<1>::type visited_index_t;
typedef typename visited_index_t::iterator not_visited_iterator;
typedef typename visited_index_t::const_iterator const_not_visited_iterator;
/**
* @brief constructor with a graph
*/
PathTree(const G &graph):
_graph(graph)
{
}
/**
* @brief retrieve graph
*/
const G &graph() const
{
return _graph;
}
/**
* @brief mark the vertex as reached with a cost
*/
void setRoot(vertex_descriptor root)
{
_nodes.clear();
_nodes.insert(node_type(root, 0.0));
}
/**
* @brief get the path to a vertex (empty is not reached)
*/
std::vector<edge_descriptor> path(vertex_descriptor destination) const
{
std::vector<edge_descriptor> result;
if ( ! isReached(destination) ){
return result;
}
node_type current = node(destination);
while ( ! current.isRoot() ){
edge_descriptor edge = current.reachingEdge.get();
result.push_back(edge);
vertex_descriptor source = boost::source(edge,_graph);
vertex_descriptor target = boost::target(edge,_graph);
if ( current.vertex == source ){
current = node(target);
}else{
current = node(source);
}
}
std::reverse(result.begin(), result.end());
return result;
}
/**
* @brief indicates if a vertex is reached
*/
inline bool isReached(vertex_descriptor vertex) const
{
return _nodes.find(vertex) != _nodes.end();
}
/**
* @brief get a vertex node
*
* @warning the vertex must be reached
*/
const node_type &node(vertex_descriptor vertex) const
{
reached_iterator it = _nodes.template get<0>().find(vertex);
BOOST_ASSERT(it != _nodes.end());
return *it;
}
/**
* @brief add a vertex node
*/
void setNode(node_type node)
{
reached_iterator it = _nodes.template get<0>().find(node.vertex);
if (it != _nodes.template get<0>().end())
{
_nodes.replace(it, node);
}
else
{
_nodes.insert(node);
}
}
inline reached_iterator reached_begin()
{
return _nodes.template get<0>().begin();
}
inline const_reached_iterator reached_begin() const
{
return _nodes.template get<0>().begin();
}
inline reached_iterator reached_end()
{
return _nodes.template get<0>().end();
}
inline const_reached_iterator reached_end() const
{
return _nodes.template get<0>().end();
}
inline not_visited_iterator not_visited_begin()
{
return _nodes.template get<1>().lower_bound(
std::make_tuple(false,0.0)
);
}
inline const_not_visited_iterator not_visited_begin() const
{
return _nodes.template get<1>().lower_bound(
std::make_tuple(false,0.0)
);
}
inline not_visited_iterator not_visited_end()
{
return _nodes.template get<1>().upper_bound(
std::make_tuple(false,std::numeric_limits<double>::infinity())
);
}
inline const_not_visited_iterator not_visited_end() const
{
return _nodes.template get<1>().upper_bound(
std::make_tuple(false,std::numeric_limits<double>::infinity())
);
}
private:
const G &_graph;
/**
* @brief store reached vertices
*/
node_set _nodes;
};
} // namespace routing
} // namespace egraph