diff --git a/include/drivers/metrics/centrality_driver.h b/include/drivers/metrics/centrality_driver.h new file mode 100644 index 0000000000..a9a6f21034 --- /dev/null +++ b/include/drivers/metrics/centrality_driver.h @@ -0,0 +1,64 @@ +/*PGR-GNU***************************************************************** +File: floydWarshall_driver.h + +Generated with Template by: +Copyright (c) 2015 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2024 Arun Thakur +Mail: bedupako12mas at 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_DRIVERS_METRICS_CENTRALITY_DRIVER_H_ +#define INCLUDE_DRIVERS_METRICS_CENTRALITY_DRIVER_H_ +#pragma once + +/* for size-t */ +#ifdef __cplusplus +# include +using IID_t_rt = struct IID_t_rt; +#else +# include +#include +typedef struct IID_t_rt IID_t_rt; +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +void +pgr_do_centrality( + char*, + bool, + + IID_t_rt**, + size_t*, + char**, + char**); + +#ifdef __cplusplus +} +#endif + +#endif // INCLUDE_DRIVERS_METRICS_CENTRALITY_DRIVER_H_ diff --git a/include/metrics/betweennessCentrality.hpp b/include/metrics/betweennessCentrality.hpp index a4f4fd1beb..d5b29f7372 100644 --- a/include/metrics/betweennessCentrality.hpp +++ b/include/metrics/betweennessCentrality.hpp @@ -48,18 +48,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "cpp_common/pgr_alloc.hpp" namespace pgrouting { -template < class G > class Pgr_metrics; +template 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 > +template void pgr_centrality( G &graph, @@ -71,7 +64,7 @@ pgr_centrality( // template class -template < class G > +template class Pgr_metrics { public: using Graph = typename G::B_G; diff --git a/sql/metrics/CMakeLists.txt b/sql/metrics/CMakeLists.txt index 01fa5eed6c..c047b395e5 100644 --- a/sql/metrics/CMakeLists.txt +++ b/sql/metrics/CMakeLists.txt @@ -1,7 +1,7 @@ SET(LOCAL_FILES - _centrality.sql - centrality.sql + _betweennessCentrality.sql + betweennessCentrality.sql ) foreach (f ${LOCAL_FILES}) diff --git a/sql/metrics/_centrality.sql b/sql/metrics/_betweennessCentrality.sql similarity index 100% rename from sql/metrics/_centrality.sql rename to sql/metrics/_betweennessCentrality.sql diff --git a/sql/metrics/centrality.sql b/sql/metrics/betweennessCentrality.sql similarity index 97% rename from sql/metrics/centrality.sql rename to sql/metrics/betweennessCentrality.sql index 08307b906f..48b468de9c 100644 --- a/sql/metrics/centrality.sql +++ b/sql/metrics/betweennessCentrality.sql @@ -31,7 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --v3.7 CREATE FUNCTION pgr_centrality( TEXT, -- edges_sql (required) - directed BOOLEAN DEFAULT true, + directed BOOLEAN DEFAULT false, OUT start_vid BIGINT, OUT end_vid BIGINT, diff --git a/src/metrics/centrality.c b/src/betweennessCentrality_driver.cpp similarity index 100% rename from src/metrics/centrality.c rename to src/betweennessCentrality_driver.cpp diff --git a/src/metrics/CMakeLists.txt b/src/metrics/CMakeLists.txt index 4d082e613a..c88a1dfd8e 100644 --- a/src/metrics/CMakeLists.txt +++ b/src/metrics/CMakeLists.txt @@ -1,4 +1,4 @@ ADD_LIBRARY(metrics OBJECT - centrality.c - centrality_driver.cpp + betweennessCentrality.c + betweennessCentrality_driver.cpp ) diff --git a/src/metrics/betweennessCentrality.c b/src/metrics/betweennessCentrality.c new file mode 100644 index 0000000000..59f7ea5500 --- /dev/null +++ b/src/metrics/betweennessCentrality.c @@ -0,0 +1,143 @@ +/*PGR-GNU***************************************************************** +File: betweennessCentrality.c + +Generated with Template by: +Copyright (c) 2015 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2024 Arun Thakur +Mail: bedupako12mas at 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*/ + +#include +#include "c_common/postgres_connection.h" + +#include "c_types/iid_t_rt.h" +#include "c_common/debug_macro.h" +#include "c_common/e_report.h" +#include "c_common/time_msg.h" + +#include "drivers/metrics/betweennessCentrality_driver.h" + +PGDLLEXPORT Datum _pgr_centrality(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(_pgr_centrality); + +static +void +process( + char* edges_sql, + bool directed, + IID_t_rt **result_tuples, + size_t *result_count) { + pgr_SPI_connect(); + char* log_msg = NULL; + char* notice_msg = NULL; + char* err_msg = NULL; + + clock_t start_t = clock(); + pgr_do_centrality( + edges_sql, + directed, + result_tuples, + result_count, + &log_msg, + &err_msg); + time_msg(" processing Centrality", start_t, clock()); + + if (err_msg && (*result_tuples)) { + pfree(*result_tuples); + (*result_tuples) = NULL; + (*result_count) = 0; + } + + pgr_global_report(log_msg, notice_msg, err_msg); + + + if (log_msg) pfree(log_msg); + if (notice_msg) pfree(notice_msg); + if (err_msg) pfree(err_msg); + pgr_SPI_finish(); +} + + +PGDLLEXPORT Datum +_pgr_centrality(PG_FUNCTION_ARGS) { + FuncCallContext *funcctx; + TupleDesc tuple_desc; + + + IID_t_rt *result_tuples = NULL; + size_t result_count = 0; + + if (SRF_IS_FIRSTCALL()) { + MemoryContext oldcontext; + funcctx = SRF_FIRSTCALL_INIT(); + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + + process( + text_to_cstring(PG_GETARG_TEXT_P(0)), + PG_GETARG_BOOL(1), + &result_tuples, + &result_count); + + funcctx->max_calls = result_count; + funcctx->user_fctx = result_tuples; + if (get_call_result_type(fcinfo, NULL, &tuple_desc) + != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context " + "that cannot accept type record"))); + + funcctx->tuple_desc = tuple_desc; + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (IID_t_rt*) funcctx->user_fctx; + + if (funcctx->call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool* nulls; + + values = palloc(3 * sizeof(Datum)); + nulls = palloc(3 * sizeof(bool)); + + // postgres starts counting from 1 + values[0] = Int64GetDatum(result_tuples[funcctx->call_cntr].from_vid); + nulls[0] = false; + values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].to_vid); + nulls[1] = false; + values[2] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost); + nulls[2] = false; + + tuple = heap_form_tuple(tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } else { + SRF_RETURN_DONE(funcctx); + } +} + diff --git a/src/metrics/betweennessCentrality_driver.cpp b/src/metrics/betweennessCentrality_driver.cpp new file mode 100644 index 0000000000..666c7659ab --- /dev/null +++ b/src/metrics/betweennessCentrality_driver.cpp @@ -0,0 +1,118 @@ +/*PGR-GNU***************************************************************** +File: centrality_driver.cpp + +Generated with Template by: +Copyright (c) 2015 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2024 Arun Thakur +Mail: bedupako12mas at 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*/ + +#include "drivers/metrics/betweennessCentrality_driver.h" + +#include +#include +#include +#include +#include "metrics/betweennessCentrality.hpp" +#include "cpp_common/pgdata_getters.hpp" + +#include "cpp_common/pgr_assert.hpp" + + +void +pgr_do_centrality( + char *edges_sql, + bool directed, + + IID_t_rt **return_tuples, + size_t *return_count, + char ** log_msg, + char ** err_msg) { + using pgrouting::pgr_msg; + using pgrouting::pgr_free; + + std::ostringstream log; + std::ostringstream err; + char *hint = nullptr; + + try { + pgassert(!(*log_msg)); + pgassert(!(*err_msg)); + pgassert(!(*return_tuples)); + pgassert(*return_count == 0); + + hint = edges_sql; + auto edges = pgrouting::pgget::get_edges(std::string(edges_sql), true, true); + + if (edges.empty()) { + throw std::string("No edges found"); + } + hint = nullptr; + + if (directed) { + log << "Processing Directed graph\n"; + pgrouting::DirectedGraph digraph; + digraph.insert_edges(edges); + pgr_centrality(digraph, *return_count, return_tuples); + } else { + log << "Processing Undirected graph\n"; + pgrouting::UndirectedGraph undigraph; + undigraph.insert_edges(edges); + pgr_centrality(undigraph, *return_count, return_tuples); + } + + + if (*return_count == 0) { + err << "No result generated, report this error\n"; + *err_msg = pgr_msg(err.str().c_str()); + *return_tuples = NULL; + *return_count = 0; + return; + } + + *log_msg = log.str().empty()? + *log_msg : + pgr_msg(log.str().c_str()); + } catch (AssertFailedException &except) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << except.what(); + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } catch (const std::string &ex) { + *err_msg = pgr_msg(ex.c_str()); + *log_msg = hint? pgr_msg(hint) : pgr_msg(log.str().c_str()); + } catch (std::exception &except) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << except.what(); + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } catch(...) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << "Caught unknown exception!"; + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } +}