Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pgRouting 3.2.0 Release Notes

* pgr_bellmanFord(Combinations)
* pgr_binaryBreadthFirstSearch(Combinations)
* pgr_dagShortestPath(Combinations)
* pgr_depthFirstSearch
* pgr_dijkstraNear(One to Many)
* pgr_dijkstraNear(Many to One)
Expand Down
76 changes: 57 additions & 19 deletions doc/dagShortestPath/pgr_dagShortestPath.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,21 @@ In particular, the DAG shortest paths algorithm implemented by Boost.Graph.

.. rubric:: Availability

* Version 3.2.0

* New **experimental** function:

* pgr_dagShortestPath(Combinations)

* Version 3.0.0

* New **experimental** function

.. rubric:: Support

* **Supported versions:**
current(`3.1 <https://docs.pgrouting.org/3.1/en/pgr_dagShortestPath.html>`__)
current(`3.2 <https://docs.pgrouting.org/3.2/en/pgr_dagShortestPath.html>`__)
`3.1 <https://docs.pgrouting.org/3.1/en/pgr_dagShortestPath.html>`__
`3.0 <https://docs.pgrouting.org/3.0/en/pgr_dagShortestPath.html>`__

Description
Expand Down Expand Up @@ -74,10 +81,11 @@ Signatures

.. code-block:: none

pgr_dagShortestPath(edges_sql, from_vid, to_vid)
pgr_dagShortestPath(edges_sql, from_vid, to_vids)
pgr_dagShortestPath(edges_sql, from_vids, to_vid)
pgr_dagShortestPath(edges_sql, from_vids, to_vids)
pgr_dagShortestPath(Edges SQL, from_vid, to_vid)
pgr_dagShortestPath(Edges SQL, from_vid, to_vids)
pgr_dagShortestPath(Edges SQL, from_vids, to_vid)
pgr_dagShortestPath(Edges SQL, from_vids, to_vids)
pgr_dagShortestPath(Edges SQL, Combinations) -- Experimental on v3.2

RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost)
OR EMPTY SET
Expand All @@ -91,7 +99,7 @@ One to One

.. code-block:: none

pgr_dagShortestPath(edges_sql, from_vid, to_vid)
pgr_dagShortestPath(Edges SQL, from_vid, to_vid)
RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost)
OR EMPTY SET

Expand All @@ -109,7 +117,7 @@ One to Many

.. code-block:: none

pgr_dagShortestPath(edges_sql, from_vid, to_vids)
pgr_dagShortestPath(Edges SQL, from_vid, to_vids)
RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost)
OR EMPTY SET

Expand All @@ -127,7 +135,7 @@ Many to One

.. code-block:: none

pgr_dagShortestPath(edges_sql, from_vids, to_vid)
pgr_dagShortestPath(Edges SQL, from_vids, to_vid)
RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost)
OR EMPTY SET

Expand All @@ -145,7 +153,7 @@ Many to Many

.. code-block:: none

pgr_dagShortestPath(edges_sql, from_vids, to_vids)
pgr_dagShortestPath(Edges SQL, from_vids, to_vids)
RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost)
OR EMPTY SET

Expand All @@ -156,32 +164,62 @@ Many to Many
:start-after: -- q4
:end-before: -- q5

.. index::
single: dagShortestPath(Combinations) -- Experimental on v3.2

Combinations
...............................................................................

.. code-block:: none

pgr_dagShortestPath(Edges SQL, Combinations)
RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost)
OR EMPTY SET

:Example: Using a combinations table on a Directed Acyclic Graph.


.. literalinclude:: doc-pgr_dagShortestPath.queries
:start-after: -- q5
:end-before: -- q6

Parameters
-------------------------------------------------------------------------------

.. pgr_dagShortestPath_parameters_start

.. rubric:: Description of the parameters of the signatures

============== ================== ======== =================================================
Parameter Type Default Description
============== ================== ======== =================================================
**edges_sql** ``TEXT`` SQL query as described above.
**start_vid** ``BIGINT`` Identifier of the starting vertex of the path.
**start_vids** ``ARRAY[BIGINT]`` Array of identifiers of starting vertices.
**end_vid** ``BIGINT`` Identifier of the ending vertex of the path.
**end_vids** ``ARRAY[BIGINT]`` Array of identifiers of ending vertices.
============== ================== ======== =================================================
===================== ================== ======== =================================================
Parameter Type Default Description
===================== ================== ======== =================================================
**Edges SQL** ``TEXT`` Edges query as described below.
**Combinations SQL** ``TEXT`` Combinations query as described above.
**start_vid** ``BIGINT`` Identifier of the starting vertex of the path.
**start_vids** ``ARRAY[BIGINT]`` Array of identifiers of starting vertices.
**end_vid** ``BIGINT`` Identifier of the ending vertex of the path.
**end_vids** ``ARRAY[BIGINT]`` Array of identifiers of ending vertices.
===================== ================== ======== =================================================

.. pgr_dagShortestPath_parameters_end

Inner Query
Inner Queries
-------------------------------------------------------------------------------

Edges query
...............................................................................

.. include:: pgRouting-concepts.rst
:start-after: basic_edges_sql_start
:end-before: basic_edges_sql_end

Combinations query
...............................................................................

.. include:: pgRouting-concepts.rst
:start-after: basic_combinations_sql_start
:end-before: basic_combinations_sql_end

Results Columns
-------------------------------------------------------------------------------

Expand Down
1 change: 1 addition & 0 deletions doc/src/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pgRouting 3.2.0 Release Notes

* pgr_bellmanFord(Combinations)
* pgr_binaryBreadthFirstSearch(Combinations)
* pgr_dagShortestPath(Combinations)
* pgr_depthFirstSearch
* pgr_dijkstraNear(One to Many)
* pgr_dijkstraNear(Many to One)
Expand Down
16 changes: 16 additions & 0 deletions docqueries/dagShortestPath/doc-pgr_dagShortestPath.result
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,21 @@ SELECT * FROM pgr_dagShortestPath(
(13 rows)

-- q5
SELECT * FROM pgr_dagShortestPath(
'SELECT id, source, target, cost FROM edge_table',
'SELECT * FROM ( VALUES (1, 6), (4, 12) ) AS t(source, target)'
);
seq | path_seq | node | edge | cost | agg_cost
-----+----------+------+------+------+----------
1 | 1 | 1 | 1 | 1 | 0
2 | 2 | 2 | 4 | 1 | 1
3 | 3 | 5 | 8 | 1 | 2
4 | 4 | 6 | -1 | 0 | 3
5 | 1 | 4 | 16 | 1 | 0
6 | 2 | 9 | 15 | 1 | 1
7 | 3 | 12 | -1 | 0 | 2
(7 rows)

-- q6
ROLLBACK;
ROLLBACK
6 changes: 5 additions & 1 deletion docqueries/dagShortestPath/doc-pgr_dagShortestPath.test.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ SELECT * FROM pgr_dagShortestPath(
ARRAY[1, 4],ARRAY[12,6]
);
\echo -- q5

SELECT * FROM pgr_dagShortestPath(
'SELECT id, source, target, cost FROM edge_table',
'SELECT * FROM ( VALUES (1, 6), (4, 12) ) AS t(source, target)'
);
\echo -- q6
34 changes: 34 additions & 0 deletions include/dagShortestPath/pgr_dagShortestPath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,40 @@ class Pgr_dag {
return paths;
}

// preparation for parallel arrays
std::deque<Path> dag(
G &graph,
const std::vector<pgr_combination_t> &combinations,
bool only_cost) {
std::deque<Path> paths;

// group targets per distinct source
std::map< int64_t, std::vector<int64_t> > vertex_map;
for (const pgr_combination_t &comb : combinations) {
std::map< int64_t, std::vector<int64_t> >::iterator it = vertex_map.find(comb.source);
if (it != vertex_map.end()) {
it->second.push_back(comb.target);
} else {
std::vector<int64_t > targets{comb.target};
vertex_map[comb.source] = targets;
}
}

for (const auto &start_ends : vertex_map) {
auto result_paths = dag(
graph,
start_ends.first,
start_ends.second,
only_cost);
paths.insert(
paths.end(),
std::make_move_iterator(result_paths.begin()),
std::make_move_iterator(result_paths.end()));
}

return paths;
}

//@}

private:
Expand Down
11 changes: 3 additions & 8 deletions include/drivers/dagShortestPath/dagShortestPath_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#endif

#include "c_types/pgr_edge_t.h"
#include "c_types/pgr_combination_t.h"
#include "c_types/general_path_element_t.h"

#ifdef __cplusplus
extern "C" {
#endif

/*********************************************************
TEXT,
BIGINT,
BIGINT,
directed BOOLEAN DEFAULT true,
only_cost BOOLEAN DEFAULT false,
********************************************************/


void
do_pgr_dagShortestPath(
pgr_edge_t *data_edges,
size_t total_tuples,
pgr_combination_t *combinations,
size_t total_combinations,
int64_t *start_vidsArr,
size_t size_start_vidsArr,
int64_t *end_vidsArr,
Expand Down
20 changes: 19 additions & 1 deletion pgtap/dagShortestPath/dagShortestPath-typesCheck.sql
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@

UPDATE edge_table SET cost = sign(cost), reverse_cost = sign(reverse_cost);
SELECT plan(10);
SELECT plan(14);

SELECT has_function('pgr_dagshortestpath');

SELECT has_function('pgr_dagshortestpath', ARRAY[ 'text', 'bigint', 'bigint' ]);
SELECT has_function('pgr_dagshortestpath', ARRAY[ 'text', 'anyarray', 'bigint' ]);
SELECT has_function('pgr_dagshortestpath', ARRAY[ 'text', 'bigint', 'anyarray' ]);
SELECT has_function('pgr_dagshortestpath', ARRAY[ 'text', 'anyarray', 'anyarray' ]);
SELECT has_function('pgr_dagshortestpath', ARRAY[ 'text', 'text' ]);

SELECT function_returns('pgr_dagshortestpath', ARRAY[ 'text', 'bigint', 'bigint' ], 'setof record');
SELECT function_returns('pgr_dagshortestpath', ARRAY[ 'text', 'anyarray', 'bigint' ], 'setof record');
SELECT function_returns('pgr_dagshortestpath', ARRAY[ 'text', 'bigint', 'anyarray' ], 'setof record');
SELECT function_returns('pgr_dagshortestpath', ARRAY[ 'text', 'anyarray', 'anyarray' ], 'setof record');
SELECT function_returns('pgr_dagshortestpath', ARRAY[ 'text', 'text' ], 'setof record');

-- testing column names
SELECT bag_has(
$$SELECT proargnames from pg_proc where proname = 'pgr_dagshortestpath'$$,
$$SELECT '{"","","","seq","path_seq","node","edge","cost","agg_cost"}'::TEXT[] $$
);

SELECT bag_has(
$$SELECT proargnames from pg_proc where proname = 'pgr_dagshortestpath'$$,
$$SELECT '{"","",seq,path_seq,node,edge,cost,agg_cost}'::TEXT[] $$
);

-- parameter types
SELECT set_eq(
$$SELECT proallargtypes from pg_proc where proname = 'pgr_dagshortestpath'$$,
$$VALUES
('{25,20,20,23,23,20,20,701,701}'::OID[]),
('{25,20,2277,23,23,20,20,701,701}'::OID[]),
('{25,2277,20,23,23,20,20,701,701}'::OID[]),
('{25,2277,2277,23,23,20,20,701,701}'::OID[]),
('{25,25,23,23,20,20,701,701}'::OID[])
$$
);
24 changes: 24 additions & 0 deletions pgtap/dagShortestPath/empty_combinations_empty_result.test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
\i setup.sql

SELECT plan(1);

CREATE OR REPLACE FUNCTION foo()
RETURNS SETOF TEXT AS
$BODY$
BEGIN

RETURN query SELECT is_empty(
'SELECT seq, path_seq, node, edge, cost, agg_cost FROM pgr_dagShortestPath(
''SELECT id, source, target, cost FROM edge_table'',
''SELECT * FROM combinations_table WHERE source IN (-1)'' ) '
);
RETURN;
END
$BODY$
language plpgsql;

SELECT * FROM foo();

-- Finish the tests and clean up.
SELECT * FROM finish();
ROLLBACK;
51 changes: 51 additions & 0 deletions pgtap/dagShortestPath/many_to_many_eq_combinations.test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
\i setup.sql

SELECT plan(1);

UPDATE edge_table SET cost = sign(cost) + 0.001 * id * id, reverse_cost = sign(reverse_cost) + 0.001 * id * id;

CREATE OR REPLACE FUNCTION foo( sql_TestFunction TEXT, cant INTEGER default 18 )
RETURNS SETOF TEXT AS
$BODY$
DECLARE
sql_Combinations TEXT;
sql_Many TEXT;
BEGIN

sql_Combinations := '';
sql_Many := '';
FOR i IN 1.. cant LOOP
IF (i > 1) THEN
sql_Many := sql_Many ||', ';
END IF;
sql_Many := sql_Many || i ;
END LOOP;

FOR i IN 1.. cant LOOP
FOR j IN 1..cant LOOP
IF NOT (i = j) THEN
sql_Combinations := sql_Combinations || '(' || i || ',' || j || '),' ;
END IF;
END LOOP;
END LOOP;
sql_Combinations := trim(trailing ',' from sql_Combinations);

sql_Many := ( sql_TestFunction || '(
''SELECT id, source, target, cost FROM edge_table'',
ARRAY[' || sql_Many ||'], ARRAY[' || sql_Many || '] ) ');

sql_Combinations := ( sql_TestFunction || '(
''SELECT id, source, target, cost FROM edge_table'',
''SELECT * FROM (VALUES' || sql_Combinations ||') AS combinations (source, target)'' ) ');

RETURN query SELECT set_eq( sql_Many, sql_Combinations );
RETURN;
END
$BODY$
language plpgsql;

SELECT * FROM foo('SELECT path_seq, node, edge, cost, agg_cost FROM pgr_dagShortestPath');

-- Finish the tests and clean up.
SELECT * FROM finish();
ROLLBACK;
Loading