diff --git a/NEWS.md b/NEWS.md index 2a11ef7a36..e9a159bbd1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -25,6 +25,7 @@ To see all issues & pull requests closed by this release see the * [#3089](https://github.com/pgRouting/pgrouting/issues/3089): edgeDisjoint and bellmanFord use shortestPath driver and process * [#3100](https://github.com/pgRouting/pgrouting/issues/3100): Coloring: create and use a process & driver +* [#3113](https://github.com/pgRouting/pgrouting/issues/3113): Components: Integrate into existing process/driver pair **Bug Fixes** diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index c81a3c998e..8941b3ca01 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -50,6 +50,7 @@ To see all issues & pull requests closed by this release see the * :issue:`3089`: edgeDisjoint and bellmanFord use shortestPath driver and process * :issue:`3100`: Coloring: create and use a process & driver +* :issue:`3113`: Components: Integrate into existing process/driver pair .. rubric:: Bug Fixes diff --git a/include/c_common/enums.h b/include/c_common/enums.h index bce4f67c2b..bf6a563e5e 100644 --- a/include/c_common/enums.h +++ b/include/c_common/enums.h @@ -50,7 +50,10 @@ enum Which { // NOLINT(cppcoreguidelines-use-enum-class) /* For flow */ MAXFLOW, PUSHRELABEL, BOYKOV, EDMONDSKARP, /* For coloring */ - EDGECOLORING, BIPARTITE, SEQUENTIAL + EDGECOLORING, BIPARTITE, SEQUENTIAL, + /* For components */ + CONNECTEDCOMPONENTS, BICONNECTEDCOMPONENTS, STRONGCOMPONENTS, ARTICULATIONPOINTS, + BRIDGES, MAKECONNECTED }; #endif // INCLUDE_C_COMMON_ENUMS_H_ diff --git a/include/components/components.hpp b/include/components/components.hpp index 1dd82e4f43..49ecd11799 100644 --- a/include/components/components.hpp +++ b/include/components/components.hpp @@ -43,7 +43,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "cpp_common/base_graph.hpp" #include "cpp_common/identifiers.hpp" -#include "components/componentsResult.hpp" namespace pgrouting { namespace algorithms { @@ -51,15 +50,15 @@ namespace algorithms { /** * works for undirected graph **/ -std::vector -pgr_connectedComponents(pgrouting::UndirectedGraph &graph); +std::vector> +connectedComponents(pgrouting::UndirectedGraph &graph); //! Strongly Connected Components Vertex Version -std::vector +std::vector> strongComponents(pgrouting::DirectedGraph &graph); //! Biconnected Components (for undirected) -std::vector +std::vector> biconnectedComponents(pgrouting::UndirectedGraph &graph); //! Articulation Points diff --git a/include/components/componentsResult.hpp b/include/components/componentsResult.hpp deleted file mode 100644 index bff0fa08bb..0000000000 --- a/include/components/componentsResult.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/*PGR-GNU***************************************************************** -File: componentsResult.hpp - -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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_COMPONENTS_COMPONENTSRESULT_HPP_ -#define INCLUDE_COMPONENTS_COMPONENTSRESULT_HPP_ -#pragma once - -#include -#include - -#include "c_types/ii_t_rt.h" - - -namespace pgrouting { -namespace algorithms { - -namespace detail { - -std::vector -componentsResult( - std::vector> &components); - -} // namespace detail - -} // namespace algorithms -} // namespace pgrouting - -#endif // INCLUDE_COMPONENTS_COMPONENTSRESULT_HPP_ diff --git a/include/components/makeConnected.hpp b/include/components/makeConnected.hpp index 34ed8071e4..0d9908563f 100644 --- a/include/components/makeConnected.hpp +++ b/include/components/makeConnected.hpp @@ -50,56 +50,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. namespace pgrouting { namespace functions { -template < class G > -class Pgr_makeConnected : public pgrouting::Pgr_messages { - public: - typedef typename G::V V; - typedef typename G::E E; - typedef typename G::E_i E_i; - std::vector makeConnected(G &graph) { - return generatemakeConnected(graph); - } +std::vector +makeConnected(pgrouting::UndirectedGraph &graph); - private: - std::vector< II_t_rt > generatemakeConnected(G &graph ) { - std::vector component(boost::num_vertices(graph.graph)); - auto comp = boost::connected_components(graph.graph, &component[0]); - comp--; - auto edgeCount = boost::num_edges(graph.graph); - size_t newEdge = 0; - log << "Number of Components before: " << boost::connected_components(graph.graph, &component[0]) << "\n"; - size_t i = 0; - - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ - CHECK_FOR_INTERRUPTS(); - try { - boost::make_connected(graph.graph); - } catch (boost::exception const& ex) { - (void)ex; - throw; - } catch (std::exception &e) { - (void)e; - throw; - } catch (...) { - throw; - } - - log << "Number of Components after: " << boost::connected_components(graph.graph, &component[0]) << "\n"; - E_i ei, ei_end; - std::vector< II_t_rt > results(comp); - for (boost::tie(ei, ei_end) = edges(graph.graph); ei != ei_end; ++ei) { - int64_t src = graph[graph.source(*ei)].id; - int64_t tgt = graph[graph.target(*ei)].id; - log<< "src:" << src<< "tgt:" << tgt <<"\n"; - if (newEdge >= edgeCount) { - results[i] = {src, tgt}; - i++; - } - newEdge++; - } - return results; - } -}; } // namespace functions } // namespace pgrouting diff --git a/include/cpp_common/to_postgres.hpp b/include/cpp_common/to_postgres.hpp index 7dd471c36b..cf9f29c75e 100644 --- a/include/cpp_common/to_postgres.hpp +++ b/include/cpp_common/to_postgres.hpp @@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "c_types/contractionHierarchies_rt.h" #include "c_types/iid_t_rt.h" +#include "c_types/ii_t_rt.h" #include "c_types/routes_t.h" #include "c_types/path_rt.h" #include "c_types/mst_rt.h" @@ -53,34 +54,40 @@ size_t count_rows(const std::vector>&); } // namespace detail -/* +/** * @brief Via Routes save on a C array */ size_t get_viaRoute(std::deque&, Routes_t**); -/* +/** * @brief get tuples from a Path to a Path_rt */ size_t get_tuples(const std::deque&, Path_rt*&); - -/* +/** * @brief get tuples from a Path to a MST_rt */ size_t get_tuples(const std::deque&, MST_rt*&); -/* +/** * @brief get tuples for Flow_t */ size_t get_tuples(const std::vector&, Flow_t*&); -/* +/** * @brief get tuples for Path_rt */ size_t get_tuples(std::vector&, const std::vector&, Path_rt*&); -/* +size_t +get_tuples(const std::vector&, II_t_rt*&); + +size_t +get_tuples(std::vector>&, II_t_rt*&); + + +/** * @brief get tuples for spanning tree driver */ size_t get_tuples( @@ -89,11 +96,32 @@ size_t get_tuples( const std::vector>&, MST_rt*&); -/* +/** * @brief get tuples from a vector of MST_rt to a MST_rt */ size_t get_tuples(const std::vector&, MST_rt*&); +/** + * @brief get tuples from Identifiers + */ +template +size_t get_identifiers( + const Identifiers &ids, + int64_t* &tuples) { + pgassert(!tuples); + + auto count = ids.size(); + if (count == 0) return 0; + + tuples = pgrouting::pgr_alloc(count, tuples); + + size_t i = 0; + for (const auto &id : ids) { + tuples[i++] = id; + } + return count; +} + /** @brief Vector of vertices id are saved on a C array * * @param[in] graph Created graph with the base Graph diff --git a/include/drivers/coloring_driver.hpp b/include/drivers/coloring_driver.hpp index 7a5f279f6e..d7e8a00993 100644 --- a/include/drivers/coloring_driver.hpp +++ b/include/drivers/coloring_driver.hpp @@ -44,6 +44,7 @@ namespace drivers { void do_coloring( const std::string&, + bool, Which, II_t_rt*&, size_t&, std::ostringstream&, std::ostringstream&, std::ostringstream&); diff --git a/include/drivers/components/articulationPoints_driver.h b/include/drivers/components/articulationPoints_driver.h deleted file mode 100644 index 04720a3fe6..0000000000 --- a/include/drivers/components/articulationPoints_driver.h +++ /dev/null @@ -1,61 +0,0 @@ -/*PGR-GNU***************************************************************** -File: articulationPoints_driver.h - -Generated with Template by: -Copyright (c) 2007-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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_COMPONENTS_ARTICULATIONPOINTS_DRIVER_H_ -#define INCLUDE_DRIVERS_COMPONENTS_ARTICULATIONPOINTS_DRIVER_H_ -#pragma once - -/* for size-t */ -#ifdef __cplusplus -# include -# include -using Edge_t = struct Edge_t; -#else -# include -# include -typedef struct Edge_t Edge_t; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -void pgr_do_articulationPoints( - const char*, - int64_t**, size_t*, - - char**, char**, char**); - - -#ifdef __cplusplus -} -#endif - -#endif // INCLUDE_DRIVERS_COMPONENTS_ARTICULATIONPOINTS_DRIVER_H_ diff --git a/include/drivers/components/biconnectedComponents_driver.h b/include/drivers/components/biconnectedComponents_driver.h deleted file mode 100644 index c2c7e763ce..0000000000 --- a/include/drivers/components/biconnectedComponents_driver.h +++ /dev/null @@ -1,60 +0,0 @@ -/*PGR-GNU***************************************************************** -File: biconnectedComponents_driver.h - -Generated with Template by: -Copyright (c) 2007-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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_COMPONENTS_BICONNECTEDCOMPONENTS_DRIVER_H_ -#define INCLUDE_DRIVERS_COMPONENTS_BICONNECTEDCOMPONENTS_DRIVER_H_ -#pragma once - -/* for size-t */ -#ifdef __cplusplus -# include -using Edge_t = struct Edge_t; -using II_t_rt = struct II_t_rt; -#else -# include -typedef struct Edge_t Edge_t; -typedef struct II_t_rt II_t_rt; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -void pgr_do_biconnectedComponents( - const char*, - - II_t_rt**, size_t*, - char**, char**, char**); - -#ifdef __cplusplus -} -#endif - -#endif // INCLUDE_DRIVERS_COMPONENTS_BICONNECTEDCOMPONENTS_DRIVER_H_ diff --git a/include/drivers/components/bridges_driver.h b/include/drivers/components/bridges_driver.h deleted file mode 100644 index 1633e3404d..0000000000 --- a/include/drivers/components/bridges_driver.h +++ /dev/null @@ -1,58 +0,0 @@ -/*PGR-GNU***************************************************************** -File: bridges_driver.h - -Generated with Template by: -Copyright (c) 2007-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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_COMPONENTS_BRIDGES_DRIVER_H_ -#define INCLUDE_DRIVERS_COMPONENTS_BRIDGES_DRIVER_H_ -#pragma once - -#ifdef __cplusplus -# include -# include -#else -# include -# include -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - -void pgr_do_bridges( - const char*, - - int64_t**, size_t*, - char**, char**, char**); - -#ifdef __cplusplus -} -#endif - -#endif // INCLUDE_DRIVERS_COMPONENTS_BRIDGES_DRIVER_H_ diff --git a/include/drivers/components/connectedComponents_driver.h b/include/drivers/components/connectedComponents_driver.h deleted file mode 100644 index 3c40c3f488..0000000000 --- a/include/drivers/components/connectedComponents_driver.h +++ /dev/null @@ -1,57 +0,0 @@ -/*PGR-GNU***************************************************************** -File: connectedComponents_driver.h - -Generated with Template by: -Copyright (c) 2007-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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_COMPONENTS_CONNECTEDCOMPONENTS_DRIVER_H_ -#define INCLUDE_DRIVERS_COMPONENTS_CONNECTEDCOMPONENTS_DRIVER_H_ -#pragma once - -#ifdef __cplusplus -# include -using II_t_rt = struct II_t_rt; -#else -# include -typedef struct II_t_rt II_t_rt; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -void pgr_do_connectedComponents( - const char*, - - II_t_rt**, size_t*, - char**, char**, char**); - -#ifdef __cplusplus -} -#endif - -#endif // INCLUDE_DRIVERS_COMPONENTS_CONNECTEDCOMPONENTS_DRIVER_H_ diff --git a/include/drivers/components/makeConnected_driver.h b/include/drivers/components/makeConnected_driver.h deleted file mode 100644 index 313b0265d1..0000000000 --- a/include/drivers/components/makeConnected_driver.h +++ /dev/null @@ -1,57 +0,0 @@ -/*PGR-GNU***************************************************************** -File: makeConnected_driver.h - -Generated with Template by: -Copyright (c) 2007-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2020 Himanshu Raj -Mail: raj.himanshu2@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_COMPONENTS_MAKECONNECTED_DRIVER_H_ -#define INCLUDE_DRIVERS_COMPONENTS_MAKECONNECTED_DRIVER_H_ -#pragma once - -#ifdef __cplusplus -# include -using II_t_rt = struct II_t_rt; -#else -# include -typedef struct II_t_rt II_t_rt; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -void pgr_do_makeConnected( - const char*, - - II_t_rt**, size_t*, - char**, char**, char**); - -#ifdef __cplusplus -} -#endif - -#endif // INCLUDE_DRIVERS_COMPONENTS_MAKECONNECTED_DRIVER_H_ diff --git a/include/drivers/components/strongComponents_driver.h b/include/drivers/components/strongComponents_driver.h deleted file mode 100644 index be0814da92..0000000000 --- a/include/drivers/components/strongComponents_driver.h +++ /dev/null @@ -1,57 +0,0 @@ -/*PGR-GNU***************************************************************** -File: strongComponents_driver.h - -Generated with Template by: -Copyright (c) 2007-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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_COMPONENTS_STRONGCOMPONENTS_DRIVER_H_ -#define INCLUDE_DRIVERS_COMPONENTS_STRONGCOMPONENTS_DRIVER_H_ -#pragma once - -#ifdef __cplusplus -# include -using II_t_rt = struct II_t_rt; -#else -# include -typedef struct II_t_rt II_t_rt; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -void pgr_do_strongComponents( - const char*, - - II_t_rt**, size_t*, - char**, char**, char**); - -#ifdef __cplusplus -} -#endif - -#endif // INCLUDE_DRIVERS_COMPONENTS_STRONGCOMPONENTS_DRIVER_H_ diff --git a/include/drivers/ordering_driver.hpp b/include/drivers/ordering_driver.hpp index b74e099c85..58949b940e 100644 --- a/include/drivers/ordering_driver.hpp +++ b/include/drivers/ordering_driver.hpp @@ -46,7 +46,8 @@ namespace pgrouting { namespace drivers { void do_ordering( - const std::string&, Which, + const std::string&, bool, + Which, int64_t*&, size_t&, std::ostringstream&, std::ostringstream&, std::ostringstream&); diff --git a/include/process/coloring_process.h b/include/process/coloring_process.h index 63d003db2e..491ef2a023 100644 --- a/include/process/coloring_process.h +++ b/include/process/coloring_process.h @@ -48,7 +48,7 @@ extern "C" { #endif void pgr_process_coloring( - const char*, + const char*, bool, enum Which, II_t_rt**, size_t*); diff --git a/include/process/ordering_process.h b/include/process/ordering_process.h index afc3dfe9e3..1e8b9ea854 100644 --- a/include/process/ordering_process.h +++ b/include/process/ordering_process.h @@ -44,7 +44,7 @@ extern "C" { #endif void pgr_process_ordering( - const char*, + const char*, bool, enum Which, int64_t**, size_t*); diff --git a/locale/en/LC_MESSAGES/pgrouting_doc_strings.po b/locale/en/LC_MESSAGES/pgrouting_doc_strings.po index eeac2c3c6e..66949f822e 100644 --- a/locale/en/LC_MESSAGES/pgrouting_doc_strings.po +++ b/locale/en/LC_MESSAGES/pgrouting_doc_strings.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: pgRouting v4.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 20:20+0000\n" +"POT-Creation-Date: 2026-06-10 19:05+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3976,6 +3976,11 @@ msgid "" "create and use a process & driver" msgstr "" +msgid "" +"`#3113 `__: Components: " +"Integrate into existing process/driver pair" +msgstr "" + msgid "Bug Fixes" msgstr "" diff --git a/locale/pot/pgrouting_doc_strings.pot b/locale/pot/pgrouting_doc_strings.pot index cfdb7f9a61..be0206387a 100644 --- a/locale/pot/pgrouting_doc_strings.pot +++ b/locale/pot/pgrouting_doc_strings.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: pgRouting v4.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 20:20+0000\n" +"POT-Creation-Date: 2026-06-10 19:05+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3559,6 +3559,9 @@ msgstr "" msgid "`#3100 `__: Coloring: create and use a process & driver" msgstr "" +msgid "`#3113 `__: Components: Integrate into existing process/driver pair" +msgstr "" + msgid "Bug Fixes" msgstr "" diff --git a/src/coloring/bipartite.c b/src/coloring/bipartite.c index 0680cc0cf2..93c1e2df09 100644 --- a/src/coloring/bipartite.c +++ b/src/coloring/bipartite.c @@ -27,25 +27,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ - #include #include "c_common/postgres_connection.h" - -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" #include "c_types/ii_t_rt.h" #include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_bipartite(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_bipartite); - PGDLLEXPORT Datum _pgr_bipartite(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; - TupleDesc tuple_desc; + TupleDesc tuple_desc; + II_t_rt *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; @@ -54,13 +49,13 @@ PGDLLEXPORT Datum _pgr_bipartite(PG_FUNCTION_ARGS) { pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, BIPARTITE, &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) { @@ -74,22 +69,22 @@ PGDLLEXPORT Datum _pgr_bipartite(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (II_t_rt*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (II_t_rt*) funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { + if (call_cntr < funcctx->max_calls) { HeapTuple tuple; Datum result; Datum *values; bool *nulls; - size_t call_cntr = funcctx->call_cntr; - size_t numb = 2; - values =(Datum *)palloc(numb * sizeof(Datum)); - nulls = palloc(numb * sizeof(bool)); + size_t num = 2; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < numb; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } diff --git a/src/coloring/coloring_driver.cpp b/src/coloring/coloring_driver.cpp index f57dab1ca3..6dbf3d6fef 100644 --- a/src/coloring/coloring_driver.cpp +++ b/src/coloring/coloring_driver.cpp @@ -36,6 +36,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include "c_types/ii_t_rt.h" +#include "cpp_common/base_graph.hpp" #include "cpp_common/pgdata_getters.hpp" #include "cpp_common/utilities.hpp" #include "cpp_common/to_postgres.hpp" @@ -45,12 +46,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "coloring/bipartite.hpp" #include "coloring/edgeColoring.hpp" #include "coloring/sequentialVertexColoring.hpp" +#include "components/components.hpp" +#include "components/makeConnected.hpp" namespace pgrouting { namespace drivers { void do_coloring( const std::string &edges_sql, + bool directed, Which which, @@ -70,11 +74,18 @@ void do_coloring( } using pgrouting::pgget::get_edges; + using pgrouting::to_postgres::get_tuples; + + using pgrouting::DirectedGraph; using pgrouting::UndirectedGraph; using pgrouting::functions::edgeColoring; using pgrouting::functions::sequentialVertexColoring; using pgrouting::functions::pgr_bipartite; + using pgrouting::algorithms::biconnectedComponents; + using pgrouting::algorithms::connectedComponents; + using pgrouting::algorithms::strongComponents; + using pgrouting::functions::makeConnected; hint = edges_sql; auto edges = get_edges(edges_sql, true, false); @@ -88,37 +99,63 @@ void do_coloring( hint = ""; UndirectedGraph undigraph; - undigraph.insert_edges(edges); + DirectedGraph digraph; std::vector results; - - switch (which) { - case EDGECOLORING: - results = edgeColoring(undigraph); - break; - case BIPARTITE: - results = pgr_bipartite(undigraph); - break; - case SEQUENTIAL: - results = sequentialVertexColoring(undigraph); - break; - default: - err << "Unknown coloring function " << get_name(which); - return; + std::vector> component_results; + + if (directed) { + digraph.insert_edges(edges); + switch (which) { + case STRONGCOMPONENTS: + component_results = strongComponents(digraph); + break; + default: + err << __FILE_NAME__ << ": Unknown function with name '" << get_name(which) + << "' for directed graph"; + return; + } + } else { + undigraph.insert_edges(edges); + + switch (which) { + case EDGECOLORING: + results = edgeColoring(undigraph); + break; + case BIPARTITE: + results = pgr_bipartite(undigraph); + break; + case SEQUENTIAL: + results = sequentialVertexColoring(undigraph); + break; + case BICONNECTEDCOMPONENTS: + component_results = biconnectedComponents(undigraph); + break; + case MAKECONNECTED: + { + results = makeConnected(undigraph); + break; + } + case CONNECTEDCOMPONENTS: + component_results = connectedComponents(undigraph); + break; + default: + err << __FILE_NAME__ << ": Unknown function with name '" << get_name(which) + << "' for undirected graph"; + return; + } } - auto count = results.size(); + if (!results.empty()) { + return_count = get_tuples(results, return_tuples); + } else if (!component_results.empty()) { + return_count = get_tuples(component_results, return_tuples); + } - if (count == 0) { + if (return_count == 0) { log << "No results found"; return; } - - return_tuples = pgr_alloc(count, return_tuples); - for (size_t i = 0; i < count; i++) { - return_tuples[i] = results[i]; - } - return_count = count; } catch (AssertFailedException &except) { err << except.what(); } catch (const std::pair& ex) { diff --git a/src/coloring/coloring_process.cpp b/src/coloring/coloring_process.cpp index 1912a27c34..7ea716adfc 100644 --- a/src/coloring/coloring_process.cpp +++ b/src/coloring/coloring_process.cpp @@ -48,6 +48,7 @@ extern "C" { void pgr_process_coloring( const char* edges_sql, + bool directed, enum Which which, II_t_rt **result_tuples, @@ -65,6 +66,7 @@ void pgr_process_coloring( clock_t start_t = clock(); pgrouting::drivers::do_coloring( edges_sql? edges_sql : "", + directed, which, (*result_tuples), (*result_count), diff --git a/src/coloring/edgeColoring.c b/src/coloring/edgeColoring.c index 841d93db0d..fe62d59010 100644 --- a/src/coloring/edgeColoring.c +++ b/src/coloring/edgeColoring.c @@ -27,25 +27,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ - #include #include "c_common/postgres_connection.h" - -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" #include "c_types/ii_t_rt.h" #include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_edgecoloring(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_edgecoloring); - PGDLLEXPORT Datum _pgr_edgecoloring(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; - TupleDesc tuple_desc; + TupleDesc tuple_desc; + II_t_rt *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; @@ -54,13 +49,13 @@ PGDLLEXPORT Datum _pgr_edgecoloring(PG_FUNCTION_ARGS) { pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, EDGECOLORING, &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) { @@ -74,22 +69,22 @@ PGDLLEXPORT Datum _pgr_edgecoloring(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (II_t_rt*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (II_t_rt*) funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { + if (call_cntr < funcctx->max_calls) { HeapTuple tuple; Datum result; Datum *values; bool *nulls; - size_t call_cntr = funcctx->call_cntr; - size_t numb = 2; - values =(Datum *)palloc(numb * sizeof(Datum)); - nulls = palloc(numb * sizeof(bool)); + size_t num = 2; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < numb; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } diff --git a/src/coloring/sequentialVertexColoring.c b/src/coloring/sequentialVertexColoring.c index 97a2bfa0df..8ea26c39d8 100644 --- a/src/coloring/sequentialVertexColoring.c +++ b/src/coloring/sequentialVertexColoring.c @@ -27,25 +27,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ - #include #include "c_common/postgres_connection.h" - -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" #include "c_types/ii_t_rt.h" #include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_sequentialvertexcoloring(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_sequentialvertexcoloring); - PGDLLEXPORT Datum _pgr_sequentialvertexcoloring(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; - TupleDesc tuple_desc; + TupleDesc tuple_desc; + II_t_rt *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; @@ -54,13 +49,13 @@ PGDLLEXPORT Datum _pgr_sequentialvertexcoloring(PG_FUNCTION_ARGS) { pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, SEQUENTIAL, &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) { @@ -74,22 +69,22 @@ PGDLLEXPORT Datum _pgr_sequentialvertexcoloring(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (II_t_rt*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (II_t_rt*) funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { + if (call_cntr < funcctx->max_calls) { HeapTuple tuple; Datum result; Datum *values; bool *nulls; - size_t call_cntr = funcctx->call_cntr; - size_t numb = 2; - values =(Datum *)palloc(numb * sizeof(Datum)); - nulls = palloc(numb * sizeof(bool)); + size_t num = 2; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < numb; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } diff --git a/src/components/CMakeLists.txt b/src/components/CMakeLists.txt index 82a08002fe..d35617e69c 100644 --- a/src/components/CMakeLists.txt +++ b/src/components/CMakeLists.txt @@ -3,17 +3,12 @@ # License: GPL-2 See https://github.com/pgRouting/pgrouting/blob/main/LICENSE ADD_LIBRARY(components OBJECT connectedComponents.c - strongComponents.c - biconnectedComponents.c + strongComponents.c + biconnectedComponents.c articulationPoints.c bridges.c makeConnected.c - makeConnected_driver.cpp - componentsResult.cpp components.cpp - connectedComponents_driver.cpp - strongComponents_driver.cpp - biconnectedComponents_driver.cpp - articulationPoints_driver.cpp - bridges_driver.cpp) + makeConnected.cpp +) diff --git a/src/components/articulationPoints.c b/src/components/articulationPoints.c index 7f1e37246c..7cf27faee3 100644 --- a/src/components/articulationPoints.c +++ b/src/components/articulationPoints.c @@ -9,7 +9,6 @@ Function's developer: Copyright (c) 2017 Maoguang Wang Mail: xjtumg1007@gmail.com - ------ This program is free software; you can redistribute it and/or modify @@ -28,77 +27,34 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -/** @file articulationPoints.c */ - #include #include "c_common/postgres_connection.h" - - -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" - -#include "drivers/components/articulationPoints_driver.h" +#include "process/ordering_process.h" PGDLLEXPORT Datum _pgr_articulationpoints(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_articulationpoints); - -static -void -process( - char* edges_sql, - int64_t **result_tuples, - size_t *result_count) { - pgr_SPI_connect(); - char* log_msg = NULL; - char* notice_msg = NULL; - char* err_msg = NULL; - - (*result_tuples) = NULL; - (*result_count) = 0; - - clock_t start_t = clock(); - pgr_do_articulationPoints( - edges_sql, - - result_tuples, - result_count, - &log_msg, - ¬ice_msg, - &err_msg); - time_msg(" processing pgr_articulationPoints", start_t, clock()); - - if (err_msg) { - if (*result_tuples) pfree(*result_tuples); - (*result_count) = 0; - } - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} - PGDLLEXPORT Datum _pgr_articulationpoints(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; int64_t *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - - process( + pgr_process_ordering( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, + + ARTICULATIONPOINTS, &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) { @@ -112,28 +68,27 @@ PGDLLEXPORT Datum _pgr_articulationpoints(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (int64_t*) funcctx->user_fctx; - - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; - - - values = palloc(2 * sizeof(Datum)); - nulls = palloc(2 * sizeof(bool)); + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; + size_t num = 2; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < 2; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int32GetDatum((int32_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr]); + values[0] = Int32GetDatum(-1); + values[1] = Int64GetDatum(result_tuples[call_cntr]); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/components/articulationPoints_driver.cpp b/src/components/articulationPoints_driver.cpp deleted file mode 100644 index 6add378921..0000000000 --- a/src/components/articulationPoints_driver.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/*PGR-GNU***************************************************************** -File: articulationPoints_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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/components/articulationPoints_driver.h" - -#include -#include -#include -#include - -#include "components/components.hpp" - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" -#include "cpp_common/base_graph.hpp" - - -void -pgr_do_articulationPoints( - const char *edges_sql, - - int64_t **return_tuples, - size_t *return_count, - char ** log_msg, - char ** notice_msg, - char ** err_msg) { - using pgrouting::pgr_alloc; - using pgrouting::to_pg_msg; - using pgrouting::pgr_free; - using pgrouting::pgget::get_edges; - - std::ostringstream log; - std::ostringstream err; - std::ostringstream notice; - const char *hint = nullptr; - - try { - pgassert(!(*log_msg)); - pgassert(!(*notice_msg)); - pgassert(!(*err_msg)); - pgassert(!(*return_tuples)); - pgassert(*return_count == 0); - - hint = edges_sql; - auto edges = get_edges(std::string(edges_sql), true, false); - if (edges.empty()) { - *notice_msg = to_pg_msg("No edges found"); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - return; - } - hint = nullptr; - - pgrouting::UndirectedGraph undigraph; - undigraph.insert_edges(edges); - auto results(pgrouting::algorithms::articulationPoints(undigraph)); - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << "No paths found between start_vid and end_vid vertices"; - return; - } - - (*return_tuples) = pgr_alloc(count, (*return_tuples)); - size_t i = 0; - for (const auto vertex : results) { - *((*return_tuples) + i) = vertex; - ++i; - } - - (*return_count) = count; - - pgassert(*err_msg == NULL); - *log_msg = to_pg_msg(log); - *notice_msg = to_pg_msg(notice); - } catch (AssertFailedException &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch (const std::string &ex) { - *err_msg = to_pg_msg(ex); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - } catch (std::exception &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch(...) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << "Caught unknown exception!"; - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } -} - diff --git a/src/components/biconnectedComponents.c b/src/components/biconnectedComponents.c index f5187320cc..f3253b89fe 100644 --- a/src/components/biconnectedComponents.c +++ b/src/components/biconnectedComponents.c @@ -9,7 +9,6 @@ Function's developer: Copyright (c) 2017 Maoguang Wang Mail: xjtumg1007@gmail.com - ------ This program is free software; you can redistribute it and/or modify @@ -28,79 +27,35 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -/** @file biconnectedComponents.c */ - #include #include "c_common/postgres_connection.h" - - #include "c_types/ii_t_rt.h" -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" - -#include "drivers/components/biconnectedComponents_driver.h" +#include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_biconnectedcomponents(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_biconnectedcomponents); - -static -void -process( - char* edges_sql, - II_t_rt **result_tuples, - size_t *result_count) { - pgr_SPI_connect(); - char* log_msg = NULL; - char* notice_msg = NULL; - char* err_msg = NULL; - - (*result_tuples) = NULL; - (*result_count) = 0; - - clock_t start_t = clock(); - pgr_do_biconnectedComponents( - edges_sql, - - result_tuples, - result_count, - &log_msg, - ¬ice_msg, - &err_msg); - - time_msg(" processing pgr_biconnectedComponents", start_t, clock()); - - if (err_msg) { - if (*result_tuples) pfree(*result_tuples); - (*result_count) = 0; - } - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} - PGDLLEXPORT Datum _pgr_biconnectedcomponents(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; II_t_rt *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - - process( + pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, + + BICONNECTEDCOMPONENTS, &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) { @@ -114,28 +69,28 @@ PGDLLEXPORT Datum _pgr_biconnectedcomponents(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (II_t_rt*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (II_t_rt*) funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; - - size_t numb = 3; - values = palloc(numb * sizeof(Datum)); - nulls = palloc(numb * sizeof(bool)); + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; + size_t num = 3; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < numb; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum((int64_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].d2); - values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].d1); + values[0] = UInt64GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr].d2); + values[2] = Int64GetDatum(result_tuples[call_cntr].d1); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); @@ -144,4 +99,3 @@ PGDLLEXPORT Datum _pgr_biconnectedcomponents(PG_FUNCTION_ARGS) { SRF_RETURN_DONE(funcctx); } } - diff --git a/src/components/biconnectedComponents_driver.cpp b/src/components/biconnectedComponents_driver.cpp deleted file mode 100644 index e1e4ba441f..0000000000 --- a/src/components/biconnectedComponents_driver.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/*PGR-GNU***************************************************************** -File: biconnectedComponents_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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/components/biconnectedComponents_driver.h" - -#include -#include -#include -#include - -#include "components/components.hpp" - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" - -#include "cpp_common/base_graph.hpp" - - -void -pgr_do_biconnectedComponents( - const char *edges_sql, - - II_t_rt **return_tuples, - size_t *return_count, - char ** log_msg, - char ** notice_msg, - char ** err_msg) { - using pgrouting::pgr_alloc; - using pgrouting::to_pg_msg; - using pgrouting::pgr_free; - using pgrouting::pgget::get_edges; - - std::ostringstream log; - std::ostringstream err; - std::ostringstream notice; - const char *hint = nullptr; - - try { - pgassert(!(*log_msg)); - pgassert(!(*notice_msg)); - pgassert(!(*err_msg)); - pgassert(!(*return_tuples)); - pgassert(*return_count == 0); - - hint = edges_sql; - auto edges = get_edges(std::string(edges_sql), true, false); - if (edges.empty()) { - *notice_msg = to_pg_msg("No edges found"); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - return; - } - hint = nullptr; - - pgrouting::UndirectedGraph undigraph; - undigraph.insert_edges(edges); - auto results(pgrouting::algorithms::biconnectedComponents(undigraph)); - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << - "No paths found between start_vid and end_vid vertices"; - return; - } - - (*return_tuples) = pgr_alloc(count, (*return_tuples)); - for (size_t i = 0; i < count; i++) { - *((*return_tuples) + i) = results[i]; - } - (*return_count) = count; - - pgassert(*err_msg == NULL); - *log_msg = to_pg_msg(log); - *notice_msg = to_pg_msg(notice); - } catch (AssertFailedException &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch (const std::string &ex) { - *err_msg = to_pg_msg(ex); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - } catch (std::exception &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch(...) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << "Caught unknown exception!"; - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } -} - diff --git a/src/components/bridges.c b/src/components/bridges.c index 4c422aa74c..32d3e5c9e0 100644 --- a/src/components/bridges.c +++ b/src/components/bridges.c @@ -9,7 +9,6 @@ Function's developer: Copyright (c) 2017 Maoguang Wang Mail: xjtumg1007@gmail.com - ------ This program is free software; you can redistribute it and/or modify @@ -28,76 +27,34 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -/** @file bridges.c */ - #include #include "c_common/postgres_connection.h" - - -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" - -#include "drivers/components/bridges_driver.h" +#include "process/ordering_process.h" PGDLLEXPORT Datum _pgr_bridges(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_bridges); - -static -void -process( - char* edges_sql, - int64_t **result_tuples, - size_t *result_count) { - pgr_SPI_connect(); - char* log_msg = NULL; - char* notice_msg = NULL; - char* err_msg = NULL; - - (*result_tuples) = NULL; - (*result_count) = 0; - - clock_t start_t = clock(); - pgr_do_bridges( - edges_sql, - - result_tuples, - result_count, - &log_msg, - ¬ice_msg, - &err_msg); - time_msg(" processing pgr_bridges", start_t, clock()); - - if (err_msg) { - if (*result_tuples) pfree(*result_tuples); - (*result_count) = 0; - } - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} - PGDLLEXPORT Datum _pgr_bridges(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; int64_t *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - process( + pgr_process_ordering( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, + + BRIDGES, &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) { @@ -111,28 +68,27 @@ PGDLLEXPORT Datum _pgr_bridges(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (int64_t*) funcctx->user_fctx; - - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; - - - values = palloc(2 * sizeof(Datum)); - nulls = palloc(2 * sizeof(bool)); + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = funcctx->user_fctx; + uint32_t call_cntr = (uint32_t)funcctx->call_cntr; + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; + size_t num = 2; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < 2; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int32GetDatum((int32_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr]); + values[0] = UInt32GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr]); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); @@ -141,4 +97,3 @@ PGDLLEXPORT Datum _pgr_bridges(PG_FUNCTION_ARGS) { SRF_RETURN_DONE(funcctx); } } - diff --git a/src/components/bridges_driver.cpp b/src/components/bridges_driver.cpp deleted file mode 100644 index 234f008f80..0000000000 --- a/src/components/bridges_driver.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/*PGR-GNU***************************************************************** -File: bridges_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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/components/bridges_driver.h" - -#include -#include -#include -#include - -#include "components/components.hpp" - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" -#include "cpp_common/base_graph.hpp" - - -void -pgr_do_bridges( - const char *edges_sql, - int64_t **return_tuples, - size_t *return_count, - char ** log_msg, - char ** notice_msg, - char ** err_msg) { - using pgrouting::pgr_alloc; - using pgrouting::to_pg_msg; - using pgrouting::pgr_free; - using pgrouting::pgget::get_edges; - - std::ostringstream log; - std::ostringstream err; - std::ostringstream notice; - const char *hint = nullptr; - - try { - pgassert(!(*log_msg)); - pgassert(!(*notice_msg)); - pgassert(!(*err_msg)); - pgassert(!(*return_tuples)); - pgassert(*return_count == 0); - - hint = edges_sql; - auto edges = get_edges(std::string(edges_sql), true, false); - if (edges.empty()) { - *notice_msg = to_pg_msg("No edges found"); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - return; - } - hint = nullptr; - - pgrouting::UndirectedGraph undigraph; - undigraph.insert_edges(edges); - auto results = pgrouting::algorithms::bridges(undigraph); - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << "No paths found between start_vid and end_vid vertices"; - return; - } - - (*return_tuples) = pgr_alloc(count, (*return_tuples)); - size_t i = 0; - for (const auto edge : results) { - *((*return_tuples) + i) = edge; - ++i; - } - (*return_count) = count; - - pgassert(*err_msg == NULL); - *log_msg = to_pg_msg(log); - *notice_msg = to_pg_msg(notice); - } catch (AssertFailedException &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch (const std::string &ex) { - *err_msg = to_pg_msg(ex); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - } catch (std::exception &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch(...) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << "Caught unknown exception!"; - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } -} - diff --git a/src/components/components.cpp b/src/components/components.cpp index e90f9dcbd7..fcdb6362e8 100644 --- a/src/components/components.cpp +++ b/src/components/components.cpp @@ -44,14 +44,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. namespace pgrouting { namespace algorithms { -std::vector -pgr_connectedComponents(pgrouting::UndirectedGraph &graph) { +std::vector> +connectedComponents(pgrouting::UndirectedGraph &graph) { if (boost::num_vertices(graph.graph) == 0) return {}; typedef pgrouting::UndirectedGraph::V V; - // perform the algorithm + std::vector components(boost::num_vertices(graph.graph)); size_t num_comps = 0; - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ + CHECK_FOR_INTERRUPTS(); try { num_comps = boost::connected_components(graph.graph, components.data()); @@ -65,17 +65,18 @@ pgr_connectedComponents(pgrouting::UndirectedGraph &graph) { results[components[vd]].push_back(graph[vd].id); } - return detail::componentsResult(results); + return results; } //! Strongly Connected Components Vertex Version -std::vector strongComponents(pgrouting::DirectedGraph &graph) { - typedef pgrouting::UndirectedGraph::V V; - // perform the algorithm +std::vector> +strongComponents(pgrouting::DirectedGraph &graph) { + typedef pgrouting::DirectedGraph::V V; + std::vector components(num_vertices(graph.graph)); size_t num_comps = 0; - /* abort in case of an interruption occurs (e.g. the query is being cancelled) - */ + + CHECK_FOR_INTERRUPTS(); try { num_comps = boost::strong_components( @@ -86,22 +87,23 @@ std::vector strongComponents(pgrouting::DirectedGraph &graph) { throw; } - // get the results + std::vector> results(num_comps); for (auto vd : boost::make_iterator_range(vertices(graph.graph))) { results[components[vd]].push_back(graph[vd].id); } - return detail::componentsResult(results); + return results; } //! Biconnected Components -std::vector biconnectedComponents(pgrouting::UndirectedGraph &graph) { +std::vector> +biconnectedComponents(pgrouting::UndirectedGraph &graph) { using G = pgrouting::UndirectedGraph; using E = G::E; using Edge_map = std::map; - // perform the algorithm + Edge_map bicmp_map; boost::associative_property_map bimap(bicmp_map); size_t num_comps = 0; @@ -117,17 +119,15 @@ std::vector biconnectedComponents(pgrouting::UndirectedGraph &graph) { results[bimap[ed]].push_back(graph[ed].id); } - return detail::componentsResult(results); + return results; } Identifiers articulationPoints(pgrouting::UndirectedGraph &graph) { using G = pgrouting::UndirectedGraph; using V = G::V; - /* abort in case of an interruption occurs (e.g. the query is being cancelled) - */ + CHECK_FOR_INTERRUPTS(); - // perform the algorithm std::vector art_points; try { #ifndef __clang_analyzer__ @@ -167,14 +167,14 @@ Identifiers bridges(pgrouting::UndirectedGraph &graph) { if (boost::num_vertices(graph.graph) == 0) return bridge_edges; std::vector components(boost::num_vertices(graph.graph)); size_t ini_comps = 0; - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ + CHECK_FOR_INTERRUPTS(); try { ini_comps = boost::connected_components(graph.graph, components.data()); } catch (...) { throw; } - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ + CHECK_FOR_INTERRUPTS(); std::vector art_points; try { diff --git a/src/components/componentsResult.cpp b/src/components/componentsResult.cpp deleted file mode 100644 index 195936fb13..0000000000 --- a/src/components/componentsResult.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/*PGR-GNU***************************************************************** -File: componentsResult.cpp - -Copyright (c) 2019-2026 pgRouting developers -Mail: project@pgrouting.org - -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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 "components/componentsResult.hpp" - -#include -#include - -namespace pgrouting { -namespace algorithms { - -namespace detail { - -std::vector -componentsResult( - std::vector< std::vector< int64_t > > &components) { - // sort identifier - for (auto &component : components) { - std::sort(component.begin(), component.end()); - } - sort(components.begin(), components.end()); - - // generate results - std::vector< II_t_rt > results; - for (const auto& component : components) { - auto component_id = component[0]; - for (const auto edge_id : component) { - results.push_back({edge_id, component_id}); - } - } - return results; -} - -} // namespace detail - -} // namespace algorithms -} // namespace pgrouting diff --git a/src/components/connectedComponents.c b/src/components/connectedComponents.c index b6123e0d15..9384ee5ec4 100644 --- a/src/components/connectedComponents.c +++ b/src/components/connectedComponents.c @@ -9,7 +9,6 @@ Function's developer: Copyright (c) 2017 Maoguang Wang Mail: xjtumg1007@gmail.com - ------ This program is free software; you can redistribute it and/or modify @@ -28,79 +27,35 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -/** @file connectedComponents.c */ - #include #include "c_common/postgres_connection.h" - - #include "c_types/ii_t_rt.h" -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" - -#include "drivers/components/connectedComponents_driver.h" +#include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_connectedcomponents(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_connectedcomponents); - -static -void -process( - char* edges_sql, - II_t_rt **result_tuples, - size_t *result_count) { - pgr_SPI_connect(); - char* log_msg = NULL; - char* notice_msg = NULL; - char* err_msg = NULL; - - (*result_tuples) = NULL; - (*result_count) = 0; - - clock_t start_t = clock(); - pgr_do_connectedComponents( - edges_sql, - - result_tuples, - result_count, - &log_msg, - ¬ice_msg, - &err_msg); - - time_msg(" processing pgr_connectedComponents", start_t, clock()); - - if (err_msg) { - if (*result_tuples) pfree(*result_tuples); - (*result_count) = 0; - } - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} - PGDLLEXPORT Datum _pgr_connectedcomponents(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; II_t_rt *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - - process( + pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, + + CONNECTEDCOMPONENTS, &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) { @@ -114,29 +69,28 @@ PGDLLEXPORT Datum _pgr_connectedcomponents(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (II_t_rt*) funcctx->user_fctx; - - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (II_t_rt*) funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; - size_t numb = 3; - values = palloc(numb * sizeof(Datum)); - nulls = palloc(numb * sizeof(bool)); - + size_t num = 3; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < numb; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum((int64_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].d2); - values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].d1); + values[0] = UInt64GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr].d2); + values[2] = Int64GetDatum(result_tuples[call_cntr].d1); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); @@ -145,4 +99,3 @@ PGDLLEXPORT Datum _pgr_connectedcomponents(PG_FUNCTION_ARGS) { SRF_RETURN_DONE(funcctx); } } - diff --git a/src/components/connectedComponents_driver.cpp b/src/components/connectedComponents_driver.cpp deleted file mode 100644 index 6a12ae7c5c..0000000000 --- a/src/components/connectedComponents_driver.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/*PGR-GNU***************************************************************** -File: connectedComponents_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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/components/connectedComponents_driver.h" - -#include -#include -#include -#include - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" -#include "cpp_common/base_graph.hpp" - -#include "components/components.hpp" - - -void -pgr_do_connectedComponents( - const char *edges_sql, - - II_t_rt **return_tuples, - size_t *return_count, - char ** log_msg, - char ** notice_msg, - char ** err_msg) { - using pgrouting::pgr_alloc; - using pgrouting::to_pg_msg; - using pgrouting::pgr_free; - using pgrouting::pgget::get_edges; - - std::ostringstream log; - std::ostringstream err; - std::ostringstream notice; - const char *hint = nullptr; - - try { - pgassert(!(*log_msg)); - pgassert(!(*notice_msg)); - pgassert(!(*err_msg)); - pgassert(!(*return_tuples)); - pgassert(*return_count == 0); - - hint = edges_sql; - auto edges = get_edges(std::string(edges_sql), true, false); - if (edges.empty()) { - *notice_msg = to_pg_msg("No edges found"); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - return; - } - hint = nullptr; - - pgrouting::UndirectedGraph undigraph; - undigraph.insert_edges(edges); - auto results(pgrouting::algorithms::pgr_connectedComponents(undigraph)); - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << "No paths found between start_vid and end_vid vertices"; - return; - } - - (*return_tuples) = pgr_alloc(count, (*return_tuples)); - for (size_t i = 0; i < count; i++) { - *((*return_tuples) + i) = results[i]; - } - (*return_count) = count; - - pgassert(*err_msg == NULL); - *log_msg = to_pg_msg(log); - *notice_msg = to_pg_msg(notice); - } catch (AssertFailedException &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch (const std::string &ex) { - *err_msg = to_pg_msg(ex); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - } catch (std::exception &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch(...) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << "Caught unknown exception!"; - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } -} - diff --git a/src/components/makeConnected.c b/src/components/makeConnected.c index f30c4f6c05..3bcc295945 100644 --- a/src/components/makeConnected.c +++ b/src/components/makeConnected.c @@ -9,7 +9,6 @@ Function's developer: Copyright (c) 2020 Himanshu Raj Mail: raj.himanshu2@gmail.com - ------ This program is free software; you can redistribute it and/or modify @@ -30,111 +29,68 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include "c_common/postgres_connection.h" - #include "c_types/ii_t_rt.h" -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" - +#include "process/coloring_process.h" -#include "drivers/components/makeConnected_driver.h" PGDLLEXPORT Datum _pgr_makeconnected(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_makeconnected); -static void -process( - char *edges_sql, - - II_t_rt **result_tuples, - size_t *result_count) { - pgr_SPI_connect(); - char* log_msg = NULL; - char* notice_msg = NULL; - char* err_msg = NULL; - - (*result_tuples) = NULL; - (*result_count) = 0; - - clock_t start_t = clock(); - pgr_do_makeConnected( - edges_sql, - - result_tuples, - result_count, - - &log_msg, - ¬ice_msg, - &err_msg); - time_msg(" processing pgr_makeConnected", start_t, clock()); - - if (err_msg) { - if (*result_tuples) pfree(*result_tuples); - (*result_count) = 0; - } - - pgr_global_report(&log_msg, ¬ice_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_makeconnected(PG_FUNCTION_ARGS) { - FuncCallContext *funcctx; - TupleDesc tuple_desc; + FuncCallContext *funcctx; + TupleDesc tuple_desc; II_t_rt *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { - MemoryContext oldcontext; + MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - PGR_DBG("Calling process"); - process( - text_to_cstring(PG_GETARG_TEXT_P(0)), - &result_tuples, - &result_count); + pgr_process_coloring( + text_to_cstring(PG_GETARG_TEXT_P(0)), + false, - funcctx->max_calls = result_count; + MAKECONNECTED, + &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) { + 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"))); + "that cannot accept type record"))); } funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (II_t_rt *)funcctx->user_fctx; - - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool *nulls; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (II_t_rt*) funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - size_t numb = 3; - values = palloc(numb * sizeof(Datum)); - nulls = palloc(numb * sizeof(bool)); + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; + size_t num = 3; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < numb; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int32GetDatum((int32_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].d1); - values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].d2); + values[0] = UInt64GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr].d1); + values[2] = Int64GetDatum(result_tuples[call_cntr].d2); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/components/makeConnected.cpp b/src/components/makeConnected.cpp new file mode 100644 index 0000000000..b0f6b95236 --- /dev/null +++ b/src/components/makeConnected.cpp @@ -0,0 +1,90 @@ +/*PGR-GNU***************************************************************** +File: makeConnected.cpp + +Copyright (c) 2015-2026 pgRouting developers +Mail: project@pgrouting.org + +Copyright (c) 2020 Himanshu Raj +Mail: raj.himanshu2@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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "c_types/ii_t_rt.h" +#include "cpp_common/messages.hpp" +#include "cpp_common/base_graph.hpp" +#include "cpp_common/interruption.hpp" + +#include "components/makeConnected.hpp" + +namespace { + +class UpdateNewEdges { + public: + using G = typename pgrouting::UndirectedGraph::B_G; + using V = typename pgrouting::UndirectedGraph::V; + + std::vector &new_edges; + + explicit UpdateNewEdges(std::vector& edges_out) + : new_edges(edges_out) {} + + void visit_vertex_pair(V u, V v, G& g) { + boost::add_edge(u, v, g); + new_edges.push_back({g[u].id, g[v].id}); + } +}; + + +} // namespace + +namespace pgrouting { +namespace functions { + +std::vector +makeConnected(pgrouting::UndirectedGraph &graph) { + std::vector results; + UpdateNewEdges visitor(results); + + /* map which store the indices with their nodes. */ + auto index_map = boost::get(boost::vertex_index, graph.graph); + + CHECK_FOR_INTERRUPTS(); + try { + boost::make_connected(graph.graph, index_map, visitor); + } catch (...) { + throw; + } + + return results; +} + +} // namespace functions +} // namespace pgrouting diff --git a/src/components/makeConnected_driver.cpp b/src/components/makeConnected_driver.cpp deleted file mode 100644 index eb265cdca7..0000000000 --- a/src/components/makeConnected_driver.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*PGR-GNU***************************************************************** -File: makeConnected_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2020 Himanshu Raj -Mail: raj.himanshu2@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/components/makeConnected_driver.h" - -#include -#include -#include - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" - -#include "components/makeConnected.hpp" -#include "cpp_common/base_graph.hpp" - -void -pgr_do_makeConnected( - const char *edges_sql, - - - II_t_rt **return_tuples, - size_t *return_count, - char ** log_msg, - char ** notice_msg, - char ** err_msg) { - using pgrouting::pgr_alloc; - using pgrouting::to_pg_msg; - using pgrouting::pgr_free; - using pgrouting::pgget::get_edges; - - std::ostringstream log; - std::ostringstream err; - std::ostringstream notice; - const char *hint = nullptr; - - try { - pgassert(!(*log_msg)); - pgassert(!(*notice_msg)); - pgassert(!(*err_msg)); - pgassert(!(*return_tuples)); - pgassert(*return_count == 0); - - std::vector results; - std::string logstr; - - hint = edges_sql; - auto edges = get_edges(std::string(edges_sql), true, false); - if (edges.empty()) { - *notice_msg = to_pg_msg("No edges found"); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - return; - } - hint = nullptr; - - pgrouting::UndirectedGraph undigraph; - undigraph.insert_edges(edges); - pgrouting::functions::Pgr_makeConnected fn_makeConnected; - results = fn_makeConnected.makeConnected(undigraph); - logstr += fn_makeConnected.get_log(); - log << logstr; - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << - "No Vertices"; - *log_msg = to_pg_msg(notice); - return; - } - - (*return_tuples) = pgr_alloc(count, (*return_tuples)); - log << "\nConverting a set of traversals into the tuples"; - for (size_t i = 0; i < count; i++) { - *((*return_tuples) + i) = results[i]; - } - (*return_count) = count; - - pgassert(*err_msg == NULL); - *log_msg = to_pg_msg(log); - *notice_msg = to_pg_msg(notice); - } catch (AssertFailedException &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch (const std::string &ex) { - *err_msg = to_pg_msg(ex); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - } catch (std::exception &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch(...) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << "Caught unknown exception!"; - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } -} diff --git a/src/components/strongComponents.c b/src/components/strongComponents.c index fd2bd98d03..7dc71b2e16 100644 --- a/src/components/strongComponents.c +++ b/src/components/strongComponents.c @@ -9,7 +9,6 @@ Function's developer: Copyright (c) 2017 Maoguang Wang Mail: xjtumg1007@gmail.com - ------ This program is free software; you can redistribute it and/or modify @@ -28,79 +27,35 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -/** @file strongComponents.c */ - #include #include "c_common/postgres_connection.h" - - #include "c_types/ii_t_rt.h" -#include "c_common/debug_macro.h" -#include "c_common/e_report.h" -#include "c_common/time_msg.h" - -#include "drivers/components/strongComponents_driver.h" +#include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_strongcomponents(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_strongcomponents); - -static -void -process( - char* edges_sql, - II_t_rt **result_tuples, - size_t *result_count) { - pgr_SPI_connect(); - char* log_msg = NULL; - char* notice_msg = NULL; - char* err_msg = NULL; - - (*result_tuples) = NULL; - (*result_count) = 0; - - clock_t start_t = clock(); - pgr_do_strongComponents( - edges_sql, - - result_tuples, - result_count, - &log_msg, - ¬ice_msg, - &err_msg); - - time_msg(" processing pgr_strongComponents", start_t, clock()); - - if (err_msg) { - if (*result_tuples) pfree(*result_tuples); - (*result_count) = 0; - } - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} - PGDLLEXPORT Datum _pgr_strongcomponents(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; II_t_rt *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - - process( + pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + true, + + STRONGCOMPONENTS, &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) { @@ -114,28 +69,28 @@ PGDLLEXPORT Datum _pgr_strongcomponents(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (II_t_rt*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (II_t_rt*) funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; - - size_t numb = 3; - values = palloc(numb * sizeof(Datum)); - nulls = palloc(numb * sizeof(bool)); + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; + size_t num = 3; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); size_t i; - for (i = 0; i < numb; ++i) { + for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum((int64_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].d2); - values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].d1); + values[0] = UInt64GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr].d2); + values[2] = Int64GetDatum(result_tuples[call_cntr].d1); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); @@ -144,4 +99,3 @@ PGDLLEXPORT Datum _pgr_strongcomponents(PG_FUNCTION_ARGS) { SRF_RETURN_DONE(funcctx); } } - diff --git a/src/components/strongComponents_driver.cpp b/src/components/strongComponents_driver.cpp deleted file mode 100644 index 045dcf772a..0000000000 --- a/src/components/strongComponents_driver.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/*PGR-GNU***************************************************************** -File: strongComponents_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2017 Maoguang Wang -Mail: xjtumg1007@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/components/strongComponents_driver.h" - -#include -#include -#include -#include - - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" -#include "cpp_common/base_graph.hpp" - -#include "components/components.hpp" - - -void -pgr_do_strongComponents( - const char *edges_sql, - - II_t_rt **return_tuples, - size_t *return_count, - char ** log_msg, - char ** notice_msg, - char ** err_msg) { - using pgrouting::pgr_alloc; - using pgrouting::to_pg_msg; - using pgrouting::pgr_free; - using pgrouting::pgget::get_edges; - - std::ostringstream log; - std::ostringstream err; - std::ostringstream notice; - const char *hint = nullptr; - - try { - pgassert(!(*log_msg)); - pgassert(!(*notice_msg)); - pgassert(!(*err_msg)); - pgassert(!(*return_tuples)); - pgassert(*return_count == 0); - - hint = edges_sql; - auto edges = get_edges(std::string(edges_sql), true, false); - if (edges.empty()) { - *notice_msg = to_pg_msg("No edges found"); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - return; - } - hint = nullptr; - - pgrouting::DirectedGraph digraph; - digraph.insert_edges(edges); - auto results(pgrouting::algorithms::strongComponents(digraph)); - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << "No components found"; - return; - } - - (*return_tuples) = pgr_alloc(count, (*return_tuples)); - for (size_t i = 0; i < count; i++) { - *((*return_tuples) + i) = results[i]; - } - (*return_count) = count; - - pgassert(*err_msg == NULL); - *log_msg = to_pg_msg(log); - *notice_msg = to_pg_msg(notice); - } catch (AssertFailedException &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch (const std::string &ex) { - *err_msg = to_pg_msg(ex); - *log_msg = hint? to_pg_msg(hint) : to_pg_msg(log); - } catch (std::exception &except) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << except.what(); - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } catch(...) { - (*return_tuples) = pgr_free(*return_tuples); - (*return_count) = 0; - err << "Caught unknown exception!"; - *err_msg = to_pg_msg(err); - *log_msg = to_pg_msg(log); - } -} - diff --git a/src/cpp_common/to_postgres.cpp b/src/cpp_common/to_postgres.cpp index 33a6704b58..a8bf58998a 100644 --- a/src/cpp_common/to_postgres.cpp +++ b/src/cpp_common/to_postgres.cpp @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include #include +#include #include "c_types/routes_t.h" #include "c_types/path_rt.h" @@ -226,6 +227,46 @@ get_tuples( return sequence; } +size_t +get_tuples(const std::vector &data, II_t_rt* &tuples) { + pgassert(!tuples); + + auto count = data.size(); + if (count == 0) return 0; + + tuples = pgrouting::pgr_alloc(count, tuples); + + size_t i = 0; + for (const auto &d : data) { + tuples[i++] = d; + } + + return count; +} + +size_t +get_tuples(std::vector> &components, II_t_rt* &tuples) { + size_t count = 0; + for (auto &component : components) { + count += component.size(); + std::sort(component.begin(), component.end()); + } + + std::sort(components.begin(), components.end()); + + tuples = pgrouting::pgr_alloc(count, tuples); + + size_t i = 0; + for (const auto& component : components) { + auto component_id = component[0]; + for (const auto edge_id : component) { + tuples[i++]= {edge_id, component_id}; + } + } + return count; +} + + size_t get_tuples( const std::vector &results, diff --git a/src/cpp_common/utilities.cpp b/src/cpp_common/utilities.cpp index d0d223675e..37695c0975 100644 --- a/src/cpp_common/utilities.cpp +++ b/src/cpp_common/utilities.cpp @@ -104,6 +104,25 @@ get_name(Which which) { case EDMONDSKARP: return "pgr_edmondsKarp"; break; + + case ARTICULATIONPOINTS: + return "pgr_articulationPoints"; + break; + case BRIDGES: + return "pgr_bridges"; + break; + case MAKECONNECTED: + return "pgr_makeConnected"; + break; + case BICONNECTEDCOMPONENTS: + return "pgr_biconnectedComponents"; + break; + case CONNECTEDCOMPONENTS: + return "pgr_connectedComponents"; + break; + case STRONGCOMPONENTS: + return "pgr_strongComponents"; + break; default: return "unknown"; break; diff --git a/src/ordering/cuthillMckeeOrdering.c b/src/ordering/cuthillMckeeOrdering.c index 6d0f035d40..94878efcf2 100644 --- a/src/ordering/cuthillMckeeOrdering.c +++ b/src/ordering/cuthillMckeeOrdering.c @@ -8,7 +8,9 @@ Mail: project@pgrouting.org Function's developer: Copyright (c) 2022 Shobhit Chaurasia Mail: 000shobhitchaurasia@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 @@ -32,23 +34,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. PGDLLEXPORT Datum _pgr_cuthillmckeeordering(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_cuthillmckeeordering); - PGDLLEXPORT Datum _pgr_cuthillmckeeordering(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; int64_t *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - pgr_process_ordering( text_to_cstring(PG_GETARG_TEXT_P(0)), + false, + CUTCHILL, &result_tuples, &result_count); @@ -67,28 +69,27 @@ _pgr_cuthillmckeeordering(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (int64_t*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; size_t num = 2; values = palloc(num * sizeof(Datum)); nulls = palloc(num * sizeof(bool)); - - size_t i; for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum((int64_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr]); + values[0] = UInt64GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr]); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/ordering/kingOrdering.c b/src/ordering/kingOrdering.c index 9c89b1d121..6e53247e84 100644 --- a/src/ordering/kingOrdering.c +++ b/src/ordering/kingOrdering.c @@ -8,7 +8,9 @@ Mail: project@pgrouting.org Function's developer: Copyright (c) 2025 Fan Wu Mail: wifiblack0131 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 @@ -32,24 +34,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. PGDLLEXPORT Datum _pgr_kingordering(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_kingordering); - PGDLLEXPORT Datum _pgr_kingordering(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; int64_t *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - pgr_process_ordering( text_to_cstring(PG_GETARG_TEXT_P(0)), - KING, /*King Ordering*/ + false, + + KING, &result_tuples, &result_count); @@ -67,28 +69,27 @@ _pgr_kingordering(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (int64_t*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; size_t num = 2; values = palloc(num * sizeof(Datum)); nulls = palloc(num * sizeof(bool)); - - size_t i; for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum((int64_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr]); + values[0] = UInt64GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr]); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/ordering/ordering_driver.cpp b/src/ordering/ordering_driver.cpp index c74c2896ff..41dc807d0f 100644 --- a/src/ordering/ordering_driver.cpp +++ b/src/ordering/ordering_driver.cpp @@ -42,26 +42,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "cpp_common/pgdata_getters.hpp" #include "cpp_common/to_postgres.hpp" +#include "cpp_common/utilities.hpp" #include "ordering/sloanOrdering.hpp" #include "ordering/kingOrdering.hpp" #include "ordering/cuthillMckeeOrdering.hpp" #include "ordering/topologicalSort.hpp" +#include "components/components.hpp" -namespace { - -template -void -process(const std::vector &edges, G &graph, Func ordering, - size_t &return_count, - int64_t* &return_tuples) { - using pgrouting::to_postgres::get_vertexId; - graph.insert_edges(edges); - auto results = ordering(graph); - get_vertexId(graph, results, return_count, return_tuples); -} - -} // namespace namespace pgrouting { namespace drivers { @@ -69,6 +57,7 @@ namespace drivers { void do_ordering( const std::string &edges_sql, + bool directed, Which which, int64_t *&return_tuples, @@ -86,6 +75,9 @@ do_ordering( } using pgrouting::pgget::get_edges; + using pgrouting::to_postgres::get_vertexId; + using pgrouting::to_postgres::get_identifiers; + using pgrouting::UndirectedGraph; using pgrouting::DirectedGraph; @@ -93,6 +85,8 @@ do_ordering( using pgrouting::functions::kingOrdering; using pgrouting::functions::cuthillMckeeOrdering; using pgrouting::functions::topologicalSort; + using pgrouting::algorithms::bridges; + using pgrouting::algorithms::articulationPoints; hint = edges_sql; @@ -105,37 +99,80 @@ do_ordering( hint = ""; - auto vertices = which == 0 || which == 2? + /* + * Decide which algorithms needs extract vertices + */ + auto vertices = which == SLOAN || which == KING? pgrouting::extract_vertices(edges) : std::vector(); - UndirectedGraph undigraph = which != TOPOSORT? UndirectedGraph(vertices) : UndirectedGraph(); - DirectedGraph digraph = which == TOPOSORT? DirectedGraph(vertices) : DirectedGraph();; - - - switch (which) { - case SLOAN: - { - process(edges, undigraph, &sloanOrdering, return_count, return_tuples); - break; - } - case CUTCHILL: - { - process(edges, undigraph, &cuthillMckeeOrdering, return_count, return_tuples); - break; - } - case KING: - { - process(edges, undigraph, &kingOrdering, return_count, return_tuples); - break; - } - case TOPOSORT: - { - process(edges, digraph, &topologicalSort, return_count, return_tuples); - break; - } - default: - break; + /* + * Initialize the graphs + * No need to use extract_vertices on directed graph, because + * SLOAN & KING are for undirected graph + */ + UndirectedGraph undigraph = vertices.empty()? UndirectedGraph() : UndirectedGraph(vertices); + DirectedGraph digraph = DirectedGraph(); + + std::vector undi_results; + std::vector di_results; + Identifiers id_results; + + if (directed) { + digraph.insert_edges(edges); + switch (which) { + case TOPOSORT: + { + di_results = topologicalSort(digraph); + break; + } + default: + err << __FILE_NAME__ << ": Unknown function with name '" << get_name(which) + << "' for directed graph"; + return; + } + + } else { + undigraph.insert_edges(edges); + switch (which) { + case SLOAN: + { + undi_results = sloanOrdering(undigraph); + break; + } + case CUTCHILL: + { + undi_results = cuthillMckeeOrdering(undigraph); + break; + } + case KING: + { + undi_results = kingOrdering(undigraph); + break; + } + case ARTICULATIONPOINTS: + { + id_results = articulationPoints(undigraph); + break; + } + case BRIDGES: + { + id_results = bridges(undigraph); + break; + } + default: + err << __FILE_NAME__ << ": Unknown function with name '" << get_name(which) + << "' for undirected graph"; + return; + } + } + + if (!undi_results.empty()) { + get_vertexId(undigraph, undi_results, return_count, return_tuples); + } else if (!di_results.empty()) { + get_vertexId(digraph, di_results, return_count, return_tuples); + } else if (!id_results.empty()) { + return_count = get_identifiers(id_results, return_tuples); } if (return_count == 0) { diff --git a/src/ordering/ordering_process.cpp b/src/ordering/ordering_process.cpp index 22e2190352..243318ef0d 100644 --- a/src/ordering/ordering_process.cpp +++ b/src/ordering/ordering_process.cpp @@ -48,6 +48,7 @@ extern "C" { void pgr_process_ordering( const char* edges_sql, + bool directed, enum Which which, int64_t **result_tuples, size_t *result_count) { @@ -63,11 +64,12 @@ void pgr_process_ordering( clock_t start_t = clock(); pgrouting::drivers::do_ordering( edges_sql? edges_sql : "", + directed, which, (*result_tuples), (*result_count), log, notice, err); - auto name = std::string(" processing ") + pgrouting::get_name(which); + auto name = std::string("PROCESS: processing ") + pgrouting::get_name(which); time_msg(name.c_str(), start_t, clock()); if (!err.str().empty() && (*result_tuples)) { diff --git a/src/ordering/sloanOrdering.c b/src/ordering/sloanOrdering.c index 8c35313550..8f7c426484 100644 --- a/src/ordering/sloanOrdering.c +++ b/src/ordering/sloanOrdering.c @@ -8,7 +8,9 @@ Mail: project@pgrouting.org Developer: Copyright (c) 2025 Bipasha Gayary Mail: bipashagayary 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 @@ -32,24 +34,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. PGDLLEXPORT Datum _pgr_sloanordering(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_sloanordering); - PGDLLEXPORT Datum _pgr_sloanordering(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; int64_t *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - pgr_process_ordering( text_to_cstring(PG_GETARG_TEXT_P(0)), - SLOAN, /* Sloan */ + false, + + SLOAN, &result_tuples, &result_count); @@ -67,28 +69,27 @@ _pgr_sloanordering(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (int64_t*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = funcctx->user_fctx; + uint64_t call_cntr = funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; size_t num = 2; values = palloc(num * sizeof(Datum)); nulls = palloc(num * sizeof(bool)); - - size_t i; for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum((int64_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr]); + values[0] = UInt64GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr]); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/ordering/topologicalSort.c b/src/ordering/topologicalSort.c index 7a07723c1e..7956b0d994 100644 --- a/src/ordering/topologicalSort.c +++ b/src/ordering/topologicalSort.c @@ -40,7 +40,7 @@ _pgr_topologicalsort(PG_FUNCTION_ARGS) { TupleDesc tuple_desc; int64_t *result_tuples = NULL; - size_t result_count = 0; + size_t result_count = 0; if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; @@ -49,6 +49,8 @@ _pgr_topologicalsort(PG_FUNCTION_ARGS) { pgr_process_ordering( text_to_cstring(PG_GETARG_TEXT_P(0)), + true, + TOPOSORT, &result_tuples, &result_count); @@ -67,27 +69,27 @@ _pgr_topologicalsort(PG_FUNCTION_ARGS) { MemoryContextSwitchTo(oldcontext); } - funcctx = SRF_PERCALL_SETUP(); - tuple_desc = funcctx->tuple_desc; - result_tuples = (int64_t*) funcctx->user_fctx; + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = funcctx->user_fctx; + uint32_t call_cntr = (uint32_t)funcctx->call_cntr; - if (funcctx->call_cntr < funcctx->max_calls) { - HeapTuple tuple; - Datum result; - Datum *values; - bool* nulls; + if (call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool *nulls; size_t num = 2; values = palloc(num * sizeof(Datum)); nulls = palloc(num * sizeof(bool)); - size_t i; for (i = 0; i < num; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum((int64_t)funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr]); + values[0] = UInt32GetDatum(call_cntr + 1); + values[1] = Int64GetDatum(result_tuples[call_cntr]); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple);