diff --git a/NEWS.md b/NEWS.md index cac582e6b7..7708c36dcc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -160,6 +160,10 @@ Summary of changes by function * Combinations signature promoted to official. +* pgr_sloanOrdering + + * New experimental function. + * pgr_sequentialVertexColoring * Output columns standardized to ``(node, color)`` @@ -310,6 +314,7 @@ New experimental functions * Ordering * [#2954](https://github.com/pgRouting/pgrouting/issues/2954): pgr_kingOrdering + * [#2955](https://github.com/pgRouting/pgrouting/issues/2955): pgr_sloanOrdering SQL signatures and output standardization diff --git a/doc/_static/page_history.js b/doc/_static/page_history.js index 654c17cc2a..cadff18276 100644 --- a/doc/_static/page_history.js +++ b/doc/_static/page_history.js @@ -5,7 +5,7 @@ function createInfo(file, newat, altnames = '', removedat = '') { this.removedat = removedat; } -const versionsArr = ['3.8','3.7', '3.6', '3.5', '3.4', '3.3', '3.2', '3.1', '3.0']; +const versionsArr = ['4.0', '3.8','3.7', '3.6', '3.5', '3.4', '3.3', '3.2', '3.1', '3.0']; var unsuportedArr = ['2.6', '2.5', '2.4', '2.3', '2.2', '2.1', '2.0']; var titles = [ {k: 'en', v: ['Supported versions', 'Unsupported versions']}, @@ -15,7 +15,7 @@ var titles = [ var newpages = [ - {v: '4.0', pages: ['pgr_bandwidth', 'pgr_kingOrdering']}, + {v: '4.0', pages: ['pgr_bandwidth', 'pgr_kingOrdering', 'pgr_sloanOrdering']}, {v: '3.8', pages: ['pgr_contractionDeadEnd', 'pgr_contractionLinear', 'pgr_separateCrossing', 'pgr_separateTouching']}, diff --git a/doc/ordering/CMakeLists.txt b/doc/ordering/CMakeLists.txt index ebdf746584..dcad220e9f 100644 --- a/doc/ordering/CMakeLists.txt +++ b/doc/ordering/CMakeLists.txt @@ -2,6 +2,7 @@ SET(LOCAL_FILES ordering-family.rst pgr_cuthillMckeeOrdering.rst pgr_topologicalSort.rst + pgr_sloanOrdering.rst pgr_kingOrdering.rst ) diff --git a/doc/ordering/ordering-family.rst b/doc/ordering/ordering-family.rst index 2c7d38736e..1b97a2adbb 100644 --- a/doc/ordering/ordering-family.rst +++ b/doc/ordering/ordering-family.rst @@ -24,8 +24,8 @@ Ordering - Family of functions * :doc:`pgr_cuthillMckeeOrdering` - Return reverse Cuthill-McKee ordering of an undirected graph. * :doc:`pgr_topologicalSort` - Linear ordering of the vertices for directed acyclic graph. -* :doc:`pgr_kingOrdering` - Returns the King ordering of an undirected graphs - acyclic graph. +* :doc:`pgr_sloanOrdering` - Returns the sloan ordering of an undirected graph. +* :doc:`pgr_kingOrdering` - Returns the King ordering of an undirected graph. .. official-end @@ -34,6 +34,7 @@ Ordering - Family of functions pgr_cuthillMckeeOrdering pgr_topologicalSort + pgr_sloanOrdering pgr_kingOrdering See Also diff --git a/doc/ordering/pgr_sloanOrdering.rst b/doc/ordering/pgr_sloanOrdering.rst new file mode 100644 index 0000000000..9de67c5c7d --- /dev/null +++ b/doc/ordering/pgr_sloanOrdering.rst @@ -0,0 +1,149 @@ +.. + **************************************************************************** + pgRouting Manual + Copyright(c) pgRouting Contributors + + This documentation is licensed under a Creative Commons Attribution-Share + + Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/ + **************************************************************************** + +.. index:: + single: Ordering Family ; pgr_sloanOrdering + single: pgr_sloanOrdering - Experimental on v4.0 + +| + +``pgr_sloanOrdering`` - Experimental +=============================================================================== + +``pgr_sloanOrdering`` — Returns the sloan ordering of an undirected +graph + +.. include:: experimental.rst + :start-after: warning-begin + :end-before: end-warning + +.. rubric:: Availability + +.. rubric:: Version 4.0.0 + +* New experimental function. + + +Description +------------------------------------------------------------------------------- + +The Sloan ordering algorithm reorders the vertices of a graph to reduce +bandwidth, profile, and wavefront properties, which is particularly useful for +sparse matrix computations and finite element analysis. + +* Finds a pseudoperipheral vertex pair to determine good starting points +* Uses a priority-based algorithm that balances vertex degree and distance from the start vertex. +* Aims to mininimize bandwidth (maximum difference between connected vertex indices. +* The implementation is for undirected graphs +* Typically produces better orderings than simple breadth-first approaches. +* Run time is 0.115846 seconds. + +|Boost| Boost Graph inside + +Signatures +------------------------------------------------------------------------------ +..rubric::Summary + +.. index:: + single: sloanOrdering - Experimental on v4.0 + +.. admonition:: \ \ + :class: signatures + + | pgr_sloanOrdering(`Edges SQL`_) + + | Returns set of |result_node_order| + | OR EMPTY SET + +:Example : Sloan ordering without specifying start vertex + +.. literalinclude:: sloanOrdering.queries + :start-after: -- q1 + :end-before: -- q2 + +.. Parameters, Inner Queries & result columns + +Parameters +------------------------------------------------------------------------------- + +.. include:: pgRouting-concepts.rst + :start-after: only_edge_param_start + :end-before: only_edge_param_end + +Inner Queries +------------------------------------------------------------------------------- + +Edges SQL +............................................................................... + +.. include:: pgRouting-concepts.rst + :start-after: basic_edges_sql_start + :end-before: basic_edges_sql_end + +Result columns +------------------------------------------------------------------------------- + +Returns set of ``(seq, node)`` + +=============== =========== ====================================== +Column Type Description +=============== =========== ====================================== +``seq`` ``BIGINT`` Sequence of the order starting from 1. +``node`` ``BIGINT`` New sloan ordering order. +=============== =========== ====================================== + +Additional Examples + +:Example: Sloan ordering of Original graph from Boost example (vertices 0-9). + +..graphviz:: + +graph G{ +node[shape=circle, style=filled, fillcolor=lightblue, color=black, fontcolor=black, fontsize=12]; +edge[color=black, penwidth=1.5]; + +0 -- 3; +0 -- 5; +1 -- 2; +1 -- 4; +1 -- 6; +1 -- 9; +2 -- 3; +2 -- 4; +3 -- 5; +3 -- 8; +4 -- 6; +5 -- 6; +5 -- 7; +6 -- 7; + +{rank=same; 0; 8;} +{rank=same; 3; 5; 7;} +{rank=same; 2; 4; 6;} +{rank=same; 1; 9;} + +} + +..literalinclude::sloanOrdering.queries + :start-after: --q3 + :end-before: --q4 + + +See Also +------------------------------------------------------------------------------- + +* :doc:`sampledata` +* `Boost: Sloan Ordering + `__ + +.. rubric:: Indices and tables + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/src/pgRouting-introduction.rst b/doc/src/pgRouting-introduction.rst index 4f75028b0b..fa79aa18c5 100644 --- a/doc/src/pgRouting-introduction.rst +++ b/doc/src/pgRouting-introduction.rst @@ -66,7 +66,8 @@ This Release Contributors Individuals in this release v4.0.0 (in alphabetical order) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Fan Wu +Bipasha Gayary, +Fan Wu, Regina Obe, Saloni kumari, Vicky Vergara @@ -111,6 +112,7 @@ Aryan Gupta, Ashraf Hossain, Ashish Kumar, Aurélie Bousquet, +Bipasha Gayary, Cayetano Benavent, Christian Gonzalez, Daniel Kastl, diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index 2eea712e8b..30399d42ea 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -238,6 +238,12 @@ Summary of changes by function :start-after: Version 4.0.0 :end-before: .. rubric +* pgr_sloanOrdering + + .. include:: pgr_sloanOrdering.rst + :start-after: Version 4.0.0 + :end-before: Description + * pgr_sequentialVertexColoring .. include:: pgr_sequentialVertexColoring.rst @@ -363,6 +369,7 @@ New experimental functions * Ordering * :issue:`2954`: pgr_kingOrdering + * :issue:`2955`: pgr_sloanOrdering SQL signatures and output standardization ............................................................................... diff --git a/docqueries/ordering/CMakeLists.txt b/docqueries/ordering/CMakeLists.txt index 02e5a6767b..5e23c98677 100644 --- a/docqueries/ordering/CMakeLists.txt +++ b/docqueries/ordering/CMakeLists.txt @@ -2,6 +2,7 @@ SET(LOCAL_FILES cuthillMckeeOrdering topologicalSort + sloanOrdering kingOrdering ) diff --git a/docqueries/ordering/sloanOrdering.pg b/docqueries/ordering/sloanOrdering.pg new file mode 100644 index 0000000000..7f56b7d4d4 --- /dev/null +++ b/docqueries/ordering/sloanOrdering.pg @@ -0,0 +1,46 @@ +-- CopyRight(c) pgRouting developers +-- Creative Commons Attribution-Share Alike 3.0 License : https://creativecommons.org/licenses/by-sa/3.0/ +/* -- q1 */ +SELECT * FROM pgr_sloanOrdering( + 'SELECT id, source, target, cost, reverse_cost FROM edges' + ); +/* -- q2 */ + +CREATE TABLE example_edges1 ( + id SERIAL PRIMARY KEY, + source INTEGER, + target INTEGER, + cost DOUBLE PRECISION, + reverse_cost DOUBLE PRECISION +); +/* --q3 */ +INSERT INTO example_edges1 (source, target, cost, reverse_cost) VALUES +(4, 7, 1, 1), +(7, 4, 1, 1), +(7, 9, 1, 1), +(9, 7, 1, 1), +(7, 0, 1, 1), +(0, 7, 1, 1), +(0, 2, 1, 1), +(2, 0, 1, 1), +(2, 5, 1, 1), +(5, 2, 1, 1), +(5, 9, 1, 1), +(9, 5, 1, 1), +(9, 8, 1, 1), +(8, 9, 1, 1), +(9, 1, 1, 1), +(1, 9, 1, 1), +(5, 1, 1, 1), +(1, 5, 1, 1), +(9, 6, 1, 1), +(6, 9, 1, 1), +(6, 3, 1, 1), +(3, 6, 1, 1), +(1, 3, 1, 1), +(3, 1, 1, 1); +/* --q4 */ +SELECT * FROM pgr_sloanOrdering( + 'SELECT id, source, target, cost, reverse_cost FROM example_edges1' +); +/* --q5 */ diff --git a/docqueries/ordering/sloanOrdering.result b/docqueries/ordering/sloanOrdering.result new file mode 100644 index 0000000000..5136f23e08 --- /dev/null +++ b/docqueries/ordering/sloanOrdering.result @@ -0,0 +1,86 @@ +BEGIN; +BEGIN +SET client_min_messages TO NOTICE; +SET +/* -- q1 */ +SELECT * FROM pgr_sloanOrdering( + 'SELECT id, source, target, cost, reverse_cost FROM edges' + ); + seq | node +-----+------ + 1 | 1 + 2 | 3 + 3 | 8 + 4 | 9 + 5 | 12 + 6 | 7 + 7 | 5 + 8 | 17 + 9 | 6 + 10 | 11 + 11 | 16 + 12 | 10 + 13 | 15 + 14 | 1 + 15 | 1 + 16 | 1 + 17 | 1 +(17 rows) + +/* -- q2 */ +CREATE TABLE example_edges1 ( + id SERIAL PRIMARY KEY, + source INTEGER, + target INTEGER, + cost DOUBLE PRECISION, + reverse_cost DOUBLE PRECISION +); +CREATE TABLE +/* --q3 */ +INSERT INTO example_edges1 (source, target, cost, reverse_cost) VALUES +(4, 7, 1, 1), +(7, 4, 1, 1), +(7, 9, 1, 1), +(9, 7, 1, 1), +(7, 0, 1, 1), +(0, 7, 1, 1), +(0, 2, 1, 1), +(2, 0, 1, 1), +(2, 5, 1, 1), +(5, 2, 1, 1), +(5, 9, 1, 1), +(9, 5, 1, 1), +(9, 8, 1, 1), +(8, 9, 1, 1), +(9, 1, 1, 1), +(1, 9, 1, 1), +(5, 1, 1, 1), +(1, 5, 1, 1), +(9, 6, 1, 1), +(6, 9, 1, 1), +(6, 3, 1, 1), +(3, 6, 1, 1), +(1, 3, 1, 1), +(3, 1, 1, 1); +INSERT 0 24 +/* --q4 */ +SELECT * FROM pgr_sloanOrdering( + 'SELECT id, source, target, cost, reverse_cost FROM example_edges1' +); + seq | node +-----+------ + 1 | 4 + 2 | 0 + 3 | 2 + 4 | 7 + 5 | 8 + 6 | 5 + 7 | 9 + 8 | 3 + 9 | 1 + 10 | 6 +(10 rows) + +/* --q5 */ +ROLLBACK; +ROLLBACK diff --git a/docqueries/ordering/test.conf b/docqueries/ordering/test.conf index 2a4628f652..4b7a245616 100644 --- a/docqueries/ordering/test.conf +++ b/docqueries/ordering/test.conf @@ -3,8 +3,10 @@ %main::tests = ( 'any' => { 'files' => [qw( + sloanOrdering.pg cuthillMckeeOrdering.pg topologicalSort.pg + sloanOrdering.pg kingOrdering.pg )] }, diff --git a/include/drivers/ordering_driver.hpp b/include/drivers/ordering_driver.hpp index 947c8d2c53..be9980e907 100644 --- a/include/drivers/ordering_driver.hpp +++ b/include/drivers/ordering_driver.hpp @@ -5,7 +5,11 @@ Generated with Template by: Copyright (c) 2025 pgRouting developers Mail: project@pgrouting.org -Developer: +Developers: + +Copyright (c) 2025 Bipasha Gayary +Mail: bipashagayary at gmail.com + Copyright (c) 2025 Fan Wu Mail: wifiblack0131 at gmail.com diff --git a/include/ordering/sloanOrdering.hpp b/include/ordering/sloanOrdering.hpp new file mode 100644 index 0000000000..655b279bf5 --- /dev/null +++ b/include/ordering/sloanOrdering.hpp @@ -0,0 +1,110 @@ +/*PGR-GNU***************************************************************** +File: sloanOrdering.hpp + +Generated with Template by: +Copyright (c) 2022 pgRouting developers +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 +(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_ORDERING_SLOANORDERING_HPP_ +#define INCLUDE_ORDERING_SLOANORDERING_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 "cpp_common/messages.hpp" + +namespace pgrouting { +namespace functions { + +template +class SloanOrdering : public Pgr_messages { + public: + typedef typename G::V V; + typedef typename G::E E; + typedef boost::adjacency_list Graph; + typedef boost::graph_traits::vertices_size_type size_type; + typedef boost::graph_traits::vertex_descriptor Vertex; + + std::vector + sloanOrdering(G &graph) { + std::vectorresults; + + auto i_map = boost::get(boost::vertex_index, graph.graph); + std::vector inv_perm(boost::num_vertices(graph.graph)); + std::vector colors(boost::num_vertices(graph.graph)); + auto color_map = boost::make_iterator_property_map(&colors[0], i_map, colors[0]); + auto out_deg = boost::make_out_degree_map(graph.graph); + std::vector priorities(boost::num_vertices(graph.graph)); + auto priority_map = boost::make_iterator_property_map(&priorities[0], i_map, priorities[0]); + + CHECK_FOR_INTERRUPTS(); + + try { + boost::sloan_ordering(graph.graph, inv_perm.begin(), color_map, out_deg, priority_map); + } catch (boost::exception const& ex) { + (void)ex; + throw; + } catch (std::exception &e) { + (void)e; + throw; + } catch (...) { + throw; + } + + results = get_results(inv_perm, graph); + + return results; + } + + private: + std::vector get_results( + std::vector & inv_perm, + const G &graph) { + std::vector results; + for (std::vector::const_iterator i = inv_perm.begin(); + i != inv_perm.end(); ++i) { + log << inv_perm[*i] << " "; + results.push_back(static_cast(graph.graph[*i].id)); + } + + return results; +} +}; +} // namespace functions +} // namespace pgrouting + +#endif // INCLUDE_ORDERING_SLOANORDERING_HPP_ diff --git a/include/process/ordering_process.h b/include/process/ordering_process.h index ea633eef49..392b5e0ef5 100644 --- a/include/process/ordering_process.h +++ b/include/process/ordering_process.h @@ -2,6 +2,8 @@ File: ordering_process.h Function's developer: +Copyright (c) 2025 Bipasha Gayary +Mail: bipashagayary at gmail.com Copyright (c) 2025 Fan Wu Mail: wifiblack0131 at gmail.com diff --git a/pgtap/ordering/sloan/edge_cases.pg b/pgtap/ordering/sloan/edge_cases.pg new file mode 100644 index 0000000000..5e55d8c9a9 --- /dev/null +++ b/pgtap/ordering/sloan/edge_cases.pg @@ -0,0 +1,105 @@ + +/*PGR-GNU***************************************************************** + +Copyright (c) 2025 pgRouting developers +Mail: project@pgrouting.org + +------ +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*/ +BEGIN; + +UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost); +SELECT CASE WHEN NOT min_version('4.0.0') THEN plan(1) ELSE plan(6) END; + + +CREATE OR REPLACE FUNCTION edge_cases() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + +IF NOT min_version('4.0.0') THEN + RETURN QUERY + SELECT skip(1, 'pgr_sloanOrdering is new on 4.0.0'); + RETURN; +END IF; + +-- 0 edge, 0 vertex test + +PREPARE q1 AS +SELECT * FROM pgr_sloanOrdering('SELECT id, source, target, cost, reverse_cost FROM edges WHERE id > 18'); + +RETURN QUERY +SELECT lives_ok('q1', 'Graph with 0 edge and 0 vertex -> Should live'); + +-- 6 -> 6 (1 vertex test) + +PREPARE q2 AS +SELECT * FROM pgr_sloanOrdering('SELECT id, source, source AS target, cost, reverse_cost FROM edges WHERE id = 2'); + +RETURN QUERY +SELECT set_eq('q2',$$VALUES (1, 6)$$, '4: Same node returned'); + +-- 3 -- 7 -- 3; 2 vertices test (connected) + +PREPARE q3 AS +SELECT * FROM pgr_sloanOrdering('SELECT id, source, target, cost, reverse_cost FROM edges WHERE id = 7'); + +RETURN QUERY +SELECT set_eq('q3',$$VALUES (1,3), (2,7)$$, '3 -- 7 -- 3; Does not matter if 7 comes first or 3'); + + +PERFORM todo_start('Its the same graph but giving different results'); + +-- 7 -- 3 -- 7; 2 vertices test (connected) + +PREPARE q4 AS +SELECT * FROM pgr_sloanOrdering('SELECT id, target AS source, source AS target, cost, reverse_cost FROM edges WHERE id = 7'); + +RETURN QUERY +SELECT set_eq('q4',$$VALUES (1,3), (2,7)$$, '7 -- 3 -- 7; Does not matter if 7 comes first or 3'); + +PERFORM todo_end(); + + +PERFORM todo_start('Graph is disconnected, check if algo works for disconnected graphs'); + +-- 3 -- 3; 7 -- 7; 2 vertices test (isolated) + +PREPARE q5 AS +SELECT * FROM pgr_sloanOrdering('SELECT id, source, source AS target, cost, reverse_cost FROM edges WHERE id = 7 +UNION +SELECT id, target AS source, target, cost, reverse_cost FROM edges WHERE id = 7'); + +RETURN QUERY +SELECT set_eq('q5',$$VALUES (1, 3), (2, 7)$$, 'Should have both vertices'); + +-- 3 vertices test (connected) + +PREPARE q6 AS +SELECT * +FROM pgr_sloanOrdering('SELECT id, source, target, cost, reverse_cost FROM edges WHERE id <= 2'); + +RETURN QUERY +SELECT set_eq('q6',$$VALUES (6, 1), (7, 3), (4, 6)$$, 'Ordering of three connected vertices'); + +PERFORM todo_end(); +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT edge_cases(); + + +SELECT * FROM finish(); +ROLLBACK; diff --git a/pgtap/ordering/sloan/inner_query.pg b/pgtap/ordering/sloan/inner_query.pg new file mode 100644 index 0000000000..c16feeadd4 --- /dev/null +++ b/pgtap/ordering/sloan/inner_query.pg @@ -0,0 +1,46 @@ + +/*PGR-GNU***************************************************************** + +Copyright (c) 2025 pgRouting developers +Mail: project@pgrouting.org + +------ +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*/ +BEGIN; + +UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost); +SELECT CASE WHEN NOT min_version('4.0.0') THEN plan(1) ELSE plan(54) END; + +CREATE OR REPLACE FUNCTION inner_query() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + +IF NOT min_version('4.0.0') THEN + RETURN QUERY + SELECT skip(1, 'pgr_sloanOrdering is new on 4.0.0'); + RETURN; +END IF; + +RETURN QUERY +SELECT style_dijkstra('pgr_sloanOrdering(', ')'); + +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT inner_query(); + +SELECT finish(); +ROLLBACK; diff --git a/pgtap/ordering/sloan/no_crash_test.pg b/pgtap/ordering/sloan/no_crash_test.pg new file mode 100644 index 0000000000..b979cc10be --- /dev/null +++ b/pgtap/ordering/sloan/no_crash_test.pg @@ -0,0 +1,62 @@ + +/*PGR-GNU***************************************************************** + +Copyright (c) 2025 pgRouting developers +Mail: project@pgrouting.org + +------ +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*/ +BEGIN; + +UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost); +SELECT CASE WHEN NOT min_version('4.0.0') THEN plan(1) ELSE plan(4) END; + +PREPARE edges AS +SELECT id, source, target, cost, reverse_cost FROM edges; + +PREPARE null_ret AS +SELECT id FROM vertices WHERE id IN (-1); + +PREPARE null_ret_arr AS +SELECT array_agg(id) FROM vertices WHERE id IN (-1); + + + +CREATE OR REPLACE FUNCTION no_crash() +RETURNS SETOF TEXT AS +$BODY$ +DECLARE +params TEXT[]; +subs TEXT[]; +BEGIN + IF NOT min_version('4.0.0') THEN + RETURN QUERY + SELECT skip(1, 'pgr_sloanOrdering is new on 4.0.0'); + RETURN; + END IF; + + params = ARRAY['$$SELECT id, source, target, cost, reverse_cost FROM edges$$']::TEXT[]; + subs = ARRAY[ 'NULL' ]::TEXT[]; + + RETURN query SELECT * FROM no_crash_test('pgr_sloanOrdering', params, subs); + +END +$BODY$ +LANGUAGE plpgsql VOLATILE; + + +SELECT no_crash(); + +SELECT finish(); +ROLLBACK; diff --git a/pgtap/ordering/sloan/types_check.pg b/pgtap/ordering/sloan/types_check.pg new file mode 100644 index 0000000000..950c1dd144 --- /dev/null +++ b/pgtap/ordering/sloan/types_check.pg @@ -0,0 +1,55 @@ + +/*PGR-GNU***************************************************************** + +Copyright (c) 2025 pgRouting developers +Mail: project@pgrouting.org + +------ +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*/ +BEGIN; + +SELECT CASE WHEN min_version('4.0.0') THEN plan(5) ELSE plan(1) END; + +CREATE OR REPLACE FUNCTION types_check() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('4.0.0') THEN + RETURN QUERY SELECT skip(1, 'Function is new on 4.0.0'); + RETURN; + END IF; + + RETURN QUERY SELECT has_function('pgr_sloanordering'); + RETURN QUERY SELECT has_function('pgr_sloanordering', ARRAY['text']); + RETURN QUERY SELECT function_returns('pgr_sloanordering', ARRAY['text'], 'setof record'); + + RETURN QUERY + SELECT function_args_eq('pgr_sloanordering', + $$SELECT '{"", seq, node}'::TEXT[] $$ + ); + + RETURN QUERY SELECT function_types_eq('pgr_sloanordering', + $$VALUES + ('{text,int8,int8}'::TEXT[]) + $$ + ); +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT types_check(); + +SELECT * FROM finish(); +ROLLBACK; diff --git a/sql/ordering/CMakeLists.txt b/sql/ordering/CMakeLists.txt index 7886a6dfc3..4f86a08284 100644 --- a/sql/ordering/CMakeLists.txt +++ b/sql/ordering/CMakeLists.txt @@ -1,14 +1,12 @@ SET(LOCAL_FILES _cuthillMckeeOrdering.sql cuthillMckeeOrdering.sql + _sloanOrdering.sql + sloanOrdering.sql _kingOrdering.sql kingOrdering.sql ) -# Do not modify below this line - - - foreach (f ${LOCAL_FILES}) configure_file(${f} ${f}) list(APPEND PACKAGE_SQL_FILES ${CMAKE_CURRENT_BINARY_DIR}/${f}) diff --git a/sql/ordering/_sloanOrdering.sql b/sql/ordering/_sloanOrdering.sql new file mode 100644 index 0000000000..0a5ee2c58f --- /dev/null +++ b/sql/ordering/_sloanOrdering.sql @@ -0,0 +1,46 @@ +/*PGR-GNU***************************************************************** +File: _sloanOrdering.sql + +Generated with Template by: +Copyright (c) 2025 pgRouting developers +Mail: project@pgrouting.org + +Function's 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 +(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*/ + +---------------------------- +-- _pgr_sloanOrdering +---------------------------- + +--v4.0.0 +CREATE FUNCTION _pgr_sloanOrdering( + TEXT, + OUT seq BIGINT, + OUT node BIGINT + ) + +RETURNS SETOF RECORD AS +'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +COMMENT ON FUNCTION _pgr_sloanOrdering(TEXT) +IS 'pgRouting internal function'; diff --git a/sql/ordering/sloanOrdering.sql b/sql/ordering/sloanOrdering.sql new file mode 100644 index 0000000000..38960406a9 --- /dev/null +++ b/sql/ordering/sloanOrdering.sql @@ -0,0 +1,52 @@ +/*PGR-GNU***************************************************************** +File: sloanOrdering.sql + +Generated with Template by: +Copyright (c) 2025 pgRouting developers +Mail: project@pgrouting.org + +Function's 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 +(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*/ + +--v4.0.0 +CREATE FUNCTION pgr_sloanOrdering( + TEXT, -- edges_sql (required) + OUT seq BIGINT, + OUT node BIGINT) +RETURNS SETOF RECORD AS +$BODY$ + SELECT seq, node + FROM _pgr_sloanOrdering(_pgr_get_statement($1)); +$BODY$ +LANGUAGE SQL VOLATILE STRICT; + +-- COMMENTS + +COMMENT ON FUNCTION pgr_sloanOrdering(TEXT) +IS 'pgr_sloanOrdering +- EXPERIMENTAL +- Parameters: + - Edges SQL with columns: id, source, target, cost [,reverse_cost] + +- Documentation: + - ${PROJECT_DOC_LINK}/pgr_sloanOrdering.html +'; diff --git a/sql/sigs/pgrouting--4.0.sig b/sql/sigs/pgrouting--4.0.sig index 0f0ef7acfc..90ec9ccaff 100644 --- a/sql/sigs/pgrouting--4.0.sig +++ b/sql/sigs/pgrouting--4.0.sig @@ -239,6 +239,8 @@ pgr_separatecrossing(text,double precision,boolean) pgr_separatetouching(text,double precision,boolean) _pgr_sequentialvertexcoloring(text) pgr_sequentialvertexcoloring(text) +_pgr_sloanordering(text) +pgr_sloanordering(text) _pgr_stoerwagner(text) pgr_stoerwagner(text) _pgr_strongcomponents(text) diff --git a/src/ordering/CMakeLists.txt b/src/ordering/CMakeLists.txt index 0eaa075a9a..71f25541c5 100644 --- a/src/ordering/CMakeLists.txt +++ b/src/ordering/CMakeLists.txt @@ -2,6 +2,7 @@ ADD_LIBRARY(ordering OBJECT kingOrdering.c cuthillMckeeOrdering.c cuthillMckeeOrdering_driver.cpp + sloanOrdering.c ordering_driver.cpp ordering_process.cpp ) diff --git a/src/ordering/ordering_driver.cpp b/src/ordering/ordering_driver.cpp index ae7691ef59..67e7e869a8 100644 --- a/src/ordering/ordering_driver.cpp +++ b/src/ordering/ordering_driver.cpp @@ -4,9 +4,14 @@ Generated with Template by: Copyright (c) 2025 pgRouting developers Mail: project@pgrouting.org -Developer: +Developers: + +Copyright (c) 2025 Bipasha Gayary +Mail: bipashagayary at gmail.com + Copyright (c) 2025 Fan Wu Mail: wifiblack0131 at gmail.com + ------ This program is free software; you can redistribute it and/or modify @@ -38,9 +43,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "cpp_common/alloc.hpp" #include "cpp_common/assert.hpp" +#include "ordering/sloanOrdering.hpp" #include "ordering/kingOrdering.hpp" - +namespace { +template +std::vector +sloanOrdering(G &graph) { + pgrouting::functions::SloanOrdering fn_sloanOrdering; + auto results = fn_sloanOrdering.sloanOrdering(graph); + return results; +} +} void do_ordering( @@ -77,32 +91,38 @@ do_ordering( auto edges = get_edges(std::string(edges_sql), true, false); if (edges.empty()) { *notice_msg = to_pg_msg("No edges found"); - *return_tuples = NULL; + *return_tuples = nullptr; *return_count = 0; return; } hint = ""; std::vector results; + auto vertices(pgrouting::extract_vertices(edges)); UndirectedGraph undigraph(vertices); undigraph.insert_edges(edges); - if (which == 2) { + if (which == 0) { + results = sloanOrdering(undigraph); + } else if (which == 2) { results = kingOrdering(undigraph); } + auto count = results.size(); if (count == 0) { *notice_msg = to_pg_msg("No results found \n"); - *return_tuples = NULL; + *err_msg = to_pg_msg(err); + *return_tuples = nullptr; *return_count = 0; return; } (*return_tuples) = pgr_alloc(count, (*return_tuples)); - for (size_t i = 0; i < count; i++) { - *((*return_tuples) + i) = results[i]; + + for (size_t i = 0; i < count; ++i) { + (*return_tuples)[i] = results[i]; } (*return_count) = count; diff --git a/src/ordering/ordering_process.cpp b/src/ordering/ordering_process.cpp index 37b7d20d5b..336d4b475f 100644 --- a/src/ordering/ordering_process.cpp +++ b/src/ordering/ordering_process.cpp @@ -4,8 +4,9 @@ File: ordering_process.cpp Copyright (c) 2025 pgRouting developers Mail: project@pgrouting.org -Developer: +Developers: Copyright (c) 2025 pgRouting developers +Mail: bipashagayary at gmail.com Mail: wifiblack0131 at gmail.com ------ @@ -44,7 +45,6 @@ extern "C" { which = 1 -> cuthillmckee which = 2 -> king - This is c++ code, linked as C code, because pgr_process_foo is called from C code */ void pgr_process_ordering( @@ -65,7 +65,8 @@ void pgr_process_ordering( std::string(edges_sql), which, result_tuples, result_count, - &log_msg, ¬ice_msg, &err_msg); + &log_msg , ¬ice_msg, &err_msg); + if (which == 0) { time_msg(std::string(" processing pgr_sloanOrdering").c_str(), start_t, clock()); } else if (which == 1) { diff --git a/src/ordering/sloanOrdering.c b/src/ordering/sloanOrdering.c new file mode 100644 index 0000000000..25f61676b4 --- /dev/null +++ b/src/ordering/sloanOrdering.c @@ -0,0 +1,104 @@ +/*PGR-GNU***************************************************************** +File: sloanOrdering.c + +Generated with Template by: +Copyright (c) 2025 pgRouting developers +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 +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#include +#include "c_common/postgres_connection.h" + +#include "c_common/debug_macro.h" +#include "c_common/e_report.h" +#include "c_common/time_msg.h" + +#include "process/ordering_process.h" + +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; + + 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)), + 0, /* Sloan */ + &result_tuples, + &result_count); + + funcctx->max_calls = result_count; + funcctx->user_fctx = result_tuples; + if (get_call_result_type(fcinfo, NULL, &tuple_desc) + != TYPEFUNC_COMPOSITE) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context " + "that cannot accept type record"))); + } + + funcctx->tuple_desc = tuple_desc; + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (int64_t*) 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)); + + + 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]); + + tuple = heap_form_tuple(tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } else { + SRF_RETURN_DONE(funcctx); + } +}