diff --git a/include/metrics/centrality.hpp b/include/metrics/centrality.hpp new file mode 100644 index 0000000000..e369534a54 --- /dev/null +++ b/include/metrics/centrality.hpp @@ -0,0 +1,203 @@ +/*PGR-GNU***************************************************************** +File: centrality.hpp + +Copyright (c) 2015 pgRouting developers +Mail: project@pgrouting.org + +Copyright (c) 2024 Arun Thakur +Mail: bedupako12mas@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + + +#ifndef INCLUDE_METRICS_CENTRALITY_HPP_ +#define INCLUDE_METRICS_CENTRALITY_HPP_ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "c_types/iid_t_rt.h" +#include "cpp_common/basePath_SSEC.hpp" +#include "cpp_common/pgr_base_graph.hpp" +#include "cpp_common/interruption.hpp" + +// TODO(vicky) don't keep it here +#include "cpp_common/pgr_alloc.hpp" + +namespace pgrouting { +template < class G > class Pgr_metrics; + +// user's functions +template < class G > +void +pgr_centrality(G &graph, std::vector< IID_t_rt> &rows) { + Pgr_metrics< G > fn_centrality; + fn_centrality.centrality(graph, rows); +} + +// for postgres +template < class G > +void +pgr_centrality( + G &graph, + size_t &result_tuple_count, + IID_t_rt **postgres_rows) { + Pgr_metrics< G > fn_centrality; + fn_centrality.centrality(graph, result_tuple_count, postgres_rows); +} + + +// template class +template < class G > +class Pgr_metrics { + public: + void centrality( + G &graph, + size_t &result_tuple_count, + IID_t_rt **postgres_rows) { + std::vector< std::vector> matrix; + make_matrix(graph.num_vertices(), matrix); + inf_plus combine; + + /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ + CHECK_FOR_INTERRUPTS(); + + boost::floyd_warshall_all_pairs_shortest_paths( + graph.graph, + matrix, + weight_map(get(&pgrouting::Basic_edge::cost, graph.graph)). + distance_combine(combine). + distance_inf((std::numeric_limits::max)()). + distance_zero(0)); + + make_result(graph, matrix, result_tuple_count, postgres_rows); + } + + void centrality( + G &graph, + std::vector< IID_t_rt> &rows) { + std::vector< std::vector> matrix; + make_matrix(graph.num_vertices(), matrix); + inf_plus combine; + + /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ + CHECK_FOR_INTERRUPTS(); + + boost::floyd_warshall_all_pairs_shortest_paths( + graph.graph, + matrix, + weight_map(get(&pgrouting::Basic_edge::cost, graph.graph)). + distance_combine(combine). + distance_inf((std::numeric_limits::max)()). + distance_zero(0)); + + make_result(graph, matrix, rows); + } + + private: + void make_matrix( + size_t v_size, + std::vector< std::vector> &matrix) const { + // TODO(vicky) in one step + matrix.resize(v_size); + for (size_t i=0; i < v_size; i++) + matrix[i].resize(v_size); + } + + void make_result( + const G &graph, + const std::vector< std::vector > &matrix, + size_t &result_tuple_count, + IID_t_rt **postgres_rows) const { + result_tuple_count = count_rows(graph, matrix); + *postgres_rows = pgr_alloc(result_tuple_count, (*postgres_rows)); + + + size_t seq = 0; + for (typename G::V v_i = 0; v_i < graph.num_vertices(); v_i++) { + for (typename G::V v_j = 0; v_j < graph.num_vertices(); v_j++) { + if (v_i == v_j) continue; + if (matrix[v_i][v_j] != (std::numeric_limits::max)()) { + (*postgres_rows)[seq].from_vid = graph[v_i].id; + (*postgres_rows)[seq].to_vid = graph[v_j].id; + (*postgres_rows)[seq].cost = matrix[v_i][v_j]; + seq++; + } // if + } // for j + } // for i + } + + + size_t count_rows( + const G &graph, + const std::vector< std::vector > &matrix) const { + size_t result_tuple_count = 0; + for (size_t i = 0; i < graph.num_vertices(); i++) { + for (size_t j = 0; j < graph.num_vertices(); j++) { + if (i == j) continue; + if (matrix[i][j] != (std::numeric_limits::max)()) { + result_tuple_count++; + } // if + } // for j + } // for i + return result_tuple_count; + } + + void make_result( + G &graph, + std::vector< std::vector > &matrix, + std::vector< IID_t_rt> &rows) { + size_t count = count_rows(graph, matrix); + rows.resize(count); + size_t seq = 0; + + for (typename G::V v_i = 0; v_i < graph.num_vertices(); v_i++) { + for (typename G::V v_j = 0; v_j < graph.num_vertices(); v_j++) { + if (matrix[v_i][v_j] != (std::numeric_limits::max)()) { + rows[seq] = + {graph[v_i].id, graph[v_j].id, matrix[v_i][v_j]}; + seq++; + } // if + } // for j + } // for i + } + + template + struct inf_plus { + T operator()(const T& a, const T& b) const { + T inf = (std::numeric_limits::max)(); + if (a == inf || b == inf) + return inf; + return a + b; + } + }; +}; + +} // namespace pgrouting + +#endif // INCLUDE_METRICS_CENTRALITY_HPP_ diff --git a/src/metrics/centrality_driver.cpp b/src/metrics/centrality_driver.cpp index 83db2fe726..9900a349ca 100644 --- a/src/metrics/centrality_driver.cpp +++ b/src/metrics/centrality_driver.cpp @@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include //TODO: Right now this is doing the floyd warshall, creating the centrality algorithm is pending +#include "metrics/centrality.hpp" #include "allpairs/pgr_allpairs.hpp" #include "cpp_common/pgdata_getters.hpp"