diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index 3fecc88eb9..afcfbc6f9b 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest strategy: - fail-fast: false + fail-fast: true matrix: boost_minor: [56] old_pgr: [4.0.1, 4.0.0, 3.8.0, 3.7.3, 3.7.2, 3.7.1, 3.7.0, 3.6.3, 3.6.2, 3.6.1, 3.6.0, 3.5.1, 3.5.0, 3.4.2, 3.4.1, 3.4.0, 3.3.5, 3.3.4, 3.3.3, 3.3.2, 3.3.1, 3.3.0, 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.0.6, 3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.2.0, 3.2.1, 3.2.2] diff --git a/NEWS.md b/NEWS.md index 4bf76bb6c6..fcbcd22b67 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,6 +24,18 @@ To see all issues & pull requests closed by this release see the * [#3086](https://github.com/pgRouting/pgrouting/issues/3086): MaxFlow: create and use a process and driver * [#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 an use a process & driver + +**Bug Fixes** + +* [#3101](https://github.com/pgRouting/pgrouting/issues/3101): pgr_edgeColoring not building graph correctly + + +**Summary of changes by function** + +* pgr_edgeColoring + + * Fix the way it builds the graph ## pgRouting 4.0 diff --git a/doc/coloring/pgr_edgeColoring.rst b/doc/coloring/pgr_edgeColoring.rst index 2328cdc8d9..2d8f6c8b59 100644 --- a/doc/coloring/pgr_edgeColoring.rst +++ b/doc/coloring/pgr_edgeColoring.rst @@ -20,6 +20,10 @@ graphs .. rubric:: Availability +.. rubric:: Version 4.1.0 + +* Fix the way it builds the graph + .. rubric:: Version 4.0.0 * Output columns standardized to |result_edge_color| diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index 736eeb7778..7756b82216 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -49,6 +49,20 @@ To see all issues & pull requests closed by this release see the * :issue:`3086`: MaxFlow: create and use a process and driver * :issue:`3089`: edgeDisjoint and bellmanFord use shortestPath driver and process +* :issue:`3100`: Coloring: create an use a process & driver + +.. rubric:: Bug Fixes + +* :issue:`3101`: pgr_edgeColoring not building graph correctly + + +.. rubric:: Summary of changes by function + +* pgr_edgeColoring + + .. include:: pgr_edgeColoring.rst + :start-after: Version 4.1.0 + :end-before: .. rubric pgRouting 4.0 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/docqueries/coloring/edgeColoring.result b/docqueries/coloring/edgeColoring.result index 35c0a0a700..e8e5d4451e 100644 --- a/docqueries/coloring/edgeColoring.result +++ b/docqueries/coloring/edgeColoring.result @@ -12,7 +12,7 @@ SELECT edge, color FROM pgr_edgeColoring( ); edge | color ------+------- - 1 | 3 + 1 | 1 2 | 2 3 | 3 4 | 4 diff --git a/include/c_common/enums.h b/include/c_common/enums.h index 2d8598fcdc..d217598a6b 100644 --- a/include/c_common/enums.h +++ b/include/c_common/enums.h @@ -47,7 +47,10 @@ enum Which { DFS = 520, BFS = 530, DIJKSTRADD = 540, - MAXFLOW, PUSHRELABEL, BOYKOV, EDMONDSKARP + /* For flow */ + MAXFLOW, PUSHRELABEL, BOYKOV, EDMONDSKARP, + /* For coloring */ + EDGECOLORING, BIPARTITE, SEQUENTIAL }; #endif // INCLUDE_C_COMMON_ENUMS_H_ diff --git a/include/drivers/coloring/bipartite_driver.h b/include/coloring/bipartite.hpp similarity index 63% rename from include/drivers/coloring/bipartite_driver.h rename to include/coloring/bipartite.hpp index 4ad01e6fbd..3ff49c3fc6 100644 --- a/include/drivers/coloring/bipartite_driver.h +++ b/include/coloring/bipartite.hpp @@ -1,8 +1,8 @@ /*PGR-GNU***************************************************************** -File: bipartite_driver.h +File: bipartite.hpp Generated with Template by: -Copyright (c) 2013-2026 pgRouting developers +Copyright (c) 2021-2026 pgRouting developers Mail: project@pgrouting.org Function's developer: @@ -27,33 +27,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -#ifndef INCLUDE_DRIVERS_COLORING_BIPARTITE_DRIVER_H_ -#define INCLUDE_DRIVERS_COLORING_BIPARTITE_DRIVER_H_ +#ifndef INCLUDE_COLORING_BIPARTITE_HPP_ +#define INCLUDE_COLORING_BIPARTITE_HPP_ +#pragma once -/* for size-t */ -#ifdef __cplusplus -# include -using II_t_rt = struct II_t_rt; -#else -# include -typedef struct II_t_rt II_t_rt; -#endif +#include +#include "c_types/ii_t_rt.h" +#include "cpp_common/base_graph.hpp" -#ifdef __cplusplus -extern "C" { -#endif +namespace pgrouting { +namespace functions { -void -pgr_do_bipartite( - const char*, +std::vector pgr_bipartite(pgrouting::UndirectedGraph&); - II_t_rt**, size_t*, - char**, char**, char**); +} // namespace functions +} // namespace pgrouting -#ifdef __cplusplus -} -#endif - -#endif // INCLUDE_DRIVERS_COLORING_BIPARTITE_DRIVER_H_ +#endif // INCLUDE_COLORING_BIPARTITE_HPP_ diff --git a/include/coloring/bipartite_driver.hpp b/include/coloring/bipartite_driver.hpp deleted file mode 100644 index 35349c6256..0000000000 --- a/include/coloring/bipartite_driver.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/*PGR-GNU***************************************************************** -File: bipartite_driver.hpp - -Generated with Template by: -Copyright (c) 2013-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2020 Prakash Tiwari -Mail: 85prakash2017@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_COLORING_BIPARTITE_DRIVER_HPP_ -#define INCLUDE_COLORING_BIPARTITE_DRIVER_HPP_ -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "cpp_common/base_graph.hpp" -#include "cpp_common/messages.hpp" -#include "cpp_common/interruption.hpp" -typedef struct II_t_rt II_t_rt; -#include "c_types/ii_t_rt.h" - -namespace pgrouting { -namespace functions { - -template -class Pgr_Bipartite : public pgrouting::Pgr_messages { - public: - typedef typename G::V_i V_i; - std::vector print_Bipartite( - G &graph) { - std::vector results; - std::vector partition(graph.num_vertices()); - auto partition_map = - make_iterator_property_map(partition.begin(), boost::get(boost::vertex_index, graph.graph)); - - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ - CHECK_FOR_INTERRUPTS(); - try { - boost::is_bipartite(graph.graph, boost::get(boost::vertex_index, graph.graph), partition_map); - } catch (boost::exception const& ex) { - (void)ex; - throw; - } catch (std::exception &e) { - (void)e; - throw; - } catch (...) { - throw; - } - V_i v, vend; - for (boost::tie(v, vend) = vertices(graph.graph); v != vend; ++v) { - int64_t vid = graph[*v].id; - boost::get(partition_map, *v) == - boost::color_traits ::white() ? - results.push_back({{vid}, {0}}) : results.push_back({{vid}, {1}}); - } - return results; - } - std::vector pgr_bipartite( - G &graph ){ - std::vector results; - bool bipartite = boost::is_bipartite(graph.graph); - if (bipartite) results = print_Bipartite(graph); - return results; - } -}; -} // namespace functions -} // namespace pgrouting -#endif // INCLUDE_COLORING_BIPARTITE_DRIVER_HPP_ diff --git a/include/coloring/edgeColoring.hpp b/include/coloring/edgeColoring.hpp index aed021ce67..f38456403d 100644 --- a/include/coloring/edgeColoring.hpp +++ b/include/coloring/edgeColoring.hpp @@ -30,56 +30,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #define INCLUDE_COLORING_EDGECOLORING_HPP_ #pragma once -#include -#include #include #include -#include -#include -#include - -#include "cpp_common/edge_t.hpp" #include "c_types/ii_t_rt.h" -#include "cpp_common/assert.hpp" -#include "cpp_common/messages.hpp" +#include "cpp_common/base_graph.hpp" namespace pgrouting { namespace functions { -class Pgr_edgeColoring : public Pgr_messages { - public: - using EdgeColoring_Graph = - boost::adjacency_list; - - using V = boost::graph_traits::vertex_descriptor; - using E = boost::graph_traits::edge_descriptor; - using V_it = boost::graph_traits::vertex_iterator; - using E_it = boost::graph_traits::edge_iterator; - - public: - std::vector edgeColoring(); - - explicit Pgr_edgeColoring(const std::vector&); - Pgr_edgeColoring() = delete; - -#if BOOST_VERSION >= 106800 - friend std::ostream& operator<<(std::ostream &, const Pgr_edgeColoring&); -#endif - - private: - V get_boost_vertex(int64_t id) const; - int64_t get_vertex_id(V v) const; - int64_t get_edge_id(E e) const; - +std::vector edgeColoring(pgrouting::UndirectedGraph); - private: - EdgeColoring_Graph graph; - std::map id_to_V; - std::map V_to_id; - std::map E_to_id; -}; } // namespace functions } // namespace pgrouting diff --git a/include/coloring/sequentialVertexColoring.hpp b/include/coloring/sequentialVertexColoring.hpp index eb413fa75e..0ff8fe3b43 100644 --- a/include/coloring/sequentialVertexColoring.hpp +++ b/include/coloring/sequentialVertexColoring.hpp @@ -28,117 +28,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #define INCLUDE_COLORING_SEQUENTIALVERTEXCOLORING_HPP_ #pragma once -#include #include -#include #include -#include -#include -#include -#include -#include -#include - #include "cpp_common/base_graph.hpp" -#include "cpp_common/interruption.hpp" - #include "c_types/ii_t_rt.h" namespace pgrouting { namespace functions { -//************************************************************* - -template < class G > -class Pgr_sequentialVertexColoring { - public: - typedef typename G::V V; - typedef typename G::E E; - typedef boost::adjacency_list < boost::listS, boost::vecS, boost::undirectedS > Graph; - typedef boost::graph_traits < Graph > ::vertices_size_type vertices_size_type; - - /** @name SequentialVertexColoring - * @{ - * - */ - - /** @brief sequentialVertexColoring function - * - * It does all the processing and returns the results. - * - * @param graph the graph containing the edges - * - * @returns results, when results are found - * - * @see [boost::sequential_vertex_coloring] - * (https://www.boost.org/libs/graph/doc/sequential_vertex_coloring.html) - */ - std::vector sequentialVertexColoring(G &graph) { - std::vector results; - - auto i_map = boost::get(boost::vertex_index, graph.graph); - - // vector which will store the color of all the vertices in the graph - std::vector < vertices_size_type > colors(boost::num_vertices(graph.graph)); - - // An iterator property map which records the color of each vertex - auto color_map = boost::make_iterator_property_map(colors.begin(), i_map); - - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ - CHECK_FOR_INTERRUPTS(); - - try { - boost::sequential_vertex_coloring(graph.graph, color_map); - } catch (boost::exception const& ex) { - (void)ex; - throw; - } catch (std::exception &e) { - (void)e; - throw; - } catch (...) { - throw; - } - - results = get_results(colors, graph); - - return results; - } - - //@} - - private: - /** @brief to get the results - * - * Uses the `colors` vector to get the results i.e. the color of every vertex. - * - * @param colors vector which contains the color of every vertex - * @param graph the graph containing the edges - * - * @returns `results` vector - */ - std::vector get_results( - std::vector < vertices_size_type > &colors, - const G &graph) { - std::vector results; - - typename boost::graph_traits < Graph > ::vertex_iterator v, vend; - - for (boost::tie(v, vend) = vertices(graph.graph); v != vend; ++v) { - int64_t node = graph[*v].id; - auto color = colors[*v]; - results.push_back({{node}, {static_cast(color + 1)}}); - } - - // ordering the results in an increasing order of the node id - std::sort(results.begin(), results.end(), - [](const II_t_rt row1, const II_t_rt row2) { - return row1.d1.id < row2.d1.id; - }); + std::vector sequentialVertexColoring(const pgrouting::UndirectedGraph&); - return results; - } -}; } // namespace functions } // namespace pgrouting diff --git a/include/drivers/coloring/edgeColoring_driver.h b/include/drivers/coloring_driver.hpp similarity index 56% rename from include/drivers/coloring/edgeColoring_driver.h rename to include/drivers/coloring_driver.hpp index 8b1364c847..7a5f279f6e 100644 --- a/include/drivers/coloring/edgeColoring_driver.h +++ b/include/drivers/coloring_driver.hpp @@ -1,13 +1,12 @@ /*PGR-GNU***************************************************************** -File: edgeColoring_driver.h +File: coloring_driver.hpp -Generated with Template by: -Copyright (c) 2013-2026 pgRouting developers +Copyright (c) 2015-2026 pgRouting developers Mail: project@pgrouting.org -Function's developer: -Copyright (c) 2021 Veenit Kumar -Mail: 123sveenit@gmail.com +Design of one process & driver file by +Copyright (c) 2025 Celia Virginia Vergara Castillo +Mail: vicky at erosion.dev ------ @@ -27,31 +26,29 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -#ifndef INCLUDE_DRIVERS_COLORING_EDGECOLORING_DRIVER_H_ -#define INCLUDE_DRIVERS_COLORING_EDGECOLORING_DRIVER_H_ +#ifndef INCLUDE_DRIVERS_COLORING_DRIVER_HPP_ +#define INCLUDE_DRIVERS_COLORING_DRIVER_HPP_ +#pragma once +#include +#include +#include +#include -#ifdef __cplusplus -# include -using II_t_rt = struct II_t_rt; -#else -# include -typedef struct II_t_rt II_t_rt; -#endif +#include "c_common/enums.h" -#ifdef __cplusplus -extern "C" { -#endif +using II_t_rt = struct II_t_rt; -void -pgr_do_edgeColoring( - const char*, +namespace pgrouting { +namespace drivers { - II_t_rt**, size_t*, - char**, char**, char**); +void do_coloring( + const std::string&, + Which, + II_t_rt*&, size_t&, + std::ostringstream&, std::ostringstream&, std::ostringstream&); -#ifdef __cplusplus -} -#endif +} // namespace drivers +} // namespace pgrouting -#endif // INCLUDE_DRIVERS_COLORING_EDGECOLORING_DRIVER_H_ +#endif // INCLUDE_DRIVERS_COLORING_DRIVER_HPP_ diff --git a/include/drivers/coloring/sequentialVertexColoring_driver.h b/include/process/coloring_process.h similarity index 69% rename from include/drivers/coloring/sequentialVertexColoring_driver.h rename to include/process/coloring_process.h index 3913cdf95c..63d003db2e 100644 --- a/include/drivers/coloring/sequentialVertexColoring_driver.h +++ b/include/process/coloring_process.h @@ -1,13 +1,12 @@ /*PGR-GNU***************************************************************** -File: sequentialVertexColoring_driver.h +File: coloring_process.h -Generated with Template by: Copyright (c) 2007-2026 pgRouting developers Mail: project@pgrouting.org -Function's developer: -Copyright (c) 2020 Ashish Kumar -Mail: ashishkr23438@gmail.com +Design of one process & driver file by +Copyright (c) 2025 Celia Virginia Vergara Castillo +Mail: vicky at erosion.dev ------ @@ -27,31 +26,34 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -#ifndef INCLUDE_DRIVERS_COLORING_SEQUENTIALVERTEXCOLORING_DRIVER_H_ -#define INCLUDE_DRIVERS_COLORING_SEQUENTIALVERTEXCOLORING_DRIVER_H_ +#ifndef INCLUDE_PROCESS_COLORING_PROCESS_H_ +#define INCLUDE_PROCESS_COLORING_PROCESS_H_ #pragma once #ifdef __cplusplus -# include +#include +#include using II_t_rt = struct II_t_rt; #else -# include +#include +#include +#include typedef struct II_t_rt II_t_rt; #endif +#include "c_common/enums.h" #ifdef __cplusplus extern "C" { #endif -void pgr_do_sequentialVertexColoring( +void pgr_process_coloring( const char*, - - II_t_rt**, size_t*, - char**, char**, char**); + enum Which, + II_t_rt**, size_t*); #ifdef __cplusplus } #endif -#endif // INCLUDE_DRIVERS_COLORING_SEQUENTIALVERTEXCOLORING_DRIVER_H_ +#endif // INCLUDE_PROCESS_COLORING_PROCESS_H_ diff --git a/locale/en/LC_MESSAGES/pgrouting_doc_strings.po b/locale/en/LC_MESSAGES/pgrouting_doc_strings.po index d7bae495fc..7eb90e305f 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-03-04 00:25+0000\n" +"POT-Creation-Date: 2026-03-25 04:02+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3971,6 +3971,28 @@ msgid "" "and bellmanFord use shortestPath driver and process" msgstr "" +msgid "" +"`#3100 `__: Coloring: " +"create an use a process & driver" +msgstr "" + +msgid "Bug Fixes" +msgstr "" + +msgid "" +"`#3101 `__: " +"pgr_edgeColoring not building graph correctly" +msgstr "" + +msgid "Summary of changes by function" +msgstr "" + +msgid "pgr_edgeColoring" +msgstr "pgr_edgeColoring" + +msgid "Fix the way it builds the graph" +msgstr "" + msgid "All releases" msgstr "" @@ -11224,6 +11246,9 @@ msgid "" "graphs" msgstr "" +msgid "Version 4.1.0" +msgstr "" + msgid "Output columns standardized to |result_edge_color|" msgstr "" @@ -15056,9 +15081,6 @@ msgid "" "utf8=%E2%9C%93&q=milestone%3A%22Release%204.0.1%22>`__" msgstr "" -msgid "Bug Fixes" -msgstr "" - msgid "" "`#2966 `__: " "pgr_withPoints does not pick optimal route when fraction = 1" @@ -15198,9 +15220,6 @@ msgstr "" msgid "To not build Doxygen documentation: `-DBUILD_DOXY=OFF`" msgstr "" -msgid "Summary of changes by function" -msgstr "" - msgid "pgr_aStar" msgstr "pgr_aStar" @@ -15264,9 +15283,6 @@ msgstr "pgr_dijkstraNearCost" msgid "pgr_dijkstraVia" msgstr "pgr_dijkstraVia" -msgid "pgr_edgeColoring" -msgstr "pgr_edgeColoring" - msgid "pgr_edgeDisjointPaths" msgstr "pgr_edgeDisjointPaths" diff --git a/locale/pot/pgrouting_doc_strings.pot b/locale/pot/pgrouting_doc_strings.pot index 816ae887c8..30245206d6 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-03-04 00:25+0000\n" +"POT-Creation-Date: 2026-03-25 04:02+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3556,6 +3556,24 @@ msgstr "" msgid "`#3089 `__: edgeDisjoint and bellmanFord use shortestPath driver and process" msgstr "" +msgid "`#3100 `__: Coloring: create an use a process & driver" +msgstr "" + +msgid "Bug Fixes" +msgstr "" + +msgid "`#3101 `__: pgr_edgeColoring not building graph correctly" +msgstr "" + +msgid "Summary of changes by function" +msgstr "" + +msgid "pgr_edgeColoring" +msgstr "" + +msgid "Fix the way it builds the graph" +msgstr "" + msgid "All releases" msgstr "" @@ -9628,6 +9646,9 @@ msgstr "" msgid "``pgr_edgeColoring`` — Returns the edge coloring of undirected and loop-free graphs" msgstr "" +msgid "Version 4.1.0" +msgstr "" + msgid "Output columns standardized to |result_edge_color|" msgstr "" @@ -12712,9 +12733,6 @@ msgstr "" msgid "To see all issues & pull requests closed by this release see the `Github milestone for 4.0.1 `__" msgstr "" -msgid "Bug Fixes" -msgstr "" - msgid "`#2966 `__: pgr_withPoints does not pick optimal route when fraction = 1" msgstr "" @@ -12829,9 +12847,6 @@ msgstr "" msgid "To not build Doxygen documentation: `-DBUILD_DOXY=OFF`" msgstr "" -msgid "Summary of changes by function" -msgstr "" - msgid "pgr_aStar" msgstr "" @@ -12895,9 +12910,6 @@ msgstr "" msgid "pgr_dijkstraVia" msgstr "" -msgid "pgr_edgeColoring" -msgstr "" - msgid "pgr_edgeDisjointPaths" msgstr "" diff --git a/pgtap/coloring/edgeColoring/edge_cases.pg b/pgtap/coloring/edgeColoring/edge_cases.pg index ef69df2405..8d1ee2ccb3 100644 --- a/pgtap/coloring/edgeColoring/edge_cases.pg +++ b/pgtap/coloring/edgeColoring/edge_cases.pg @@ -6,7 +6,7 @@ BEGIN; UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost); -SELECT CASE WHEN min_version('4.0.0') THEN plan(29) ELSE plan(1) END; +SELECT CASE WHEN min_version('4.0.0') THEN plan(17) ELSE plan(1) END; CREATE OR REPLACE FUNCTION edge_cases() RETURNS SETOF TEXT AS @@ -27,409 +27,236 @@ FROM edges WHERE id > 18; RETURN QUERY -SELECT is_empty('q1', 'Graph with 0 edge and 0 vertex'); - -PREPARE edgeColoring1 AS -SELECT * FROM pgr_edgeColoring('q1'); - -RETURN QUERY -SELECT is_empty('edgeColoring1', 'Graph with 0 edge and 0 vertex -> Empty row is returned'); +SELECT is_empty($$SELECT * FROM pgr_edgeColoring('q1')$$, 'is empty: Graph with 0 edge and 0 vertex'); -- 1 vertex test +-- 6 -- 6 PREPARE q2 AS -SELECT id, source, 6 AS target, cost, reverse_cost -FROM edges -WHERE id = 2; - -PREPARE edgeColoring2 AS -SELECT * FROM pgr_edgeColoring('q2'); +SELECT 2 AS id, 6 AS source, 6 AS target, -1 AS cost, 1 AS reverse_cost; RETURN QUERY -SELECT is_empty('edgeColoring2', 'One vertex graph can not be edgeColored -> Empty row is returned'); +SELECT CASE WHEN min_lib_version('4.1.0') THEN +collect_tap( + isnt_empty($$SELECT * FROM pgr_edgeColoring('q2')$$, 'q2: One vertex self-loop graph has results') +) +ELSE +collect_tap( + skip(1, 'pgr_edgecoloring: graph building fixed on v4.1.0.') +) +END; -- 2 vertices test (connected) +-- 3--7 PREPARE q3 AS -SELECT id, source, target, cost, reverse_cost -FROM edges -WHERE id = 7; - -RETURN QUERY -SELECT set_eq('q3', $$VALUES (7, 3, 7, 1, 1)$$, 'Graph with two connected vertices'); - -PREPARE edgeColoring3 AS -SELECT * FROM pgr_edgeColoring('q3'); +SELECT 7 AS id, 3 AS source, 7 AS target, 1 AS cost, 1 AS reverse_cost; RETURN QUERY -SELECT set_eq('edgeColoring3', $$VALUES (7, 1)$$, 'Edge is colored with color 1'); - +SELECT set_eq($$SELECT * FROM pgr_edgeColoring('q3')$$, + $$VALUES (7, 1)$$, 'q3: Edge is colored with color 1'); --- linear tests -- 3 vertices test +-- 6 -- {5---10} PREPARE q4 AS -SELECT id, source, target, cost, reverse_cost -FROM edges -WHERE id <= 2; - -RETURN QUERY -SELECT set_eq('q4', $$VALUES (1, 5, 6, 1, 1), (2, 6, 10, -1, 1)$$, 'Graph with three vertices'); - -PREPARE edgeColoring4 AS -SELECT * FROM pgr_edgeColoring('q4'); +SELECT id, source, target, cost, reverse_cost FROM edges WHERE id <= 2; RETURN QUERY -SELECT set_eq('edgeColoring4', $$VALUES (1, 1), (2, 2)$$, 'Two colors are expected'); +SELECT set_eq($$SELECT * FROM pgr_edgeColoring('q4')$$, $$VALUES (1, 1), (2, 2)$$, 'q4: Two colors are expected'); -- 4 vertices test +-- 6 -- {5---10}; 15--10; PREPARE q5 AS -SELECT id, source, target, cost, reverse_cost -FROM edges -WHERE id <= 3; - -RETURN QUERY -SELECT set_eq('q5', - $$VALUES - (1, 5, 6, 1, 1), - (2, 6, 10, -1, 1), - (3, 10, 15, -1, 1) - $$, - 'Graph with four vertices' -); +SELECT id, source, target, cost, reverse_cost FROM edges WHERE id <= 3; RETURN QUERY -SELECT ok((SELECT count(DISTINCT color) <= 3 FROM pgr_edgeColoring('q5')), 'At most three colors are expected'); +SELECT ok((SELECT count(DISTINCT color) <= 3 FROM pgr_edgeColoring('q5')), 'q5: At most three colors are expected'); -- even length cycle test -- 4 vertices length +-- {7,12}--{8,11} ; PREPARE q6 AS SELECT id, source, target, cost, reverse_cost -FROM edges -WHERE id IN (8, 10, 11, 12); +FROM edges WHERE id IN (8, 10, 11, 12) ORDER BY id ASC; RETURN QUERY -SELECT set_eq('q6', - $$VALUES - (8, 7, 11, 1, 1), - (10, 7, 8, 1, 1), - (11, 11, 12, 1, -1), - (12, 8, 12, 1, -1) - $$, - 'Graph with four vertices (cyclic)' -); +SELECT ok((SELECT count(DISTINCT color) <= 3 FROM pgr_edgeColoring('q6')), 'q6: At most three colors are expected'); RETURN QUERY -SELECT ok((SELECT count(DISTINCT color) <= 3 FROM pgr_edgeColoring('q6')), 'At most three colors are expected'); +SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q6')), 3, 'q6: Three colors are used'); -- changing the order of the edges will change the number of colors expected --- 4 vertices length - +-- {7,12}--{8,11} ; PREPARE q7 AS SELECT id, source, target, cost, reverse_cost FROM edges WHERE id IN (8, 10, 11, 12) ORDER BY id DESC; RETURN QUERY -SELECT set_eq('q7', - $$VALUES - (8, 7, 11, 1, 1), - (10, 7, 8, 1, 1), - (11, 11, 12, 1, -1), - (12, 8, 12, 1, -1) - $$, - 'Graph with four vertices (cyclic)' -); - -RETURN QUERY -SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q7')), 2, 'Two colors are expected'); - - --- odd length cycle test - --- 3 vertices cyclic - -CREATE TABLE three_vertices_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); +SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q7')), 2, 'q7 == q6 DESC: Two colors are used'); -INSERT INTO three_vertices_table (source, target, cost, reverse_cost) VALUES - (3, 6, 20, 15), - (3, 8, 10, -10), - (6, 8, -1, 12); +-- 3--{6,8}; 8--3; 8--6; PREPARE q8 AS SELECT id, source, target, cost, reverse_cost -FROM three_vertices_table; +FROM (VALUES + (1, 3, 6, 20, 15), + (2, 3, 8, 10, -10), + (3, 6, 8, -1, 12)) +AS t(id, source, target, cost, reverse_cost); RETURN QUERY -SELECT set_eq('q8', - $$VALUES - (1, 3, 6, 20, 15), - (2, 3, 8, 10, -10), - (3, 6, 8, -1, 12) - $$, - 'Cyclic Graph with three vertices 3, 6 and 8' -); - -RETURN QUERY -SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q8')), 3, 'Three colors are expected'); - - --- 5 vertices cyclic - -CREATE TABLE five_vertices_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); - -INSERT INTO five_vertices_table (source, target, cost, reverse_cost) VALUES - (1, 2, 1, 1), - (2, 3, 1, 1), - (3, 4, 1, -1), - (4, 5, 1, 1), - (5, 1, 1, -1); +SELECT CASE WHEN min_lib_version('4.1.0') THEN + collect_tap( + is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q8')), 4, 'q8: Four colors are expected') + ) +ELSE + collect_tap( + is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q8')), 3, 'q8: Three colors are expected') + ) +END; +-- 1--2--3--4--5--6--1 PREPARE q9 AS SELECT id, source, target, cost, reverse_cost -FROM five_vertices_table; - -RETURN QUERY -SELECT set_eq('q9', - $$VALUES - (1, 1, 2, 1, 1), - (2, 2, 3, 1, 1), - (3, 3, 4, 1, -1), - (4, 4, 5, 1, 1), - (5, 5, 1, 1, -1) - $$, - 'Cyclic Graph with five vertices 1, 2, 3, 4 and 5' -); +FROM (VALUES + (1, 1, 2, 1, 1), + (2, 2, 3, 1, 1), + (3, 3, 4, 1, -1), + (4, 4, 5, 1, 1), + (5, 5, 1, 1, -1)) +AS t(id, source, target, cost, reverse_cost); RETURN QUERY -SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q9')), 3, 'Three colors are expected'); +SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q9')), 3, 'q9: Three colors are expected'); -- self loop test --- 1 vertex self loop - -CREATE TABLE one_vertex_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); - -INSERT INTO one_vertex_table (source, target, cost, reverse_cost) VALUES - (1, 1, 1, 1); - +-- 1--1 PREPARE q10 AS SELECT id, source, target, cost, reverse_cost -FROM one_vertex_table; - -RETURN QUERY -SELECT set_eq('q10', - $$VALUES - (1, 1, 1, 1, 1) - $$, - 'Self loop Graph with one vertex 1' -); +FROM (VALUES + (1, 1, 1, 1, 1)) +AS t(id, source, target, cost, reverse_cost); PREPARE edgeColoring10 AS SELECT * FROM pgr_edgeColoring('q10'); RETURN QUERY -SELECT is_empty('edgeColoring10', 'One vertex self-loop graph can not be edgeColored -> Empty row is returned'); - - --- 2 vertex self loop - -CREATE TABLE two_vertices_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); +SELECT CASE WHEN min_lib_version('4.1.0') THEN +collect_tap( + isnt_empty($$SELECT * FROM pgr_edgeColoring('q10')$$, 'q10: One vertex self-loop graph has results') +) +ELSE +collect_tap( + is_empty($$SELECT * FROM pgr_edgeColoring('q10')$$, 'q10: One vertex self-loop graph is empty') +) +END; -INSERT INTO two_vertices_table (source, target, cost, reverse_cost) VALUES - (1, 2, 1, 1), - (2, 2, 1, 1); +-- {1,2} --2 PREPARE q11 AS SELECT id, source, target, cost, reverse_cost -FROM two_vertices_table; - -RETURN QUERY -SELECT set_eq('q11', - $$VALUES - (1, 1, 2, 1, 1), - (2, 2, 2, 1, 1) - $$, - 'Self loop Graph with two vertices 1 and 2' -); - -PREPARE edgeColoring11 AS -SELECT * FROM pgr_edgeColoring('q11'); +FROM (VALUES + (1, 1, 2, 1, 1), + (2, 2, 2, 1, 1)) +AS t(id, source, target, cost, reverse_cost); RETURN QUERY -SELECT set_eq('edgeColoring11', $$VALUES (1, 1)$$, 'One color is required'); - - --- 7 vertices tree - -CREATE TABLE seven_vertices_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); +SELECT CASE WHEN min_lib_version('4.1.0') THEN +collect_tap( + is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q11')), 2, 'q11: Two colors are used') +) +ELSE + collect_tap( + is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q11')), 1, 'q11: One color is used') + ) +END; -INSERT INTO seven_vertices_table (source, target, cost, reverse_cost) VALUES - (1, 2, 1, 1), - (1, 4, 1, 1), - (2, 3, 1, 1), - (2, 5, 1, 1), - (4, 6, 1, 1), - (4, 7, 1, 1); +-- 1--{2,4} ; 2--{3,5} ; 4--{6,7} PREPARE q12 AS SELECT id, source, target, cost, reverse_cost -FROM seven_vertices_table; - -RETURN QUERY -SELECT set_eq('q12', - $$VALUES - (1, 1, 2, 1, 1), - (2, 1, 4, 1, 1), - (3, 2, 3, 1, 1), - (4, 2, 5, 1, 1), - (5, 4, 6, 1, 1), - (6, 4, 7, 1, 1) - $$, - 'A tree Graph with seven vertices 1, 2, 3, 4, 5, 6 and 7' -); +FROM (VALUES + (1, 1, 2, 1, 1), + (2, 1, 4, 1, 1), + (3, 2, 3, 1, 1), + (4, 2, 5, 1, 1), + (5, 4, 6, 1, 1), + (6, 4, 7, 1, 1)) +AS t(id, source, target, cost, reverse_cost); RETURN QUERY -SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q12')), 3, 'Three colors are expected'); +SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q12')), 3, 'q12: Three colors are used'); -- 3 vertices multiple edge -CREATE TABLE multiple_edge_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); - -INSERT INTO multiple_edge_table (source, target, cost, reverse_cost) VALUES - (1, 2, 1, 1), - (2, 3, 1, 1), - (3, 2, 1, 1); - +-- 1--2--3--2 PREPARE q13 AS SELECT id, source, target, cost, reverse_cost -FROM multiple_edge_table; - -RETURN QUERY -SELECT set_eq('q13', - $$VALUES - (1, 1, 2, 1, 1), - (2, 2, 3, 1, 1), - (3, 3, 2, 1, 1) - $$, - 'Multiple edge Graph with three vertices 1, 2 and 3' -); +FROM (VALUES + (1, 1, 2, 1, 1), + (2, 2, 3, 1, 1), + (3, 3, 2, 1, 1)) +AS t(id, source, target, cost, reverse_cost) ORDER BY id ASC; RETURN QUERY -SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q13')), 2, 'Two colors are expected'); +SELECT CASE WHEN min_lib_version('4.1.0') THEN +collect_tap( + is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q13')), 3, 'q13: Three colors are expected') +) +ELSE + collect_tap( + skip(1, 'pgr_edgecoloring: graph building fixed on v4.1.0.') + ) +END; -- 2 vertices multiple edge -CREATE TABLE two_vertices_multiple_edge_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); - -INSERT INTO two_vertices_multiple_edge_table (source, target, cost, reverse_cost) VALUES - (1, 2, 1, 1), - (2, 1, 1, 1); - +-- 1--2--1 PREPARE q14 AS SELECT id, source, target, cost, reverse_cost -FROM two_vertices_multiple_edge_table; - -RETURN QUERY -SELECT set_eq('q14', - $$VALUES +FROM (VALUES (1, 1, 2, 1, 1), - (2, 2, 1, 1, 1) - $$, - 'Multiple edge Graph with two vertices 1 and 2' -); - -PREPARE edgeColoring14 AS -SELECT * FROM pgr_edgeColoring('q14'); + (2, 2, 1, 1, 1)) +AS t(id, source, target, cost, reverse_cost) ORDER BY id ASC; RETURN QUERY -SELECT set_eq('edgeColoring14', $$VALUES (1, 1)$$, 'One color is required'); - +SELECT CASE WHEN min_lib_version('4.1.0') THEN +collect_tap( + is((SELECT count(*) FROM pgr_edgeColoring('q14'))::INTEGER, 2, 'q14: two rows are expected'), + is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q14')), 2, 'q14: Two colors are used') +) +ELSE + collect_tap( + skip(2, 'pgr_edgecoloring: graph building fixed on v4.1.0.') + ) +END; -- 4 vertices disconnected graph -CREATE TABLE disconnected_graph_table ( - id BIGSERIAL, - source BIGINT, - target BIGINT, - cost FLOAT, - reverse_cost FLOAT -); - -INSERT INTO disconnected_graph_table (source, target, cost, reverse_cost) VALUES - (1, 2, 1, 1), - (3, 4, 1, 1); - PREPARE q15 AS SELECT id, source, target, cost, reverse_cost -FROM disconnected_graph_table; - -RETURN QUERY -SELECT set_eq('q15', - $$VALUES +FROM (VALUES (1, 1, 2, 1, 1), - (2, 3, 4, 1, 1) - $$, - 'Disconnected Graph with four vertices 1, 2, 3 and 4' -); + (2, 3, 4, 1, 1)) +AS t(id, source, target, cost, reverse_cost); RETURN QUERY -SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q15')), 1, 'One color is required'); - +SELECT is((SELECT count(DISTINCT color)::INTEGER FROM pgr_edgeColoring('q15')), 1, 'q15: One color is used'); END; $BODY$ diff --git a/src/coloring/CMakeLists.txt b/src/coloring/CMakeLists.txt index e55009b8a9..a8a7b37c35 100644 --- a/src/coloring/CMakeLists.txt +++ b/src/coloring/CMakeLists.txt @@ -3,10 +3,13 @@ # License: GPL-2 See https://github.com/pgRouting/pgrouting/blob/main/LICENSE ADD_LIBRARY(coloring OBJECT sequentialVertexColoring.c - sequentialVertexColoring_driver.cpp bipartite.c - bipartite_driver.cpp edgeColoring.c - edgeColoring_driver.cpp + + bipartite.cpp edgeColoring.cpp - ) + sequentialVertexColoring.cpp + + coloring_process.cpp + coloring_driver.cpp +) diff --git a/src/coloring/bipartite.c b/src/coloring/bipartite.c index 1822bd0700..dfdd050a1a 100644 --- a/src/coloring/bipartite.c +++ b/src/coloring/bipartite.c @@ -29,77 +29,47 @@ 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 "drivers/coloring/bipartite_driver.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); -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; - - PGR_DBG("Starting timer"); - clock_t start_t = clock(); - pgr_do_bipartite( - edges_sql, - result_tuples, result_count, - &log_msg, - ¬ice_msg, - &err_msg); - time_msg("processing pgr_bipartite()", start_t, clock()); - - - if (err_msg && (*result_tuples)) { - pfree(*result_tuples); - (*result_tuples) = NULL; - (*result_count) = 0; - } - - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} - -PGDLLEXPORT Datum -_pgr_bipartite(PG_FUNCTION_ARGS) { +PGDLLEXPORT Datum _pgr_bipartite(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; II_t_rt *result_tuples = NULL; size_t result_count = 0; + if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - process( + + pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + + 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) + != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); + } + funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } @@ -122,12 +92,14 @@ _pgr_bipartite(PG_FUNCTION_ARGS) { for (i = 0; i < numb; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum(result_tuples[call_cntr].d1.id); - values[1] = Int64GetDatum(result_tuples[call_cntr].d2.value); - tuple = heap_form_tuple(tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); - SRF_RETURN_NEXT(funcctx, result); - } else { - SRF_RETURN_DONE(funcctx); - } + + values[0] = Int64GetDatum(result_tuples[call_cntr].d1.id); + values[1] = Int64GetDatum(result_tuples[call_cntr].d2.value); + + tuple = heap_form_tuple(tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } else { + SRF_RETURN_DONE(funcctx); + } } diff --git a/src/coloring/bipartite.cpp b/src/coloring/bipartite.cpp new file mode 100644 index 0000000000..62e4070f69 --- /dev/null +++ b/src/coloring/bipartite.cpp @@ -0,0 +1,84 @@ +/*PGR-GNU***************************************************************** +File: bipartite.cpp + +Generated with Template by: +Copyright (c) 2021-2026 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2020 Prakash Tiwari +Mail: 85prakash2017@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 "coloring/bipartite.hpp" + +#include +#include +#include + +#include + +#include "cpp_common/interruption.hpp" + +namespace { + +std::vector get_bipartition(pgrouting::UndirectedGraph &graph) { + using V_i = pgrouting::UndirectedGraph::V_i; + + std::vector results; + std::vector partition(graph.num_vertices()); + auto partition_map = + make_iterator_property_map(partition.begin(), boost::get(boost::vertex_index, graph.graph)); + + CHECK_FOR_INTERRUPTS(); + try { + boost::is_bipartite(graph.graph, boost::get(boost::vertex_index, graph.graph), partition_map); + } catch (boost::exception const& ex) { + throw; + } catch (std::exception &e) { + throw; + } catch (...) { + throw std::make_pair( + std::string("INTERNAL: something went wrong while calling boost::edge_coloring"), + std::string(__PGR_PRETTY_FUNCTION__));; + } + + V_i v, vend; + for (boost::tie(v, vend) = vertices(graph.graph); v != vend; ++v) { + int64_t vid = graph[*v].id; + boost::get(partition_map, *v) == + boost::color_traits ::white() ? + results.push_back({{vid}, {0}}) : results.push_back({{vid}, {1}}); + } + return results; +} + +} // namespace + +namespace pgrouting { +namespace functions { + +std::vector pgr_bipartite(pgrouting::UndirectedGraph &graph ) { + bool bipartite = boost::is_bipartite(graph.graph); + return (bipartite)? get_bipartition(graph) : std::vector(); +} + +} // namespace functions +} // namespace pgrouting diff --git a/src/coloring/bipartite_driver.cpp b/src/coloring/bipartite_driver.cpp deleted file mode 100644 index 07f740ad03..0000000000 --- a/src/coloring/bipartite_driver.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/*PGR-GNU***************************************************************** -File: bipartite_driver.cpp - -Generated with Template by: -Copyright (c) 2013-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2020 Prakash Tiwari -Mail: 85prakash2017@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 "cpp_common/pgdata_getters.hpp" -#include "c_types/ii_t_rt.h" -#include "cpp_common/identifiers.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/path.hpp" -#include "cpp_common/base_graph.hpp" -#include "drivers/coloring/bipartite_driver.h" -#include "coloring/bipartite_driver.hpp" - - -void -pgr_do_bipartite( - 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; - - std::ostringstream log; - std::ostringstream notice; - std::ostringstream err; - const char *hint = nullptr; - - - try { - // NOLINTBEGIN(clang-analyzer-cplusplus.NewDelete) - pgassert(!(*log_msg)); - pgassert(!(*notice_msg)); - pgassert(!(*err_msg)); - pgassert(!(*return_tuples)); - pgassert(*return_count == 0); - // NOLINTEND(clang-analyzer-cplusplus.NewDelete) - - hint = edges_sql; - auto edges = pgrouting::pgget::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; - - std::string logstr; - pgrouting::UndirectedGraph undigraph; - undigraph.insert_edges(edges); - std::vector results; - pgrouting::functions::Pgr_Bipartite fn_Bipartite; - results = fn_Bipartite.pgr_bipartite(undigraph); - logstr += fn_Bipartite.get_log(); - log << logstr; - auto count = results.size(); - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - *log_msg = to_pg_msg(log); - *notice_msg = to_pg_msg(notice); - 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/coloring/coloring_driver.cpp b/src/coloring/coloring_driver.cpp new file mode 100644 index 0000000000..7b510e2a4d --- /dev/null +++ b/src/coloring/coloring_driver.cpp @@ -0,0 +1,136 @@ +/*PGR-GNU***************************************************************** +File: coloring_driver.cpp + +Copyright (c) 2015-2026 pgRouting developers +Mail: project@pgrouting.org + +Design of one process & driver file by +Copyright (c) 2025 Celia Virginia Vergara Castillo +Mail: vicky at erosion.dev + +------ + +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/coloring_driver.hpp" + +#include +#include +#include +#include +#include +#include + +#include "c_types/ii_t_rt.h" +#include "cpp_common/pgdata_getters.hpp" +#include "cpp_common/utilities.hpp" +#include "cpp_common/to_postgres.hpp" +#include "cpp_common/alloc.hpp" +#include "cpp_common/assert.hpp" + +#include "coloring/bipartite.hpp" +#include "coloring/edgeColoring.hpp" +#include "coloring/sequentialVertexColoring.hpp" + +namespace pgrouting { +namespace drivers { + +void do_coloring( + const std::string &edges_sql, + + Which which, + + II_t_rt* &return_tuples, + size_t &return_count, + std::ostringstream &log, + std::ostringstream ¬ice, + std::ostringstream &err) { + std::string hint = ""; + + try { + if (edges_sql.empty()) { + err << "Empty edges SQL"; + return; + } + + using pgrouting::pgget::get_edges; + using pgrouting::UndirectedGraph; + + using pgrouting::functions::edgeColoring; + using pgrouting::functions::sequentialVertexColoring; + using pgrouting::functions::pgr_bipartite; + + hint = edges_sql; + auto edges = get_edges(edges_sql, true, false); + + if (edges.empty()) { + notice << "No edges found"; + log << edges_sql; + return; + } + + hint = ""; + + UndirectedGraph undigraph; + undigraph.insert_edges(edges); + + 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; + } + + auto count = results.size(); + + if (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) { + err << ex.first; + log << ex.second; + } catch (const std::string &ex) { + err << ex; + log << hint; + } catch (std::exception &except) { + err << except.what(); + } catch (...) { + err << "Caught unknown exception!"; + } +} + +} // namespace drivers +} // namespace pgrouting diff --git a/src/coloring/coloring_process.cpp b/src/coloring/coloring_process.cpp new file mode 100644 index 0000000000..190c9275fa --- /dev/null +++ b/src/coloring/coloring_process.cpp @@ -0,0 +1,85 @@ +/*PGR-GNU***************************************************************** +File: coloring_process.cpp + +Copyright (c) 2025-2026 pgRouting developers +Mail: project@pgrouting.org + +Design of one process & driver file by +Copyright (c) 2025 Celia Virginia Vergara Castillo +Mail: vicky at erosion.dev + +------ + +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 "process/coloring_process.h" + +extern "C" { +#include "c_common/postgres_connection.h" +#include "c_common/e_report.h" +#include "c_common/time_msg.h" +} + +#include +#include + +#include "c_types/ii_t_rt.h" + +#include "cpp_common/report_messages.hpp" +#include "cpp_common/utilities.hpp" +#include "cpp_common/assert.hpp" +#include "cpp_common/alloc.hpp" + +#include "drivers/coloring_driver.hpp" + +void pgr_process_coloring( + const char* edges_sql, + + enum Which which, + II_t_rt **result_tuples, + size_t *result_count) { + using pgrouting::to_pg_msg; + using pgrouting::pgr_free; + pgassert(edges_sql); + pgassert(!(*result_tuples)); + pgassert(*result_count == 0); + pgr_SPI_connect(); + + std::ostringstream log; + std::ostringstream err; + std::ostringstream notice; + + clock_t start_t = clock(); + pgrouting::drivers::do_coloring( + edges_sql? edges_sql : "", + + which, + (*result_tuples), (*result_count), + log, notice, err); + + auto name = std::string(" processing ") + pgrouting::get_name(which); + time_msg(name.c_str(), start_t, clock()); + + if (!err.str().empty() && (*result_tuples)) { + pfree(*result_tuples); + (*result_tuples) = nullptr; + (*result_count) = 0; + } + + pgrouting::report_messages(log, notice, err); + pgr_SPI_finish(); +} diff --git a/src/coloring/edgeColoring.c b/src/coloring/edgeColoring.c index 51b784790e..17c16bfcab 100644 --- a/src/coloring/edgeColoring.c +++ b/src/coloring/edgeColoring.c @@ -2,12 +2,14 @@ File: edgeColoring.c Generated with Template by: +Generated with Template by: Copyright (c) 2015-2026 pgRouting developers Mail: project@pgrouting.org Function's developer: Copyright (c) 2021 Veenit Kumar Mail: 123sveenit@gmail.com + ------ This program is free software; you can redistribute it and/or modify @@ -26,10 +28,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -/** @file edgeColoring.c - * @brief Connecting code with postgres. - * - */ #include #include "c_common/postgres_connection.h" @@ -37,56 +35,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #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 "drivers/coloring/edgeColoring_driver.h" +#include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_edgecoloring(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_edgecoloring); -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_edgeColoring( - edges_sql, - - result_tuples, - result_count, - &log_msg, - ¬ice_msg, - &err_msg); - time_msg("processing pgr_edgeColoring", start_t, clock()); - - if (err_msg && (*result_tuples)) { - pfree(*result_tuples); - (*result_tuples) = NULL; - (*result_count) = 0; - } - - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} - 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; @@ -95,12 +53,14 @@ PGDLLEXPORT Datum _pgr_edgecoloring(PG_FUNCTION_ARGS) { funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - process( + pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + + EDGECOLORING, &result_tuples, &result_count); - funcctx->max_calls = result_count; + funcctx->max_calls = result_count; funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) @@ -120,23 +80,22 @@ PGDLLEXPORT Datum _pgr_edgecoloring(PG_FUNCTION_ARGS) { result_tuples = (II_t_rt*) funcctx->user_fctx; if (funcctx->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)); - - + 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 i; - for (i = 0; i < num; ++i) { + for (i = 0; i < numb; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum(result_tuples[funcctx->call_cntr].d1.id); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].d2.value); + values[0] = Int64GetDatum(result_tuples[call_cntr].d1.id); + values[1] = Int64GetDatum(result_tuples[call_cntr].d2.value); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/coloring/edgeColoring.cpp b/src/coloring/edgeColoring.cpp index 02ffa43dd8..25de286562 100644 --- a/src/coloring/edgeColoring.cpp +++ b/src/coloring/edgeColoring.cpp @@ -5,6 +5,10 @@ Generated with Template by: Copyright (c) 2021-2026 pgRouting developers Mail: project@pgrouting.org +Rewrite: +Copyright (c) 2026 Vicky Vergara +Mail: vicky at erosion.dev + Function's developer: Copyright (c) 2021 Veenit Kumar Mail: 123sveenit@gmail.com @@ -29,14 +33,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "coloring/edgeColoring.hpp" #include -#include #include +#include +#include -#include "cpp_common/identifiers.hpp" #include -#include -#include "cpp_common/assert.hpp" #include "cpp_common/interruption.hpp" @@ -44,97 +46,46 @@ namespace pgrouting { namespace functions { std::vector -Pgr_edgeColoring::edgeColoring() { - std::vector results; - - CHECK_FOR_INTERRUPTS(); - - try { - boost::edge_coloring(graph, boost::get(boost::edge_bundle, graph)); - } catch (...) { - throw std::make_pair( - std::string("INTERNAL: something went wrong while calling boost::edge_coloring"), - std::string(__PGR_PRETTY_FUNCTION__)); - } - - for (auto e_i : boost::make_iterator_range(boost::edges(graph))) { - auto edge = get_edge_id(e_i); - int64_t color = graph[e_i]; - results.push_back({{edge}, {(color + 1)}}); - } - return results; -} - -Pgr_edgeColoring::Pgr_edgeColoring(const std::vector &edges) { - /* - * Inserting vertices - */ - Identifiers ids; - for (const auto &e : edges) { - ids += e.source; - ids += e.target; - } - - for (const auto id : ids) { - auto v = add_vertex(graph); - id_to_V.insert(std::make_pair(id, v)); - V_to_id.insert(std::make_pair(v, id)); - } +edgeColoring(pgrouting::UndirectedGraph g) { + std::vector results(boost::num_edges(g.graph)); + using B_G = pgrouting::UndirectedGraph::B_G; + using E = pgrouting::UndirectedGraph::E; - /* - * Inserting edges - */ - bool added = false; - for (const auto &edge : edges) { - auto v1 = get_boost_vertex(edge.source); - auto v2 = get_boost_vertex(edge.target); - auto e_exists = boost::edge(v1, v2, graph); - // NOLINTNEXTLINE - if (e_exists.second) continue; + // Create a std::map to store edge colors + std::map edge_colors_map; - if (edge.source == edge.target) continue; + // Create an associated property map adaptor + boost::associative_property_map> color_map(edge_colors_map); - if (edge.cost < 0 && edge.reverse_cost < 0) continue; - - E e; - // NOLINTNEXTLINE - boost::tie(e, added) = boost::add_edge(v1, v2, graph); - - E_to_id.insert(std::make_pair(e, edge.id)); - } -} - -Pgr_edgeColoring::V -Pgr_edgeColoring::get_boost_vertex(int64_t id) const { + int64_t colors = 0; + // Run the edge coloring algorithm + CHECK_FOR_INTERRUPTS(); try { - return id_to_V.at(id); + colors = boost::edge_coloring(g.graph, color_map); + } catch (boost::exception const& ex) { + throw; + } catch (std::exception &e) { + throw; } catch (...) { throw std::make_pair( - std::string("INTERNAL: something went wrong when getting the vertex descriptor"), - std::string(__PGR_PRETTY_FUNCTION__)); + std::string("INTERNAL: something went wrong while calling boost::edge_coloring"), + std::string(__PGR_PRETTY_FUNCTION__)); } -} -int64_t -Pgr_edgeColoring::get_vertex_id(V v) const { - try { - return V_to_id.at(v); - } catch (...) { - throw std::make_pair( - std::string("INTERNAL: something went wrong when getting the vertex id"), - std::string(__PGR_PRETTY_FUNCTION__)); + size_t i = 0; + boost::graph_traits::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = boost::edges(g.graph); ei != ei_end; ++ei, ++i) { + results[i].d1.id = static_cast(g[*ei].id); + + /** + * There is a problem with boost: + * Sometimes it returns a color with outsatnding large value + * When that happens changing color to: colors + 1 + */ + results[i].d2.value = get(color_map, *ei) < colors? get(color_map, *ei) + 1 : colors + 1; } -} -int64_t -Pgr_edgeColoring::get_edge_id(E e) const { - try { - return E_to_id.at(e); - } catch (...) { - throw std::make_pair( - std::string("INTERNAL: something went wrong when getting the edge id"), - std::string(__PGR_PRETTY_FUNCTION__)); - } + return results; } } // namespace functions diff --git a/src/coloring/edgeColoring_driver.cpp b/src/coloring/edgeColoring_driver.cpp deleted file mode 100644 index 85bfc54882..0000000000 --- a/src/coloring/edgeColoring_driver.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/*PGR-GNU***************************************************************** -File: edgeColoring_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2021 Veenit Kumar -Mail: 123sveenit@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/coloring/edgeColoring_driver.h" - -#include -#include - -#include "coloring/edgeColoring.hpp" - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" - -void pgr_do_edgeColoring( - 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; - - 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 = pgrouting::pgget::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; - - - std::vector results; - - pgrouting::functions::Pgr_edgeColoring fn_edgeColoring(edges); - - results = fn_edgeColoring.edgeColoring(); - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << "No results found"; - *log_msg = to_pg_msg(notice); - 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 = log.str().empty() ? *log_msg : to_pg_msg(log); - *notice_msg = notice.str().empty() ? *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/coloring/sequentialVertexColoring.c b/src/coloring/sequentialVertexColoring.c index ac34a1425b..f0ee97c5fa 100644 --- a/src/coloring/sequentialVertexColoring.c +++ b/src/coloring/sequentialVertexColoring.c @@ -1,13 +1,14 @@ /*PGR-GNU***************************************************************** File: sequentialVertexColoring.c -Generated with Template by: +Generated with Template by: Copyright (c) 2015-2026 pgRouting developers Mail: project@pgrouting.org Function's developer: Copyright (c) 2020 Ashish Kumar Mail: ashishkr23438@gmail.com + ------ This program is free software; you can redistribute it and/or modify @@ -26,10 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ -/** @file sequentialVertexColoring.c - * @brief Connecting code with postgres. - * - */ #include #include "c_common/postgres_connection.h" @@ -37,56 +34,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #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 "drivers/coloring/sequentialVertexColoring_driver.h" +#include "process/coloring_process.h" PGDLLEXPORT Datum _pgr_sequentialvertexcoloring(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(_pgr_sequentialvertexcoloring); -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_sequentialVertexColoring( - edges_sql, - - result_tuples, - result_count, - &log_msg, - ¬ice_msg, - &err_msg); - time_msg("processing pgr_sequentialVertexColoring", start_t, clock()); - - if (err_msg && (*result_tuples)) { - pfree(*result_tuples); - (*result_tuples) = NULL; - (*result_count) = 0; - } - - pgr_global_report(&log_msg, ¬ice_msg, &err_msg); - - pgr_SPI_finish(); -} 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; @@ -95,8 +52,10 @@ PGDLLEXPORT Datum _pgr_sequentialvertexcoloring(PG_FUNCTION_ARGS) { funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - process( + pgr_process_coloring( text_to_cstring(PG_GETARG_TEXT_P(0)), + + SEQUENTIAL, &result_tuples, &result_count); @@ -120,23 +79,22 @@ PGDLLEXPORT Datum _pgr_sequentialvertexcoloring(PG_FUNCTION_ARGS) { result_tuples = (II_t_rt*) funcctx->user_fctx; if (funcctx->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)); - - + 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 i; - for (i = 0; i < num; ++i) { + for (i = 0; i < numb; ++i) { nulls[i] = false; } - values[0] = Int64GetDatum(result_tuples[funcctx->call_cntr].d1.id); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].d2.value); + values[0] = Int64GetDatum(result_tuples[call_cntr].d1.id); + values[1] = Int64GetDatum(result_tuples[call_cntr].d2.value); tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/coloring/sequentialVertexColoring.cpp b/src/coloring/sequentialVertexColoring.cpp new file mode 100644 index 0000000000..6ac0e6a13b --- /dev/null +++ b/src/coloring/sequentialVertexColoring.cpp @@ -0,0 +1,121 @@ +/*PGR-GNU***************************************************************** +File: sequentialVertexColoring.cpp + +Copyright (c) 2026-2026 pgRouting developers +Mail: project@pgrouting.org + +Copyright (c) 2020 Ashish Kumar +Mail: ashishkr23438@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 "coloring/sequentialVertexColoring.hpp" + +#include +#include +#include +#include + +#include + +#include "cpp_common/interruption.hpp" + +namespace { + +using vertices_size_type = pgrouting::UndirectedGraph::vertices_size_type; + +/** @brief to get the results + * + * Uses the `colors` vector to get the results i.e. the color of every vertex. + * + * @param colors vector which contains the color of every vertex + * @param graph the graph containing the edges + * + * @returns `results` vector + */ +std::vector get_results( + const std::vector &colors, + const pgrouting::UndirectedGraph &graph) { + std::vector results; + + pgrouting::UndirectedGraph::V_i v, vend; + + for (boost::tie(v, vend) = vertices(graph.graph); v != vend; ++v) { + int64_t node = graph[*v].id; + auto color = colors[*v]; + results.push_back({{node}, {static_cast(color + 1)}}); + } + + // ordering the results in an increasing order of the node id + std::sort(results.begin(), results.end(), + [](const II_t_rt row1, const II_t_rt row2) { + return row1.d1.id < row2.d1.id; + }); + + return results; +} + +} // namespace + +namespace pgrouting { +namespace functions { + +/** @brief sequentialVertexColoring function + * + * It does all the processing and returns the results. + * + * @param graph the graph containing the edges + * + * @returns results, when results are found + * + * @see [boost::sequential_vertex_coloring] + * (https://www.boost.org/libs/graph/doc/sequential_vertex_coloring.html) + */ +std::vector sequentialVertexColoring(const pgrouting::UndirectedGraph &graph) { + using vertices_size_type = pgrouting::UndirectedGraph::vertices_size_type; + + std::vector results; + + auto i_map = boost::get(boost::vertex_index, graph.graph); + + // vector which will store the color of all the vertices in the graph + std::vector colors(boost::num_vertices(graph.graph)); + + // An iterator property map which records the color of each vertex + auto color_map = boost::make_iterator_property_map(colors.begin(), i_map); + + CHECK_FOR_INTERRUPTS(); + + try { + boost::sequential_vertex_coloring(graph.graph, color_map); + } catch (boost::exception const& ex) { + throw; + } catch (std::exception &e) { + throw; + } catch (...) { + throw std::make_pair( + std::string("INTERNAL: something went wrong while calling boost::edge_coloring"), + std::string(__PGR_PRETTY_FUNCTION__));; + } + + return get_results(colors, graph); +} + +} // namespace functions +} // namespace pgrouting + diff --git a/src/coloring/sequentialVertexColoring_driver.cpp b/src/coloring/sequentialVertexColoring_driver.cpp deleted file mode 100644 index 9753093a82..0000000000 --- a/src/coloring/sequentialVertexColoring_driver.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/*PGR-GNU***************************************************************** -File: sequentialVertexColoring_driver.cpp - -Generated with Template by: -Copyright (c) 2015-2026 pgRouting developers -Mail: project@pgrouting.org - -Function's developer: -Copyright (c) 2020 Ashish Kumar -Mail: ashishkr23438@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/coloring/sequentialVertexColoring_driver.h" - -#include -#include -#include -#include - -#include "cpp_common/pgdata_getters.hpp" -#include "cpp_common/alloc.hpp" -#include "cpp_common/assert.hpp" - -#include "coloring/sequentialVertexColoring.hpp" - -/** @file sequentialVertexColoring_driver.cpp */ - - -namespace { - -template < class G > -std::vector -pgr_sequentialVertexColoring(G &graph) { - pgrouting::functions::Pgr_sequentialVertexColoring < G > fn_sequentialVertexColoring; - auto results = fn_sequentialVertexColoring.sequentialVertexColoring(graph); - return results; -} - -} // namespace - -void -pgr_do_sequentialVertexColoring( - 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; - - 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 = pgrouting::pgget::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; - - std::vector results; - - pgrouting::UndirectedGraph undigraph; - - undigraph.insert_edges(edges); - - results = pgr_sequentialVertexColoring(undigraph); - - auto count = results.size(); - - if (count == 0) { - (*return_tuples) = NULL; - (*return_count) = 0; - notice << "No traversal found"; - *log_msg = to_pg_msg(notice); - 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/tools/scripts/code_checker.sh b/tools/scripts/code_checker.sh index 2f699ef0f9..ee04ef2fb4 100755 --- a/tools/scripts/code_checker.sh +++ b/tools/scripts/code_checker.sh @@ -29,7 +29,8 @@ INCLUDE_ORDER=" -build/include_order:src/astar/astar_process.cpp, -build/include_order:src/max_flow/maxFlow_process.cpp, -build/include_order:src/spanningTree/spanningTree_process.cpp, --build/include_order:src/allpairs/allpairs_process.cpp" +-build/include_order:src/allpairs/allpairs_process.cpp, +-build/include_order:src/coloring/coloring_process.cpp" if test -z "$DIRECTORY"; then echo "--------------------"