32 #if defined(__MINGW32__) || defined(_MSC_VER)
51 #include "../../common/src/pgr_base_graph.hpp"
57 template <
class G,
typename T_V,
typename T_E>
62 boost::adjacency_list < boost::listS, boost::vecS,
68 boost::adjacency_list < boost::listS, boost::vecS,
69 boost::bidirectionalS,
75 template <
class G,
typename T_V,
typename T_E>
76 class Pgr_contractionGraph :
public Pgr_base_graph<G, T_V, T_E> {
78 typedef typename boost::graph_traits < G >::vertex_descriptor
V;
79 typedef typename boost::graph_traits < G >::edge_descriptor
E;
80 typedef typename boost::graph_traits < G >::vertex_iterator
V_i;
81 typedef typename boost::graph_traits < G >::edge_iterator
E_i;
82 typedef typename boost::graph_traits < G >::out_edge_iterator
EO_i;
83 typedef typename boost::graph_traits < G >::in_edge_iterator
EI_i;
84 typedef typename std::map< int64_t, V >
id_to_V;
85 typedef typename id_to_V::const_iterator
LI;
94 return edge1.id > edge2.id;
121 template <
typename T >
129 template <
typename T >
131 for (
const auto edge : edges) {
160 V out_vertex, in_vertex;
161 out_vertex = in_vertex = -1;
162 for (boost::tie(out, out_end) = out_edges(v, this->
graph);
163 out != out_end; ++out) {
164 out_vertex = target(*out, this->
graph);
166 for (boost::tie(in, in_end) = in_edges(v, this->
graph);
167 in != in_end; ++in) {
168 in_vertex = source(*in, this->
graph);
172 else if (out_vertex == -1)
174 else if (out_vertex == in_vertex)
187 V out_vertex, in_vertex;
188 out_vertex = in_vertex = -1;
189 for (boost::tie(out, out_end) = out_edges(v, this->
graph);
190 out != out_end; ++out) {
191 out_vertex = target(*out, this->
graph);
192 adjacent_vertices += out_vertex;
194 for (boost::tie(in, in_end) = in_edges(v, this->
graph);
195 in != in_end; ++in) {
196 in_vertex = source(*in, this->
graph);
197 adjacent_vertices += in_vertex;
199 return adjacent_vertices;
203 return this->
graph[v];
207 return this->
graph[e];
217 for (
auto id : boost_ids) {
218 log << this->
graph[id].id <<
", ";
229 int &contracted_vertices_size,
231 contracted_vertices_size = (int)boost_ids.
size();
232 (*contracted_vertices) = (int64_t*)malloc(
sizeof(int64_t)*contracted_vertices_size);
234 for (
auto id : boost_ids) {
235 (*contracted_vertices)[count++] = this->
graph[id].id;
243 for (
auto vi = vertices(this->
graph).first; vi != vertices(this->
graph).second; ++vi) {
245 remaining_vertices.push_back(this->
graph[*vi]);
255 for (
auto vi = vertices(this->
graph).first; vi != vertices(this->
graph).second; ++vi) {
257 remaining_vertices += this->
graph[*vi].id;
269 shortcut_edges.push_back(shortcut);
271 std::sort(shortcut_edges.begin(), shortcut_edges.end(),
compareById);
283 double min_cost = std::numeric_limits<double>::max();
284 for (boost::tie(out_i, out_end) = boost::out_edges(source, this->
graph);
285 out_i != out_end; ++out_i) {
287 if (target(e, this->
graph) == destination) {
288 if (this->
graph[e].cost < min_cost) {
289 min_cost = this->
graph[e].cost;
296 return min_cost_edge;
308 for (boost::tie(in_i, in_end) = boost::in_edges(vertex, this->
graph);
309 in_i != in_end; ++in_i) {
312 if (source(e, this->
graph) == neighbor) {
327 for (boost::tie(out_i, out_end) = boost::out_edges(vertex, this->
graph);
328 out_i != out_end; ++out_i) {
331 if (target(e, this->
graph) == neighbor) {
341 log <<
"Printing shortcuts\n";
352 for (
auto vi = vertices(this->
graph).first; vi != vertices(this->
graph).second; ++vi) {
354 log << this->
graph[(*vi)].id <<
"(" << (*vi) <<
")"
355 << this->
graph[(*vi)].contracted_vertices() << std::endl;
356 log <<
" out_edges_of(" << this->
graph[(*vi)].id <<
"):";
357 for (boost::tie(out, out_end) = out_edges(*vi, this->
graph);
358 out != out_end; ++out) {
359 log <<
' ' << this->
graph[*out].id <<
"=(" << this->
graph[source(*out, this->
graph)].id
360 <<
", " << this->
graph[target(*out, this->
graph)].id <<
") = "
361 << this->
graph[*out].cost <<
"\t";
375 for (
auto vertex : this->
graph[v].contracted_vertices()) {
388 int &contracted_vertices_size, int64_t vid) {
391 contracted_vertices_size = (int)this->
graph[v].contracted_vertices().size();
392 (*contracted_vertices) = (int64_t*)malloc(
sizeof(int64_t)*contracted_vertices_size);
394 for (
auto vertex : this->
graph[v].contracted_vertices()) {
395 (*contracted_vertices)[count++] = this->
graph[
vertex].id;
404 for (
auto vid : e.contracted_vertices()) {
405 this->
graph[v].add_vertex_id(vid);
407 e.clear_contracted_vertices();
413 template <
typename T>
417 if ((edge.cost < 0) && (edge.reverse_cost < 0))
423 auto vm_s = this->
get_V(T_V(edge,
true));
424 auto vm_t = this->
get_V(T_V(edge,
false));
427 if (edge.cost >= 0) {
428 boost::tie(e, inserted) =
429 boost::add_edge(vm_s, vm_t, this->
graph);
430 this->
graph[e].cost = edge.cost;
431 this->
graph[e].id = edge.id;
432 this->
graph[e].first =
true;
433 this->
graph[e].source = edge.source;
434 this->
graph[e].target = edge.target;
436 if (edge.reverse_cost >= 0) {
437 boost::tie(e, inserted) =
438 boost::add_edge(vm_t, vm_s, this->
graph);
440 this->
graph[e].cost = edge.reverse_cost;
441 this->
graph[e].id = edge.id;
442 this->
graph[e].first =
false;
443 this->
graph[e].target = edge.source;
444 this->
graph[e].source = edge.target;
461 log <<
"Graph before adding shortcut\n";
465 auto vm_s = this->
get_V(edge.source);
466 auto vm_t = this->
get_V(edge.target);
467 log <<
"Adding edge between " << this->
graph[vm_s] <<
", "
468 << this->
graph[vm_t] << std::endl;
470 if (edge.cost >= 0) {
471 boost::tie(e, inserted) =
472 boost::add_edge(vm_s, vm_t, this->
graph);
473 log <<
"inserted: " << inserted << std::endl;
474 this->
graph[e].cp_members(edge, log);
475 log << this->
graph[e];
477 log <<
"Graph after adding shortcut\n";
480 shortcut.cp_members(edge, log);
497 log <<
"Disconnecting current vertex " << this->
graph[vertex].id <<
"\n";
500 for (boost::tie(out, out_end) = out_edges(vertex, this->
graph);
501 out != out_end; ++out) {
502 d_edge.id = this->
graph[*out].id;
503 d_edge.source = this->
graph[source(*out, this->
graph)].id;
504 d_edge.target = this->
graph[target(*out, this->
graph)].id;
505 d_edge.cost = this->
graph[*out].cost;
512 for (boost::tie(in, in_end) = in_edges(vertex, this->
graph);
513 in != in_end; ++in) {
514 d_edge.id = this->
graph[*in].id;
515 d_edge.source = this->
graph[source(*in, this->
graph)].id;
516 d_edge.target = this->
graph[target(*in, this->
graph)].id;
517 d_edge.cost = this->
graph[*in].cost;
522 boost::clear_vertex(vertex, this->
graph);
525 log <<
"Caught unknown exception!\n";
void get_ids(std::ostringstream &log, Identifiers< int64_t > boost_ids)
get the user ids given the boost graph ids in string format
bool has(const T other) const
Returns a boolean value true or false.
Identifiers< V > find_adjacent_vertices(V v) const
get the vertex descriptors of adjacent vertices of v
Identifiers< V > removed_vertices
graph::Pgr_contractionGraph< boost::adjacency_list< boost::listS, boost::vecS, boost::undirectedS, contraction::Vertex, contraction::Edge >, contraction::Vertex, contraction::Edge > CHUndirectedGraph
void print_graph(std::ostringstream &log)
print the graph with contracted vertices of all vertices and edges
void print_shortcuts(std::ostringstream &log)
print the edges added during contraction
std::vector< T_E > shortcuts
void disconnect_vertex(std::ostringstream &log, V vertex)
Disconnects all incoming and outgoing edges from the vertex boost::graph doesn't recommend th to inse...
boost::graph_traits< G >::edge_iterator E_i
bool is_connected(int64_t v) const
True when.
void get_contracted_vertices(std::ostringstream &log, int64_t vid)
get the contracted vertex ids of a given vertex in string format
boost::graph_traits< G >::vertex_iterator V_i
void get_remaining_vertices(std::vector< T_V > &remaining_vertices)
get the remaining vertices of the graph after contraction
void graph_add_edge(const T &edge)
Inserts an edge of type T into the graph.
boost::graph_traits< G >::edge_descriptor E
boost::graph_traits< G >::vertex_descriptor V
graphType m_gType
type (DIRECTED or UNDIRECTED)
bool has_vertex(int64_t vid) const
True when vid is in the graph.
boost::graph_traits< G >::degree_size_type degree_size_type
size_t m_num_vertices
local count.
void get_contracted_vertices(int64_t **contracted_vertices, int &contracted_vertices_size, int64_t vid)
get the contracted vertex ids of a given vertex in string format
static bool compareById(const T_E &edge1, const T_E &edge2)
Binary function that accepts two elements , and returns a value convertible to bool.
V get_V(const T_V &vertex)
get the vertex descriptor of the vertex
void get_shortcuts(std::vector< T_E > &shortcut_edges)
get the edges of the graph that are added during contraction
#define pgassert(expr)
Uses the standard assert syntax.
graph::Pgr_contractionGraph< boost::adjacency_list< boost::listS, boost::vecS, boost::bidirectionalS, contraction::Vertex, contraction::Edge >, contraction::Vertex, contraction::Edge > CHDirectedGraph
void graph_add_shortcut(const T_E &edge, std::ostringstream &log)
add edges(shortuct) to the graph during contraction
std::map< int64_t, V > id_to_V
V find_adjacent_vertex(V v) const
id_to_V::const_iterator LI
void add_contracted_edge_vertices(V v, T_E &e)
add the contracted vertices of an edge e to the vertex v
id_to_V vertices_map
id -> graph id
degree_size_type out_degree(int64_t vertex_id) const
get the out-degree of a vertex
void get_changed_vertices(Identifiers< int64_t > &remaining_vertices)
get the vertices of the graph with atleast one contracted vertex
std::deque< T_E > removed_edges
Used for storing the removed_edges.
boost::graph_traits< G >::out_edge_iterator EO_i
void graph_insert_data(const std::vector< T > &edges)
Inserts vector of edges of type T into the graph.
degree_size_type in_degree(V &v) const
True when vid is in the graph.
degree_size_type out_degree_to_vertex(V vertex, V neighbor)
get the out-degree of a vertex to its neighbor
degree_size_type in_degree_from_vertex(V vertex, V neighbor)
get the in-degree of a vertex from its neighbor
boost::graph_traits< G >::in_edge_iterator EI_i
void get_ids(int64_t **contracted_vertices, int &contracted_vertices_size, Identifiers< int64_t > boost_ids)
get the user ids given the boost graph ids in array format
void graph_insert_data(const T *edges, int64_t count)
Inserts count edges of type T into the graph.
E get_min_cost_edge(V source, V destination)
get the edge with minimum cost between two vertices