From 620c054daecfb7bc5fb1c48855d7b3ef6e72d11b Mon Sep 17 00:00:00 2001 From: cvvergara Date: Thu, 20 Mar 2025 13:21:56 -0600 Subject: [PATCH 01/11] (contraction/pgtap) the tests that need to pass --- .../edge_cases/compare_dijkstra_combined.pg | 122 +++++++ .../edge_cases/compare_dijkstra_deadend.pg | 110 ++++++ .../edge_cases/compare_dijkstra_linear.pg | 125 +++++++ .../contraction/edge_cases/edge_cases.pg | 274 +++++++++++++++ .../edge_cases/edge_cases_deadend.pg | 320 ++++++++++++++++++ .../edge_cases/edge_cases_linear.pg | 305 +++++++++++++++++ .../edge_cases/linear/directed/edge_cases.pg | 10 +- .../contraction/edge_cases/remaining_tests.pg | 22 +- pgtap/contraction/contraction/inner_query.pg | 105 ++++++ .../contraction/contraction/no_crash_test.pg | 18 +- pgtap/contraction/contraction/types_check.pg | 55 ++- tools/testers/contraction_tapfuncs.sql | 137 ++++++++ 12 files changed, 1562 insertions(+), 41 deletions(-) create mode 100644 pgtap/contraction/contraction/edge_cases/compare_dijkstra_combined.pg create mode 100644 pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg create mode 100644 pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg create mode 100644 pgtap/contraction/contraction/edge_cases/edge_cases.pg create mode 100644 pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg create mode 100644 pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg create mode 100644 pgtap/contraction/contraction/inner_query.pg diff --git a/pgtap/contraction/contraction/edge_cases/compare_dijkstra_combined.pg b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_combined.pg new file mode 100644 index 00000000000..b90611db147 --- /dev/null +++ b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_combined.pg @@ -0,0 +1,122 @@ +/*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('3.8.0') THEN plan(654) ELSE plan(4) END; + +UPDATE edges SET cost = sign(cost) + 0.001 * id * id, reverse_cost = sign(reverse_cost) + 0.001 * id * id; + +ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; +ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; + +CREATE OR REPLACE FUNCTION check_cg(BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY SELECT skip(1, 'contraction function/signature is new on 3.8.0'); + RETURN; + END IF; + + IF $1 THEN + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES + ('v',7,ARRAY[1,3],-1,-1), + ('v',4,ARRAY[2],-1,-1), + ('v',14,ARRAY[13],-1,-1), + ('v',8,ARRAY[9],'-1','-1'), + ('v',6,ARRAY[5],'-1','-1') $$); + + RETURN QUERY + SELECT is_empty($$SELECT id FROM edges WHERE is_new$$); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (16,17,'1.225'::TEXT,'1.225'::TEXT), + (10,15,'-0.991','1.009'), + (12,17,'1.169','-0.831'), + (15,16,'1.256','1.256'), + (6, 10, '-0.996', '1.004'), + (6, 7, '1.016', '1.016'), + (10, 11, '1.025', '-0.975'), + (7, 11, '1.064', '1.064'), + (11, 16, '1.081', '1.081'), + (11, 12, '1.121', '-0.879'), + (8, 12, '1.144', '-0.856'), + (7, 8, '1.100', '1.100')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + ELSE + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES + ('v',7,ARRAY[1,3],-1,-1), + ('v',4,ARRAY[2],-1,-1), + ('v',14,ARRAY[13],-1,-1), + ('e',-3,ARRAY[8,9],7,12), + ('e',-4,ARRAY[17],16,12), + ('e',-2,ARRAY[15],10,16), + ('e',-1,ARRAY[5,6],10,7)$$); + + RETURN QUERY + SELECT set_eq( + $$SELECT id FROM edges WHERE is_new$$, + $$SELECT unnest(ARRAY[19, 20, 21,22])$$ + ); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (10, 11, '1.025', '-0.975'), + (7, 11, '1.064', '1.064'), + (11, 16, '1.081', '1.081'), + (11, 12, '1.121', '-0.879'), + (10,16,'2.265','-1.000'), + (16,12,'2.394','-1.000'), + (10,7,'2.020','-1.000'), + (7,12,'2.244','-1.000')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + + END IF; + DEALLOCATE PREPARE c_expected_graph; +END +$BODY$ +LANGUAGE plpgsql; + + +CALL create_contracted_graph(false,'pgr_contraction', ARRAY[1,2]); +SELECT check_cg(false); +SELECT compare_dijkstra_contraction(false); + +CALL create_contracted_graph(true,'pgr_contraction', ARRAY[1,2]); +SELECT check_cg(true); +SELECT compare_dijkstra_contraction(true); + +SELECT finish(); +ROLLBACK; diff --git a/pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg new file mode 100644 index 00000000000..e96cb05ac27 --- /dev/null +++ b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg @@ -0,0 +1,110 @@ +/*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('3.8.0') THEN plan(654) ELSE plan(4) END; +UPDATE edges SET cost = sign(cost) + 0.001 * id * id, reverse_cost = sign(reverse_cost) + 0.001 * id * id; + +ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; +ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; + +CREATE OR REPLACE FUNCTION check_cg(BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY SELECT skip(1, 'contraction function/signature is new on 3.8.0'); + RETURN; + END IF; + + IF $1 THEN + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('v',7,ARRAY[1,3],-1,-1), ('v',4,ARRAY[2],-1,-1), ('v',8,ARRAY[9],-1,-1), + ('v',6,ARRAY[5],-1,-1), ('v',14,ARRAY[13],-1,-1) $$); + + RETURN QUERY SELECT is_empty($$SELECT id FROM edges WHERE is_new$$); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (16,17,'1.225'::TEXT,'1.225'::TEXT), + (10,15,'-0.991','1.009'), + (12,17,'1.169','-0.831'), + (15,16,'1.256','1.256'), + (6, 10, '-0.996', '1.004'), + (6, 7, '1.016', '1.016'), + (10, 11, '1.025', '-0.975'), + (7, 11, '1.064', '1.064'), + (11, 16, '1.081', '1.081'), + (11, 12, '1.121', '-0.879'), + (8, 12, '1.144', '-0.856'), + (7, 8, '1.100', '1.100')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + ELSE + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('v',7,ARRAY[1,3],-1,-1), ('v',4,ARRAY[2],-1,-1), ('v',8,ARRAY[9],-1,-1), + ('v',6,ARRAY[5],-1,-1), ('v',14,ARRAY[13],-1,-1) $$); + + RETURN QUERY SELECT is_empty($$SELECT id FROM edges WHERE is_new$$); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (6, 10, '-0.996', '1.004'), + (6, 7, '1.016', '1.016'), + (10, 11, '1.025', '-0.975'), + (7, 11, '1.064', '1.064'), + (11, 16, '1.081', '1.081'), + (11, 12, '1.121', '-0.879'), + (8, 12, '1.144', '-0.856'), + (7, 8, '1.100', '1.100'), + (16,17,'1.225'::TEXT,'1.225'::TEXT), + (10,15,'-0.991','1.009'), + (12,17,'1.169','-0.831'), + (15,16,'1.256','1.256')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + + END IF; + DEALLOCATE PREPARE c_expected_graph; +END +$BODY$ +LANGUAGE plpgsql; + + +CALL create_contracted_graph(false,'pgr_contraction', ARRAY[1]); +SELECT check_cg(false); +SELECT compare_dijkstra_contraction(false); + +CALL create_contracted_graph(true,'pgr_contraction', ARRAY[1]); +SELECT check_cg(true); +SELECT compare_dijkstra_contraction(true); + +SELECT finish(); +ROLLBACK; diff --git a/pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg new file mode 100644 index 00000000000..87be224389a --- /dev/null +++ b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg @@ -0,0 +1,125 @@ +/*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('3.8.0') THEN plan(654) ELSE plan(4) END; +UPDATE edges SET cost = sign(cost) + 0.001 * id * id, reverse_cost = sign(reverse_cost) + 0.001 * id * id; + +ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; +ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; + +CREATE OR REPLACE FUNCTION check_cg(BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY SELECT skip(1, 'contraction function/signature is new on 3.8.0'); + RETURN; + END IF; + + IF $1 THEN + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('e',-1,ARRAY[3],7,1), ('e',-2,ARRAY[3],1,7)$$, 'The edges') ; + + RETURN QUERY + SELECT set_eq( + $$SELECT id FROM edges WHERE is_new$$, + $$SELECT unnest(ARRAY[19, 20])$$, 'The vertices' + ); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (16,17,'1.225'::TEXT,'1.225'::TEXT), + (10,15,'-0.991','1.009'), + (12,17,'1.169','-0.831'), + (15,16,'1.256','1.256'), + (6, 10, '-0.996', '1.004'), + (6, 7, '1.016', '1.016'), + (10, 11, '1.025', '-0.975'), + (7, 11, '1.064', '1.064'), + (11, 16, '1.081', '1.081'), + (11, 12, '1.121', '-0.879'), + (8, 12, '1.144', '-0.856'), + (7, 8, '1.100', '1.100'), + (1,7,'2.085','-1.000'), + (7,1,'2.085','-1.000'), + (5, 6, '1.001', '1.001'), + (8, 9, '1.196', '1.196'), + (2, 4, '1.289', '1.289'), + (13, 14, '1.324', '1.324')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + ELSE + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('e',-3,ARRAY[17],16,12), ('e',-2,ARRAY[3],7,1), ('e', -1, ARRAY[15], 10, 16)$$) ; + + RETURN QUERY + SELECT set_eq( + $$SELECT id FROM edges WHERE is_new$$, + $$SELECT unnest(ARRAY[19, 20, 21])$$ + ); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (6, 10, '-0.996', '1.004'), + (6, 7, '1.016', '1.016'), + (10, 11, '1.025', '-0.975'), + (7, 11, '1.064', '1.064'), + (11, 16, '1.081', '1.081'), + (11, 12, '1.121', '-0.879'), + (8, 12, '1.144', '-0.856'), + (7, 8, '1.100', '1.100'), + (10,16,'2.265','-1.000'), + (7,1,'2.085','-1.000'), + (16,12,'2.394','-1.000'), + (5, 6, '1.001', '1.001'), + (8, 9, '1.196', '1.196'), + (2, 4, '1.289', '1.289'), + (13, 14, '1.324', '1.324')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + + END IF; + DEALLOCATE PREPARE c_expected_graph; +END +$BODY$ +LANGUAGE plpgsql; + + +CALL create_contracted_graph(false,'pgr_contraction', ARRAY[2]); +SELECT check_cg(false); +SELECT compare_dijkstra_contraction(false); + +CALL create_contracted_graph(true,'pgr_contraction', ARRAY[2]); +SELECT check_cg(true); +SELECT compare_dijkstra_contraction(true); + +SELECT finish(); +ROLLBACK; diff --git a/pgtap/contraction/contraction/edge_cases/edge_cases.pg b/pgtap/contraction/contraction/edge_cases/edge_cases.pg new file mode 100644 index 00000000000..8d65388d202 --- /dev/null +++ b/pgtap/contraction/contraction/edge_cases/edge_cases.pg @@ -0,0 +1,274 @@ +/*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 min_version('3.8.0') THEN plan(128) ELSE plan(1) END; + +CREATE TABLE test_deadend ( + id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + source BIGINT, + target BIGINT, + cost BIGINT default 1, + reverse_cost BIGINT default 1, + dead_case INTEGER +); + +/* 2 -- {3 -- 4} ; 3 -- 4 */ +INSERT INTO test_deadend(source, target, dead_case) +VALUES +(2, 3, 0), +(2, 4, 0), +(3, 4, 0); + +INSERT INTO test_deadend(source, target, cost, reverse_cost, dead_case) +VALUES +/* 2->{3->4 [dir=both]} [dir=both]; 1->2 */ +(1, 2, 1, -1, 1), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1 */ +(2, 1, 1, -1, 2), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1 [dir=both] */ +(1, 2, 1, 1, 3), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1,2->1 */ +(2, 1, 1, -1, 4), +(2, 1, 1, -1, 4), + +/* 2->{3->4 [dir=both]} [dir=both]; {2,3}->1 */ +(2, 1, 1, -1, 5), +(3, 1, 1, -1, 5), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1;2->1;3->1 */ +(2, 1, 1, -1, 6), +(2, 1, 1, -1, 6), +(3, 1, 1, -1, 6); + +CREATE OR REPLACE FUNCTION edge_cases_sampledata(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + -- SINGLE edge + + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{}',$$||directed||$$)$$, $$ VALUES ('v',6,ARRAY[5]::BIGINT[]) $$, '5 <=> 6: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{6}',$$||directed||$$) $$, $$ VALUES ('v',6,ARRAY[5]::BIGINT[]) $$, '5 <=> 6: Directed = ' || directed || ',forbid 5'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{5}',$$||directed||$$) $$, $$ VALUES ('v',5,ARRAY[6]::BIGINT[]) $$, '5 <=> 6: Directed = ' || directed || ',forbid 6'); + RETURN QUERY + SELECT is_empty($$"graph1" ('1','{5,6}',$$||directed||$$) $$, '5 <=> 6: Directed = ' || directed || ',forbid 5,6'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{}',$$||directed||$$)$$, $$ VALUES ('v',15,ARRAY[10]::BIGINT[]) $$, '10 -> 15: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{10}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[15]::BIGINT[]) $$, '10 -> 15: Directed = ' || directed || ',forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{15}',$$||directed||$$)$$, $$ VALUES ('v',15,ARRAY[10]::BIGINT[]) $$, '10 -> 15: Directed = ' || directed || ',forbid 15'); + RETURN QUERY + SELECT is_empty($$"graph1" ('3','{10,15}',$$||directed||$$) $$, '5 <=> 6: Directed = ' || directed || ',forbid 10,15'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[8]::BIGINT[]) $$, '8 -> 12: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{8}',$$||directed||$$)$$, $$ VALUES ('v',8,ARRAY[12]::BIGINT[]) $$, '8 -> 12: Directed = ' || directed || ',forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{12}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[8]::BIGINT[]) $$, '8 -> 12: Directed = ' || directed || ',forbid 12'); + + -- TWO edges + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{}',$$||directed||$$)$$, $$ VALUES ('v',15,ARRAY[6,10]::BIGINT[]) $$, '15 -> 10 -> 6: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{6}',$$||directed||$$)$$, $$ VALUES ('v',6,ARRAY[10,15]::BIGINT[]) $$, '15 -> 10 -> 6: Directed = ' || directed || ',forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{10}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6,15]::BIGINT[]) $$, '15 -> 10 -> 6: Directed = ' || directed || ',forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{15}',$$||directed||$$)$$, $$ VALUES ('v',15,ARRAY[6,10]::BIGINT[]) $$, '15 -> 10 -> 6: Directed = ' || directed || ',forbid 15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{6,10}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[15]::BIGINT[]) $$, '15 -> 10 -> 6: Directed = ' || directed || ',forbid 6,10'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,3','{6,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed = ' || directed || ',forbid 6,15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{10,15}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]::BIGINT[]) $$, '15 -> 10 -> 6: Directed = ' || directed || ',forbid 10,15'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,3','{6,10,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed = ' || directed || ',forbid 6,10,15'); + + + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{}',$$||directed||$$)$$, $$ VALUES ('v',8,ARRAY[11,12]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8}',$$||directed||$$)$$, $$ VALUES ('v',8,ARRAY[11,12]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 8'); + + IF directed THEN + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{11}',$$||directed||$$)$$, $$ VALUES ('v',8,ARRAY[12]::BIGINT[]), ('v',11,ARRAY[12]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8,11}',$$||directed||$$)$$, $$ VALUES ('v',8,ARRAY[12]::BIGINT[]), ('v',11,ARRAY[12]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 8,11'); + ELSE + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{11}',$$||directed||$$)$$, $$ VALUES ('v',11,ARRAY[8,12]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 11'); + RETURN QUERY + SELECT is_empty($$"graph1" ('11,12','{8,11}',$$||directed||$$)$$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 8,11'); + END IF; + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{12}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[8,11]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8,12}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[11]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{11,12}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[8]::BIGINT[]) $$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 11,12'); + RETURN QUERY + SELECT is_empty($$"graph1" ('11,12','{8,11,12}',$$||directed||$$)$$, '11 -> 12 <- 8: Directed = ' || directed || ',forbid 8,11,12'); + + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]),('v',12,ARRAY[8]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6}',$$||directed||$$)$$, $$ VALUES ('v',6,ARRAY[10]::BIGINT[]), ('v',12,ARRAY[8]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]::BIGINT[]), ('v',8,ARRAY[12]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{10}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]::BIGINT[]), ('v',12,ARRAY[8]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{12}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]::BIGINT[]), ('v',12,ARRAY[8]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8}',$$||directed||$$)$$, $$ VALUES ('v',6,ARRAY[10]::BIGINT[]), ('v',8,ARRAY[12]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6,8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,10}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[8]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,12}',$$||directed||$$)$$, $$ VALUES ('v',6,ARRAY[10]::BIGINT[]), ('v',12,ARRAY[8]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,10}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]::BIGINT[]), ('v',8,ARRAY[12]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 8,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,12}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8,10}',$$||directed||$$)$$, $$ VALUES ('v',8,ARRAY[12]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6,8,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8,12}',$$||directed||$$)$$, $$ VALUES ('v',6,ARRAY[10]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6,8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,10,12}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[8]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6,10,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,10,12}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[6]::BIGINT[]) $$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 8,10,12'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,12','{6,8,10,12}',$$||directed||$$)$$, '10 -> 6, 8 -> 12: Directed = ' || directed || ',forbid 6,8,10,12'); + + + -- THREE edges + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{}',$$||directed||$$)$$, $$ VALUES ('v',17,ARRAY[10,11,12]) $$, '10 -> 11 -> 12 -> 17: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{10}',$$||directed||$$)$$, $$ VALUES ('v',10,ARRAY[11,12,17]) $$, '10 -> 11 -> 12 -> 17: Directed = ' || directed || ',forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{11}',$$||directed||$$)$$, $$ VALUES ('v',11,ARRAY[10,12,17]) $$, '10 -> 11 -> 12 -> 17: Directed = ' || directed || ',forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{12}',$$||directed||$$)$$, $$ VALUES ('v',12,ARRAY[10,11,17]) $$, '10 -> 11 -> 12 -> 17: Directed = ' || directed || ',forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{17}',$$||directed||$$)$$, $$ VALUES ('v',17,ARRAY[10,11,12]) $$, '10 -> 11 -> 12 -> 17: Directed = ' || directed || ',forbid 17'); + RETURN QUERY + SELECT is_empty($$"graph1" ('5,11,13','{10,17}',$$||directed||$$)$$, '10 -> 11 -> 12 -> 17: Directed = ' || directed || ', forbid 10,17'); + + -- The graph1 + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{}',$$||directed||$$)$$, + $$ VALUES ('v',8,ARRAY[9]),('v',7,ARRAY[1,3]),('v',6,ARRAY[5]) $$, 'the graph1: Directed = ' || directed || ', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{3}',$$||directed||$$)$$, + $$ VALUES ('v',8,ARRAY[9]),('v',3,ARRAY[1]),('v',6,ARRAY[5]) $$, 'the graph1: Directed = ' || directed || ', forbid 3'); + +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION edge_cases(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + +RETURN QUERY SELECT is_empty(format($$"graph" ('0',%1$s)$$,directed),'empty graph: 0,'||directed); + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('1',%1$s)$$,directed), 'not empty graph: 1,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 1,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,1',%1$s)$$,directed), 'not empty graph: 0,1,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,1,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,2',%1$s)$$,directed), 'not empty graph: 0,2,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,2',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,2,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,3',%1$s)$$,directed), 'not empty graph: 0,3,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,3,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,4',%1$s)$$,directed), 'not empty graph: 0,4,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed) ; + +RETURN QUERY +SELECT CASE WHEN directed::BOOLEAN THEN + collect_tap( + isnt_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), + set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed), + isnt_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed), + set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,6,'||directed)) +ELSE + collect_tap( + is_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), + is_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed)) +END; + +END; +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION edge_cases() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY + SELECT skip(1, 'pgr_contraction new signature on 3.8.0'); + RETURN; + END IF; + + PREPARE graph1(text,text,text) AS + SELECT type, id, contracted_vertices FROM pgr_contraction( + format($$SELECT id, source, target, cost, reverse_cost FROM edges WHERE id IN (%s) ORDER BY id$$, $1), + $3::boolean,ARRAY[1],1,$2::BIGINT[]); + + prepare graph(text, text) AS + SELECT * FROM pgr_contraction( + format($$SELECT * FROM test_deadend WHERE dead_case IN (%1$s) ORDER BY id$$, $1), + $2::boolean,ARRAY[1]); + + RETURN QUERY SELECT edge_cases('true'); + RETURN QUERY SELECT edge_cases('false'); + RETURN QUERY SELECT edge_cases_sampledata('true'); + RETURN QUERY SELECT edge_cases_sampledata('false'); + +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT edge_cases(); + +SELECT finish(); +ROLLBACK; + diff --git a/pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg b/pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg new file mode 100644 index 00000000000..c26ac6ddc6f --- /dev/null +++ b/pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg @@ -0,0 +1,320 @@ +/*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 min_version('3.8.0') THEN plan(128) ELSE plan(1) END; + +CREATE TABLE graphs ( + id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + source BIGINT, + target BIGINT, + cost BIGINT default 1, + reverse_cost BIGINT default 1, + dead_case INTEGER +); + +/* 2 -- {3 -- 4} ; 3 -- 4 */ +INSERT INTO graphs(source, target, dead_case) +VALUES +(2, 3, 0), +(2, 4, 0), +(3, 4, 0); + +INSERT INTO graphs(source, target, cost, reverse_cost, dead_case) +VALUES +/* 2->{3->4 [dir=both]} [dir=both]; 1->2 */ +(1, 2, 1, -1, 1), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1 */ +(2, 1, 1, -1, 2), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1 [dir=both] */ +(1, 2, 1, 1, 3), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1,2->1 */ +(2, 1, 1, -1, 4), +(2, 1, 1, -1, 4), + +/* 2->{3->4 [dir=both]} [dir=both]; {2,3}->1 */ +(2, 1, 1, -1, 5), +(3, 1, 1, -1, 5), + +/* 2->{3->4 [dir=both]} [dir=both]; 2->1;2->1;3->1 */ +(2, 1, 1, -1, 6), +(2, 1, 1, -1, 6), +(3, 1, 1, -1, 6); + +CREATE TABLE results ( + type text, + id INTEGER, + contracted_vertices BIGINT[], + result_case INTEGER +); + +INSERT INTO results(type, id, contracted_vertices, result_case) +VALUES +('v',6,ARRAY[5]::BIGINT[], 1), +('v',5,ARRAY[6], 2), +('v',15,ARRAY[10], 3), +('v',10,ARRAY[15], 4), +('v',12,ARRAY[8], 5), +('v',8,ARRAY[12], 6), +('v',15,ARRAY[6,10], 7), +('v',6,ARRAY[10,15], 8), +('v',10,ARRAY[6,15], 9), +('v',10,ARRAY[15], 10), +('v',10,ARRAY[6], 11), +('v',8,ARRAY[11,12], 12), +('v',8,ARRAY[12], 13), +('v',11,ARRAY[12], 13), +('v',11,ARRAY[8,12], 113), +('v',12,ARRAY[8,11], 14), +('v',12,ARRAY[11], 15), + +('v',10,ARRAY[6], 16), +('v',12,ARRAY[8], 16), +('v',6,ARRAY[10], 17), +('v',12,ARRAY[8], 17), +('v',10,ARRAY[6], 18), +('v',8,ARRAY[12], 18), +('v',6,ARRAY[10], 19), +('v',8,ARRAY[12], 19), +('v',6,ARRAY[10], 20), + +('v',17,ARRAY[10,11,12], 21), +('v',10,ARRAY[11,12,17], 22), +('v',11,ARRAY[10,12,17], 23), +('v',12,ARRAY[10,11,17], 24), + +('v',8,ARRAY[9], 25), +('v',7,ARRAY[1,3], 25), +('v',6,ARRAY[5], 25), + +('v',8,ARRAY[9], 26), +('v',3,ARRAY[1], 26), +('v',6,ARRAY[5], 26) + +; + +prepare get_solution(integer, integer, text) AS +WITH a AS (SELECT CASE WHEN $3::BOOLEAN THEN $1 ELSE $2 END r) +SELECT type,id,contracted_vertices FROM results, a WHERE result_case = r; + +CREATE OR REPLACE FUNCTION edge_cases_sampledata(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + -- SINGLE edge + + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{}',$$||directed||$$)$$, $$"get_solution" (1,1,$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{6}',$$||directed||$$)$$, $$"get_solution" (1,1,$$||directed||$$) $$, '5 <=> 6: Directed=' || directed ||', forbid 5'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{5}',$$||directed||$$)$$, $$"get_solution" (2,2,$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', forbid 6'); + RETURN QUERY + SELECT is_empty($$"graph1" ('1','{5,6}',$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', forbid 5,6'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{}',$$||directed||$$)$$, $$"get_solution" (3,3,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{10}',$$||directed||$$)$$, $$"get_solution" (4,4,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{15}',$$||directed||$$)$$, $$"get_solution" (3,3,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', forbid 15'); + RETURN QUERY + SELECT is_empty($$"graph1" ('3','{10,15}',$$||directed||$$) $$, '5 <=> 6: Directed=' || directed ||', forbid 10,15'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{8}',$$||directed||$$)$$, $$"get_solution" (6,6,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', forbid 12'); + + -- TWO edges + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{}',$$||directed||$$)$$, $$"get_solution" (7,7,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{6}',$$||directed||$$)$$, $$"get_solution" (8,8,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{10}',$$||directed||$$)$$, $$"get_solution" (9,9,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{15}',$$||directed||$$)$$, $$"get_solution" (7,7,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{6,10}',$$||directed||$$)$$, $$"get_solution" (10,10,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,10'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,3','{6,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{10,15}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 10,15'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,3','{6,10,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,10,15'); + + + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{}',$$||directed||$$)$$, $$"get_solution" (12,12,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8}',$$||directed||$$)$$, $$"get_solution" (12,12,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{11}',$$||directed||$$)$$, $$"get_solution" (13,113,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{12}',$$||directed||$$)$$, $$"get_solution" (14,14,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8,11}',$$||directed||$$)$$, $$"get_solution" (13,213,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8,12}',$$||directed||$$)$$, $$"get_solution" (15,15,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{11,12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 11,12'); + RETURN QUERY + SELECT is_empty($$"graph1" ('11,12','{8,11,12}',$$||directed||$$)$$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,11,12'); + + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6}',$$||directed||$$)$$, $$"get_solution" (17,17,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8}',$$||directed||$$)$$, $$"get_solution" (18,18,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{10}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{12}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8}',$$||directed||$$)$$, $$"get_solution" (19,19,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,10}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,12}',$$||directed||$$)$$, $$"get_solution" (17,17,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,10}',$$||directed||$$)$$, $$"get_solution" (18,18,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,12}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8,10}',$$||directed||$$)$$, $$"get_solution" (6,6,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8,12}',$$||directed||$$)$$, $$"get_solution" (20,20,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,10,12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,10,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,10,12}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,10,12'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,12','{6,8,10,12}',$$||directed||$$)$$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,10,12'); + + + -- THREE edges + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{}',$$||directed||$$)$$, $$"get_solution" (21,21,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{10}',$$||directed||$$)$$, $$"get_solution" (22,22,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{11}',$$||directed||$$)$$, $$"get_solution" (23,23,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{12}',$$||directed||$$)$$, $$"get_solution" (24,24,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{17}',$$||directed||$$)$$, $$"get_solution" (21,21,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 17'); + RETURN QUERY + SELECT is_empty($$"graph1" ('5,11,13','{10,17}',$$||directed||$$)$$, '10 -> 11 -> 12 -> 17: Directed Directed=' || directed ||', forbid 10,17'); + + -- The graph1 + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{}',$$||directed||$$)$$, $$"get_solution" (25,25,$$||directed||$$) $$, 'the graph1: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{3}',$$||directed||$$)$$, $$"get_solution" (26,26,$$||directed||$$) $$, 'the graph1: Directed=' || directed ||', forbid 3'); + +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION edge_cases(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + +RETURN QUERY SELECT is_empty(format($$"graph" ('0',%1$s)$$,directed),'empty graph: 0,'||directed); + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('1',%1$s)$$,directed), 'not empty graph: 1,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 1,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,1',%1$s)$$,directed), 'not empty graph: 0,1,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,1,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,2',%1$s)$$,directed), 'not empty graph: 0,2,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,2',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,2,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,3',%1$s)$$,directed), 'not empty graph: 0,3,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,3,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,4',%1$s)$$,directed), 'not empty graph: 0,4,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed) ; + +RETURN QUERY +SELECT CASE WHEN directed::BOOLEAN THEN + collect_tap( + isnt_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), + set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed), + isnt_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed), + set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,6,'||directed)) +ELSE + collect_tap( + is_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), + is_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed)) +END; + +END; +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION edge_cases() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY + SELECT skip(1, 'pgr_contraction new signature on 3.8.0'); + RETURN; + END IF; + + PREPARE graph1(text,text,text) AS + SELECT type, id, contracted_vertices FROM pgr_contraction( + format($$SELECT id, source, target, cost, reverse_cost FROM edges WHERE id IN (%s) ORDER BY id$$, $1), + $3::boolean, ARRAY[1],1,$2::BIGINT[]); + + prepare graph(text, text) AS + SELECT * FROM pgr_contraction( + format($$SELECT * FROM graphs WHERE dead_case IN (%1$s) ORDER BY id$$, $1), + $2::boolean,ARRAY[1]); + + RETURN QUERY SELECT edge_cases('true'); + RETURN QUERY SELECT edge_cases('false'); + RETURN QUERY SELECT edge_cases_sampledata('true'); + RETURN QUERY SELECT edge_cases_sampledata('false'); + +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT edge_cases(); + +SELECT finish(); +ROLLBACK; + diff --git a/pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg b/pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg new file mode 100644 index 00000000000..800afda4c4e --- /dev/null +++ b/pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg @@ -0,0 +1,305 @@ +/*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 min_version('3.8.0') THEN plan(112) ELSE plan(1) END; + +CREATE TABLE graphs ( + id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + source BIGINT, + target BIGINT, + cost BIGINT default 1, + reverse_cost BIGINT default 1, + dead_case INTEGER +); + +/* 11 -> {12 -> {13, 14} [dir=both]} [dir=both]; 13 ->14 [dir=both] */ +INSERT INTO graphs(source, target, dead_case) +VALUES +(11, 12, 0), +(11, 13, 0), +(11, 14, 0), +(12, 13, 0), +(12, 14, 0), +(13, 14, 0); + +INSERT INTO graphs(source, target, cost, reverse_cost, dead_case) +VALUES +/* 1->11 */ +(1, 11, 1, -1, 1), + +/* 11->1 */ +(11, 1, 1, -1, 2), + +/* 1 -> 2 -> 11 */ +(1, 2, 1, -1, 3), +(2, 11, 1, -1, 3), + +/* 11 -> 2 -> 1 */ +(11, 2, 1, -1, 4), +(2, 1, 1, -1, 4), + +/* 11 -> 2 [dir=both]; 2 -> 1 [dir=both] */ +(11, 2, 1, 1, 5), +(2, 1, 1, 1, 5), + +/* 11 -> {1,3} [dir=both]; 1->3 [dir=both]*/ +(11, 1, 1, 1, 6), +(1, 3, 1, 1, 6), +(3, 11, 1, 1, 6), + +/* 11 -> {1,3} [dir=both]; 2 -> {1,3} [dir=both]; 2->3 [dir=both]*/ +(11, 1, 1, 1, 7), +(1, 2, 1, 1, 7), +(2, 3, 1, 1, 7), +(3, 11, 1, -1, 7); + +CREATE TABLE results ( + type text, + contracted_vertices BIGINT[], + source BIGINT, + target BIGINT, + cost FLOAT, + result_case INTEGER +); + +INSERT INTO results(type, contracted_vertices, source, target, cost, result_case) +VALUES +('e',ARRAY[3]::BIGINT[],1,7,2, 1), +('e',ARRAY[3],7,1,2, 1), +('e',ARRAY[3],1,7,2, 2), +('e',ARRAY[3],7,1,2, 2), +('e',ARRAY[3,7],1,11,3, 3), +('e',ARRAY[3,7],11,1,3, 3), +('e',ARRAY[7],3,11,2, 4), +('e',ARRAY[7],11,3,2, 4), +('e',ARRAY[16],15,11,2, 5), +('e',ARRAY[16],11,15,2, 5), +('e',ARRAY[10],15,11,2, 5), +('e',ARRAY[16],15,11,2, 6), +('e',ARRAY[16],11,15,2, 6), +('e',ARRAY[10],15,11,2, 7), +('e',ARRAY[7],6,11,2, 8), +('e',ARRAY[7],11,6,2, 8), +('e',ARRAY[3],1,7,2, 9), +('e',ARRAY[3],7,1,2, 9), +('e',ARRAY[3],1,7,2, 11), +('e',ARRAY[3],7,1,2, 12), +('e',ARRAY[3,7],1,11,3, 13), +('e',ARRAY[7],3,11,2, 14), +('e',ARRAY[10,15],11,16,3, 15), +('e',ARRAY[10,11],15,16,3, 25), +('e',ARRAY[15,16],10,11,3, 16), +('e',ARRAY[10,15],11,16,3, 17), +('e',ARRAY[6,10],7,11,3, 18), +('e',ARRAY[10,11],6,7,3, 28), +('e',ARRAY[6,7],10,11,3, 38), +('e',ARRAY[3],7,1,2, 19), +('e',ARRAY[15],10,16,2, 19), +('e',ARRAY[17],16,12,2, 19), +('e',ARRAY[15],10,16,2, 20), +('e',ARRAY[17],16,12,2, 20) +; + +prepare get_solution(integer, integer, text) AS +WITH a AS (SELECT CASE WHEN $3::BOOLEAN THEN $1 ELSE $2 END r) +SELECT type,contracted_vertices,source,target,cost FROM results, a WHERE result_case = r; + +CREATE OR REPLACE FUNCTION edge_cases_sampledata(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + -- SINGLE edge + + RETURN QUERY SELECT is_empty($$"graph1" ('6','{}',$$||directed||$$)$$, '1<=>3: Directed=' || directed ||' no forbidden vertices'); + + -- TWO edges + + RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7','{}',$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7','{}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$ , '1<=>3<=>7: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7','{1}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 1'); + RETURN QUERY SELECT is_empty($$"graph1" ('6,7','{3}',$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 3'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7','{7}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 7'); + + -- T shape + + RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7,4,10','{}',$$||directed||$$)$$, '1<=>3<=>7<->6,8: Directed=' || directed ||' no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,4,10','{}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,4,10','{1}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 1'); + RETURN QUERY + SELECT is_empty($$"graph1" ('6,7,4,10','{3}',$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 3'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,4,10','{7}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 7'); + + + -- THREE edges + + RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7,8','{}',$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{1}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 1'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{11}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{3}',$$||directed||$$)$$, $$"get_solution" (4,14,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 3'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{7}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 7'); + + -- FOUR edges + -- circling square + RETURN QUERY SELECT isnt_empty($$"graph1" ('3,5,9,16','{}',$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{}',$$||directed||$$)$$, $$"get_solution" (5,15,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{11}',$$||directed||$$)$$, $$"get_solution" (5,15,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{15}',$$||directed||$$)$$, $$"get_solution" (5,25,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{10}',$$||directed||$$)$$, $$"get_solution" (6,16,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{16}',$$||directed||$$)$$, $$"get_solution" (7,17,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 16'); + + -- non circling square + RETURN QUERY SELECT isnt_empty($$"graph1" ('2,4,5,8','{}',$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' no forbidden'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' no forbidden'); + + if directed THEN + RETURN QUERY + SELECT is_empty($$"graph1" ('2,4,5,8','{7}',$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 7'); + ELSE + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{7}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 7'); + END IF; + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{11}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{6}',$$||directed||$$)$$, $$"get_solution" (8,28,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{10}',$$||directed||$$)$$, $$"get_solution" (8,38,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 10'); + + -- The graph1 + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{}',$$||directed||$$)$$, $$"get_solution" (9,19,$$||directed||$$)$$, 'the graph: Directed=' || directed ||' no forbidden'); + IF directed THEN + RETURN QUERY + SELECT is_empty($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{3}',$$||directed||$$)$$, 'the graph1: Directed=' || directed ||', forbid 3'); + ELSE + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{3}',$$||directed||$$)$$, $$"get_solution" (1,20,$$||directed||$$)$$, 'the graph1: Directed=' || directed ||', forbid 3'); + END IF; + + +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION edge_cases(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + RETURN QUERY SELECT is_empty(format($$"graph" ('0',%1$s)$$,directed),'empty graph: 0,'||directed); + RETURN QUERY SELECT is_empty(format($$"graph" ('1',%1$s)$$,directed),'empty graph: 1,'||directed); + RETURN QUERY SELECT is_empty(format($$"graph" ('2',%1$s)$$,directed),'empty graph: 2,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('3',%1$s)$$,directed),'not empty graph: 3,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('4',%1$s)$$,directed),'not empty graph: 4,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('5',%1$s)$$,directed),'not empty graph: 5,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('6',%1$s)$$,directed),'not empty graph: 6,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('7',%1$s)$$,directed),'not empty graph: 7,'||directed); + + RETURN QUERY SELECT is_empty(format($$"graph" ('0,1',%1$s)$$,directed), 'empty graph: 0,1,'||directed); + RETURN QUERY SELECT is_empty(format($$"graph" ('0,2',%1$s)$$,directed), 'empty graph: 0,2,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,3',%1$s)$$,directed), 'not empty graph: 0,3,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,4',%1$s)$$,directed), 'not empty graph: 0,4,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'not empty graph: 0,5,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'not empty graph: 0,6,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,7',%1$s)$$,directed), 'not empty graph: 0,7,'||directed); + + RETURN QUERY SELECT set_eq(format($$"graph" ('3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 3,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 4,'||directed) ; + + if directed THEN + RETURN QUERY SELECT set_eq(format($$"graph" ('5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2),('e',-2,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[11]::BIGINT[],1,3,2), ('e',-2,ARRAY[11]::BIGINT[],3,1,2) $$, 'expected graph: 6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3), ('e',-2,ARRAY[1,2]::BIGINT[],3,11,3) $$, 'expected graph: 7,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 0,3,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,4,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2),('e',-2,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 0,5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1]::BIGINT[],11,3,2),('e',-2,ARRAY[1]::BIGINT[],3,11,2) $$, 'expected graph: 0,6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3),('e',-2,ARRAY[1,2]::BIGINT[],3,11,3) $$, 'expected graph: 0,7,'||directed) ; + ELSE + RETURN QUERY SELECT set_eq(format($$"graph" ('5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[11]::BIGINT[],1,3,2) $$, 'expected graph: 6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,11]::BIGINT[],2,3,3) $$, 'expected graph: 7,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,3,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,4,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1]::BIGINT[],11,3,2) $$, 'expected graph: 0,6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3) $$, 'expected graph: 0,7,'||directed) ; + END IF; + +END; +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION edge_cases() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY + SELECT skip(1, 'pgr_contraction new signature on 3.8.0'); + RETURN; + END IF; + + PREPARE graph1(text,text,text) AS + SELECT type, contracted_vertices,source,target,cost FROM pgr_contraction( + format($$SELECT id, source, target, cost, reverse_cost FROM edges WHERE id IN (%s) ORDER BY id$$, $1), + $3::boolean,ARRAY[2],1,$2::INTEGER[]); + + prepare graph(text, text) AS + SELECT * FROM pgr_contraction(format($$SELECT * FROM graphs WHERE dead_case IN (%1$s)$$, $1), $2::boolean,ARRAY[2]); + + RETURN QUERY SELECT edge_cases('true'); + RETURN QUERY SELECT edge_cases('false'); + RETURN QUERY SELECT edge_cases_sampledata('true'); + RETURN QUERY SELECT edge_cases_sampledata('false'); + +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT edge_cases(); + +SELECT finish(); +ROLLBACK; + diff --git a/pgtap/contraction/contraction/edge_cases/linear/directed/edge_cases.pg b/pgtap/contraction/contraction/edge_cases/linear/directed/edge_cases.pg index eebae547f57..31c88f95ef2 100644 --- a/pgtap/contraction/contraction/edge_cases/linear/directed/edge_cases.pg +++ b/pgtap/contraction/contraction/edge_cases/linear/directed/edge_cases.pg @@ -74,17 +74,17 @@ SELECT is_empty('v3e2q20', 'graph_e_1_2 QUERY 2: Directed graph with two edges a -- GRAPH 5 - 6 - 7 PREPARE graph_e_1_4_q1 AS -SELECT type, id, contracted_vertices, source, target, cost +SELECT type, contracted_vertices, source, target, cost FROM pgr_contraction( 'graph_e_1_4', ARRAY[2]::INTEGER[], 5, ARRAY[]::INTEGER[], true); PREPARE graph_e_1_4_sol1 AS -SELECT type, id, contracted_vertices, source, target, cost +SELECT type, contracted_vertices, source, target, cost FROM (VALUES - ('e', -1, ARRAY[6]::BIGINT[], 7, 5, 2), - ('e', -2, ARRAY[6]::BIGINT[], 5, 7, 2)) -AS t(type, id, contracted_vertices, source, target, cost); + ('e', ARRAY[6]::BIGINT[], 7, 5, 2), + ('e', ARRAY[6]::BIGINT[], 5, 7, 2)) +AS t(type, contracted_vertices, source, target, cost); SELECT set_eq('graph_e_1_4_q1', 'graph_e_1_4_sol1', 'graph_e_1_4 QUERY 1: Directed graph with two edges and no forbidden vertices'); diff --git a/pgtap/contraction/contraction/edge_cases/remaining_tests.pg b/pgtap/contraction/contraction/edge_cases/remaining_tests.pg index 30740360e4e..e2bb4aded19 100644 --- a/pgtap/contraction/contraction/edge_cases/remaining_tests.pg +++ b/pgtap/contraction/contraction/edge_cases/remaining_tests.pg @@ -19,7 +19,7 @@ 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 plan(49); +SELECT plan(48); SET client_min_messages TO WARNING; SELECT has_function('pgr_contraction'); @@ -34,26 +34,6 @@ SELECT function_returns('pgr_contraction', ARRAY[ ], 'setof record'); - -PREPARE parameters AS -SELECT array[ -'', -'', -'max_cycles', -'forbidden_vertices', -'directed', -'type', -'id', -'contracted_vertices', -'source', -'target', -'cost']; - -SELECT set_eq( - $$SELECT proargnames FROM pg_proc WHERE proname = 'pgr_contraction'$$, - 'parameters'); - - CREATE OR REPLACE FUNCTION test_anyInteger(fn TEXT, params TEXT[], parameter TEXT) RETURNS SETOF TEXT AS $BODY$ diff --git a/pgtap/contraction/contraction/inner_query.pg b/pgtap/contraction/contraction/inner_query.pg new file mode 100644 index 00000000000..ae7eb0b2249 --- /dev/null +++ b/pgtap/contraction/contraction/inner_query.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 min_version('3.8.0') THEN plan(387) ELSE plan(1) END; + +CREATE OR REPLACE FUNCTION inner_query() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY SELECT skip(1, 'pgr_contraction new signature on 3.8.0'); + RETURN; + END IF; + + RETURN QUERY SELECT style_dijkstra('pgr_contraction(', ')'); + RETURN QUERY SELECT style_dijkstra('pgr_contraction(', ', true)'); + RETURN QUERY SELECT style_dijkstra('pgr_contraction(', ', false)'); + RETURN QUERY SELECT style_dijkstra('pgr_contraction(', ', true, ARRAY[1])'); + RETURN QUERY SELECT style_dijkstra('pgr_contraction(', ', false, ARRAY[1])'); + RETURN QUERY SELECT style_dijkstra('pgr_contraction(', ', true, ARRAY[2])'); + RETURN QUERY SELECT style_dijkstra('pgr_contraction(', ', false, ARRAY[2])'); + + RETURN QUERY SELECT throws_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[1]::bigint[], 1, ARRAY[ 2 ]::bigint[])$$, + '42883', 'function pgr_contraction(unknown, boolean, bigint[], integer, bigint[]) does not exist', + 'Throws because methods is bigint[]'); + + RETURN QUERY SELECT throws_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[]::INTEGER[], 1, ARRAY[ 2 ]::integer[])$$, + 'XX000', 'One dimension expected', 'Throws because methods is empty ARRAY[]'); + + RETURN QUERY SELECT throws_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[], 1, ARRAY[ 2 ]::integer[])$$, + '42P18', 'cannot determine type of empty array', 'Throws because methods is empty ARRAY[]'); + + RETURN QUERY SELECT throws_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[1], 1, ARRAY[ [2,3,4,5], [4,5,6,7] ]::integer[][])$$, + 'XX000', 'One dimension expected', 'Throws because forbidden is 2 dimensions'); + + RETURN QUERY SELECT lives_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[1], 1, ARRAY[ 2 ])$$, + 'Lives when forbidden is not described'); + + RETURN QUERY SELECT lives_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[1], 1, ARRAY[ 2 ]::integer[])$$, + 'Lives when forbidden is integer[]'); + + RETURN QUERY SELECT lives_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[1], 1, ARRAY[ 2 ]::bigint[])$$, + 'Lives when forbidden is bigint[]'); + + RETURN QUERY SELECT lives_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[1], 1, ARRAY[ 2 ]::smallint[])$$, + 'Lives when forbidden is smallint[]'); + + RETURN QUERY SELECT throws_ok( + $$SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', true, + ARRAY[1], 1, ARRAY[ 2 ]::float8[])$$, + '42883', 'function pgr_contraction(unknown, boolean, integer[], integer, double precision[]) does not exist', + 'Throws because forbidden is float8[]'); + +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT inner_query(); + +SELECT finish(); +ROLLBACK; diff --git a/pgtap/contraction/contraction/no_crash_test.pg b/pgtap/contraction/contraction/no_crash_test.pg index 0a6a663be12..91133d6c864 100644 --- a/pgtap/contraction/contraction/no_crash_test.pg +++ b/pgtap/contraction/contraction/no_crash_test.pg @@ -1,4 +1,3 @@ - /*PGR-GNU***************************************************************** Copyright (c) 2018 pgRouting developers @@ -20,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. BEGIN; UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost); -SELECT plan(7); +SELECT CASE WHEN min_version('3.8.0') THEN plan(11) ELSE plan(8) END; PREPARE edges AS SELECT id, source, target, cost, reverse_cost FROM edges; @@ -46,6 +45,21 @@ BEGIN RETURN query SELECT * FROM no_crash_test('pgr_contraction', params, subs); + IF NOT min_version('3.8.0') THEN + RETURN QUERY + SELECT skip(1, 'pgr_contraction new signature on 3.8.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_contraction', params, subs); + END $BODY$ LANGUAGE plpgsql VOLATILE; diff --git a/pgtap/contraction/contraction/types_check.pg b/pgtap/contraction/contraction/types_check.pg index 8dd9524a774..f5650b3004f 100644 --- a/pgtap/contraction/contraction/types_check.pg +++ b/pgtap/contraction/contraction/types_check.pg @@ -1,4 +1,3 @@ - /*PGR-GNU***************************************************************** Copyright (c) 2018 pgRouting developers @@ -17,23 +16,53 @@ 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 plan(5); +SELECT CASE WHEN min_version('3.8.0') THEN plan(7) ELSE plan(5) END; + +CREATE OR REPLACE FUNCTION types_check() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF min_version('3.8.0') THEN + RETURN QUERY SELECT has_function('pgr_contraction', ARRAY['text','boolean','integer[]','integer','bigint[]']); + RETURN QUERY SELECT function_returns('pgr_contraction', ARRAY['text','boolean','integer[]','integer','bigint[]'], 'setof record'); + + RETURN QUERY SELECT set_eq( + $$SELECT proargnames FROM pg_proc WHERE proname = 'pgr_contraction'$$, + $$VALUES + ('{"","",max_cycles,forbidden_vertices,directed,type,id,contracted_vertices,source,target,cost}'::TEXT[]), + ('{"",directed,methods,cycles,forbidden,type,id,contracted_vertices,source,target,cost}'::TEXT[]) + $$,'pgr_contraction: Column names'); + + RETURN QUERY SELECT function_types('pgr_contraction', + $$VALUES ('{text,bool,_int4,int4,_int8,text,int8,_int8,int8,int8,float8}'::TEXT[]), + ('{text,_int8,int4,_int8,bool,text,int8,_int8,int8,int8,float8}'::TEXT[]) $$); + + ELSE + + RETURN QUERY SELECT set_eq( + $$SELECT proargnames FROM pg_proc WHERE proname = 'pgr_contraction'$$, + $$VALUES + ('{"", "", "max_cycles", "forbidden_vertices", "directed", "type", "id", "contracted_vertices", "source", "target", "cost"}'::TEXT[]) + $$); + + RETURN QUERY SELECT set_eq( + $$SELECT proallargtypes from pg_proc where proname = 'pgr_contraction'$$, + $$SELECT '{25,1016,23,1016,16,25,20,1016,20,20,701}'::OID[] $$ + ); + +END IF; + +END; +$BODY$ +LANGUAGE plpgsql; SELECT has_function('pgr_contraction'); SELECT has_function('pgr_contraction', ARRAY['text','bigint[]','integer','bigint[]','boolean']); SELECT function_returns('pgr_contraction', ARRAY['text', 'bigint[]','integer','bigint[]','boolean'], 'setof record'); - -SELECT set_eq( - $$SELECT proargnames FROM pg_proc WHERE proname = 'pgr_contraction'$$, - $$VALUES - ('{"", "", "max_cycles", "forbidden_vertices", "directed", "type", "id", "contracted_vertices", "source", "target", "cost"}'::TEXT[]) - $$); - -SELECT set_eq( - $$SELECT proallargtypes from pg_proc where proname = 'pgr_contraction'$$, - $$SELECT '{25,1016,23,1016,16,25,20,1016,20,20,701}'::OID[] $$ -); +SELECT types_check(); SELECT finish(); ROLLBACK; diff --git a/tools/testers/contraction_tapfuncs.sql b/tools/testers/contraction_tapfuncs.sql index 59194493b4d..d565ee7f84f 100644 --- a/tools/testers/contraction_tapfuncs.sql +++ b/tools/testers/contraction_tapfuncs.sql @@ -16,6 +16,143 @@ 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*/ + +CREATE OR REPLACE PROCEDURE create_contracted_graph(directed BOOLEAN, fn TEXT, methods INTEGER[] DEFAULT NULL::INTEGER[]) AS +$BODY$ + +BEGIN + + IF NOT min_version('3.8.0') THEN RETURN; END IF; + + DELETE FROM edges WHERE id >= 19; + ALTER SEQUENCE edges_id_seq RESTART WITH 19; + UPDATE edges SET (is_new, contracted_vertices)=(false,NULL); + UPDATE vertices SET (is_contracted, contracted_vertices)=(false,NULL); + + -- add extra columns to the edges and vertices table + + DROP TABLE IF EXISTS contraction_info; + IF fn = 'pgr_contraction' THEN + EXECUTE format($q$ + CREATE TABLE contraction_info AS + SELECT * FROM %s( + 'SELECT id, source, target, cost, reverse_cost FROM edges ORDER BY id', + %s, '%s'::INTEGER[]); + $q$, fn, directed::TEXT, methods); + ELSE + EXECUTE format($q$ + CREATE TABLE contraction_info AS + SELECT * FROM %s( + 'SELECT id, source, target, cost, reverse_cost FROM edges ORDER BY id', + '%s'); + $q$, fn, directed::TEXT); + END IF; + + -- add the new edges + INSERT INTO edges(source, target, cost, reverse_cost, contracted_vertices, is_new) + SELECT source, target, cost, -1, contracted_vertices, true + FROM contraction_info + WHERE type = 'e'; + + -- Indicate vertices that were contracted + UPDATE vertices + SET is_contracted = true + WHERE id IN (SELECT unnest(contracted_vertices) FROM contraction_info); + + -- add the contracted vertices on the vertices table + UPDATE vertices + SET contracted_vertices = contraction_info.contracted_vertices + FROM contraction_info + WHERE type = 'v' AND vertices.id = contraction_info.id; + + DROP VIEW IF EXISTS contracted_graph; + CREATE VIEW contracted_graph AS + SELECT id,source, target, cost, reverse_cost, contracted_vertices FROM edges + WHERE + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.source) + AND + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.target); + +END +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION path_cost_contraction(BIGINT, BIGINT, BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE q TEXT; +BEGIN + + RETURN QUERY + SELECT round(agg_cost::numeric, 3)::TEXT FROM pgr_dijkstra( + 'WITH cul_de_sac AS ( + SELECT contracted_vertices || id as v + FROM vertices WHERE ' || $1 ||' = ANY(contracted_vertices) OR ' || $2 ||' = ANY(contracted_vertices)), + linears_to_expand AS ( + SELECT id, contracted_vertices + FROM edges WHERE is_new AND (' || $1 ||' = ANY(contracted_vertices) OR '|| $2 ||' = ANY(contracted_vertices)) + ), + verts AS (SELECT * FROM cul_de_sac UNION SELECT contracted_vertices FROM linears_to_expand) + SELECT id, source, target, cost, reverse_cost FROM edges, verts WHERE source = ANY(v) OR target = ANY(v) + + UNION + + SELECT id, source, target, cost, reverse_cost FROM contracted_graph LEFT JOIN linears_to_expand c USING (id) WHERE c.id IS NULL', + $1, $2, $3) WHERE edge = -1; + +END; +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION compare_dijkstra_contraction( + BIGINT, BIGINT, BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + q TEXT; +BEGIN + + RETURN QUERY + SELECT set_eq( + $$SELECT * FROM path_cost_contraction($$|| $1 || $$,$$ || $2 || $$,$$ || $3::BOOLEAN || $$)$$, + $$SELECT round(agg_cost::numeric, 3)::TEXT + FROM pgr_dijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edges WHERE id < 19', + $$|| $1 || $$,$$ || $2 || $$,$$ || $3::BOOLEAN || $$) WHERE edge = -1 + $$, + 'From ' || $1 || ' to ' || $2 || 'Directed = ' || $3::BOOLEAN); + +END +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION compare_dijkstra_contraction(BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + i INTEGER; + j INTEGER; + +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY + SELECT skip(1, 'contraction function/signature is new on 3.8.0'); + RETURN; + END IF; + + FOR i IN 1..18 LOOP + FOR j IN 1..18 LOOP + RETURN QUERY + SELECT compare_dijkstra_contraction(i, j, $1); + END LOOP; + END LOOP; + +END +$BODY$ +LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION test_ids_size(pow INTEGER, directed BOOLEAN) RETURNS SETOF TEXT AS $BODY$ From 6fbf5f56b8353acceeae6f7bbfd70414a689e4ce Mon Sep 17 00:00:00 2001 From: cvvergara Date: Thu, 20 Mar 2025 13:23:50 -0600 Subject: [PATCH 02/11] (contraction/docqueries) Ajusting the documentation queries --- docqueries/contraction/CMakeLists.txt | 1 - docqueries/contraction/contraction.pg | 97 +++++++++++- docqueries/contraction/contraction.result | 176 +++++++++++++++++++++- docqueries/contraction/test.conf | 1 - 4 files changed, 265 insertions(+), 10 deletions(-) diff --git a/docqueries/contraction/CMakeLists.txt b/docqueries/contraction/CMakeLists.txt index d640c0ea807..9fe0f6d0974 100644 --- a/docqueries/contraction/CMakeLists.txt +++ b/docqueries/contraction/CMakeLists.txt @@ -1,6 +1,5 @@ # Do not use extensions SET(LOCAL_FILES - contraction-family contraction ) diff --git a/docqueries/contraction/contraction.pg b/docqueries/contraction/contraction.pg index bbda07d9c67..d817d6a1664 100644 --- a/docqueries/contraction/contraction.pg +++ b/docqueries/contraction/contraction.pg @@ -2,14 +2,103 @@ -- Creative Commons Attribution-Share Alike 3.0 License : https://creativecommons.org/licenses/by-sa/3.0/ /* -- q1 */ SELECT * FROM pgr_contraction( - 'SELECT id, source, target, cost, reverse_cost FROM edges', - ARRAY[1, 2], directed => false); + 'SELECT id, source, target, cost, reverse_cost FROM edges', false); /* -- q2 */ SELECT type, id, contracted_vertices FROM pgr_contraction( 'SELECT id, source, target, cost, reverse_cost FROM edges', - ARRAY[1]); + methods => ARRAY[1]); /* -- q3 */ SELECT * FROM pgr_contraction( 'SELECT id, source, target, cost, reverse_cost FROM edges', - ARRAY[2]); + methods => ARRAY[2]); /* -- q4 */ + +/* -- cg1 */ +ALTER TABLE vertices + ADD is_contracted BOOLEAN DEFAULT false, + ADD contracted_vertices BIGINT[]; +ALTER TABLE edges + ADD is_new BOOLEAN DEFAULT false, + ADD contracted_vertices BIGINT[]; +/* -- cg2 */ +SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', false); +/* -- cg3 */ +SELECT * INTO contraction_results +FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', false); +/* -- cg4 */ +UPDATE vertices +SET is_contracted = true +WHERE id IN (SELECT unnest(contracted_vertices) FROM contraction_results); +/* -- cg5 */ +SELECT id, is_contracted +FROM vertices +ORDER BY id; +/* -- cg6 */ +UPDATE vertices +SET contracted_vertices = contraction_results.contracted_vertices +FROM contraction_results +WHERE type = 'v' AND vertices.id = contraction_results.id; +/* -- cg7 */ +INSERT INTO edges(source, target, cost, reverse_cost, contracted_vertices, is_new) +SELECT source, target, cost, -1, contracted_vertices, true +FROM contraction_results +WHERE type = 'e'; +/* -- cg8 */ +SELECT id FROM vertices WHERE is_contracted = false ORDER BY id; +/* -- cg9 */ +WITH +vertices_in_graph AS (SELECT id FROM vertices WHERE is_contracted = false) +SELECT id, source, target, cost, reverse_cost, contracted_vertices +FROM edges +WHERE + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.source) + AND + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.target) +ORDER BY id; +/* -- cg10 */ +DROP VIEW IF EXISTS contracted_graph; +CREATE VIEW contracted_graph AS +SELECT id,source, target, cost, reverse_cost, contracted_vertices FROM edges +WHERE + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.source) + AND + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.target); +/* -- cg11 */ +CREATE OR REPLACE FUNCTION path_cost(source BIGINT, target BIGINT) +RETURNS SETOF FLOAT AS +$BODY$ + +SELECT agg_cost FROM pgr_dijkstraCost( + /* The inner query */ + 'WITH + cul_de_sac AS ( + SELECT contracted_vertices || id as v + FROM vertices WHERE ' || $1 ||' = ANY(contracted_vertices) + OR ' || $2 ||' = ANY(contracted_vertices)), + linears_to_expand AS ( + SELECT id, contracted_vertices + FROM edges WHERE is_new AND (' || $1 ||' = ANY(contracted_vertices) + OR '|| $2 ||' = ANY(contracted_vertices)) + ), + additional_vertices AS ( + SELECT * FROM cul_de_sac UNION SELECT contracted_vertices FROM linears_to_expand) + SELECT id, source, target, cost, reverse_cost + FROM edges, additional_vertices WHERE source = ANY(v) OR target = ANY(v) + + UNION + + SELECT id, source, target, cost, reverse_cost + FROM contracted_graph LEFT JOIN linears_to_expand c USING (id) WHERE c.id IS NULL', + + source, target, false); + +$BODY$ LANGUAGE SQL; +/* -- cg12 */ +SELECT * FROM path_cost(10, 12); +/* -- cg13 */ +SELECT * FROM path_cost(15, 12); +/* -- cg14 */ +SELECT * FROM path_cost(15, 1); +/* -- cg15 */ diff --git a/docqueries/contraction/contraction.result b/docqueries/contraction/contraction.result index c07e3037eaa..e9662cd97b2 100644 --- a/docqueries/contraction/contraction.result +++ b/docqueries/contraction/contraction.result @@ -4,8 +4,7 @@ SET client_min_messages TO NOTICE; SET /* -- q1 */ SELECT * FROM pgr_contraction( - 'SELECT id, source, target, cost, reverse_cost FROM edges', - ARRAY[1, 2], directed => false); + 'SELECT id, source, target, cost, reverse_cost FROM edges', false); type | id | contracted_vertices | source | target | cost ------+----+---------------------+--------+--------+------ v | 4 | {2} | -1 | -1 | -1 @@ -20,7 +19,7 @@ SELECT * FROM pgr_contraction( /* -- q2 */ SELECT type, id, contracted_vertices FROM pgr_contraction( 'SELECT id, source, target, cost, reverse_cost FROM edges', - ARRAY[1]); + methods => ARRAY[1]); type | id | contracted_vertices ------+----+--------------------- v | 4 | {2} @@ -33,7 +32,7 @@ SELECT type, id, contracted_vertices FROM pgr_contraction( /* -- q3 */ SELECT * FROM pgr_contraction( 'SELECT id, source, target, cost, reverse_cost FROM edges', - ARRAY[2]); + methods => ARRAY[2]); type | id | contracted_vertices | source | target | cost ------+----+---------------------+--------+--------+------ e | -1 | {3} | 1 | 7 | 2 @@ -41,5 +40,174 @@ SELECT * FROM pgr_contraction( (2 rows) /* -- q4 */ +/* -- cg1 */ +ALTER TABLE vertices + ADD is_contracted BOOLEAN DEFAULT false, + ADD contracted_vertices BIGINT[]; +ALTER TABLE +ALTER TABLE edges + ADD is_new BOOLEAN DEFAULT false, + ADD contracted_vertices BIGINT[]; +ALTER TABLE +/* -- cg2 */ +SELECT * FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', false); + type | id | contracted_vertices | source | target | cost +------+----+---------------------+--------+--------+------ + v | 4 | {2} | -1 | -1 | -1 + v | 7 | {1,3} | -1 | -1 | -1 + v | 14 | {13} | -1 | -1 | -1 + e | -1 | {5,6} | 7 | 10 | 2 + e | -2 | {8,9} | 7 | 12 | 2 + e | -3 | {17} | 12 | 16 | 2 + e | -4 | {15} | 10 | 16 | 2 +(7 rows) + +/* -- cg3 */ +SELECT * INTO contraction_results +FROM pgr_contraction( + 'SELECT id, source, target, cost, reverse_cost FROM edges', false); +SELECT 7 +/* -- cg4 */ +UPDATE vertices +SET is_contracted = true +WHERE id IN (SELECT unnest(contracted_vertices) FROM contraction_results); +UPDATE 10 +/* -- cg5 */ +SELECT id, is_contracted +FROM vertices +ORDER BY id; + id | is_contracted +----+--------------- + 1 | t + 2 | t + 3 | t + 4 | f + 5 | t + 6 | t + 7 | f + 8 | t + 9 | t + 10 | f + 11 | f + 12 | f + 13 | t + 14 | f + 15 | t + 16 | f + 17 | t +(17 rows) + +/* -- cg6 */ +UPDATE vertices +SET contracted_vertices = contraction_results.contracted_vertices +FROM contraction_results +WHERE type = 'v' AND vertices.id = contraction_results.id; +UPDATE 3 +/* -- cg7 */ +INSERT INTO edges(source, target, cost, reverse_cost, contracted_vertices, is_new) +SELECT source, target, cost, -1, contracted_vertices, true +FROM contraction_results +WHERE type = 'e'; +INSERT 0 4 +/* -- cg8 */ +SELECT id FROM vertices WHERE is_contracted = false ORDER BY id; + id +---- + 4 + 7 + 10 + 11 + 12 + 14 + 16 +(7 rows) + +/* -- cg9 */ +WITH +vertices_in_graph AS (SELECT id FROM vertices WHERE is_contracted = false) +SELECT id, source, target, cost, reverse_cost, contracted_vertices +FROM edges +WHERE + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.source) + AND + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.target) +ORDER BY id; + id | source | target | cost | reverse_cost | contracted_vertices +----+--------+--------+------+--------------+--------------------- + 5 | 10 | 11 | 1 | -1 | + 8 | 7 | 11 | 1 | 1 | + 9 | 11 | 16 | 1 | 1 | + 11 | 11 | 12 | 1 | -1 | + 19 | 7 | 10 | 2 | -1 | {5,6} + 20 | 7 | 12 | 2 | -1 | {8,9} + 21 | 12 | 16 | 2 | -1 | {17} + 22 | 10 | 16 | 2 | -1 | {15} +(8 rows) + +/* -- cg10 */ +DROP VIEW IF EXISTS contracted_graph; +NOTICE: view "contracted_graph" does not exist, skipping +DROP VIEW +CREATE VIEW contracted_graph AS +SELECT id,source, target, cost, reverse_cost, contracted_vertices FROM edges +WHERE + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.source) + AND + EXISTS (SELECT id FROM vertices AS v WHERE NOT is_contracted AND v.id = edges.target); +CREATE VIEW +/* -- cg11 */ +CREATE OR REPLACE FUNCTION path_cost(source BIGINT, target BIGINT) +RETURNS SETOF FLOAT AS +$BODY$ + +SELECT agg_cost FROM pgr_dijkstraCost( + /* The inner query */ + 'WITH + cul_de_sac AS ( + SELECT contracted_vertices || id as v + FROM vertices WHERE ' || $1 ||' = ANY(contracted_vertices) + OR ' || $2 ||' = ANY(contracted_vertices)), + linears_to_expand AS ( + SELECT id, contracted_vertices + FROM edges WHERE is_new AND (' || $1 ||' = ANY(contracted_vertices) + OR '|| $2 ||' = ANY(contracted_vertices)) + ), + additional_vertices AS ( + SELECT * FROM cul_de_sac UNION SELECT contracted_vertices FROM linears_to_expand) + SELECT id, source, target, cost, reverse_cost + FROM edges, additional_vertices WHERE source = ANY(v) OR target = ANY(v) + + UNION + + SELECT id, source, target, cost, reverse_cost + FROM contracted_graph LEFT JOIN linears_to_expand c USING (id) WHERE c.id IS NULL', + + source, target, false); + +$BODY$ LANGUAGE SQL; +CREATE FUNCTION +/* -- cg12 */ +SELECT * FROM path_cost(10, 12); + path_cost +----------- + 2 +(1 row) + +/* -- cg13 */ +SELECT * FROM path_cost(15, 12); + path_cost +----------- + 3 +(1 row) + +/* -- cg14 */ +SELECT * FROM path_cost(15, 1); + path_cost +----------- + 5 +(1 row) + +/* -- cg15 */ ROLLBACK; ROLLBACK diff --git a/docqueries/contraction/test.conf b/docqueries/contraction/test.conf index bd08f892df0..bc173f01024 100644 --- a/docqueries/contraction/test.conf +++ b/docqueries/contraction/test.conf @@ -3,7 +3,6 @@ %main::tests = ( 'any' => { 'files' => [qw( - contraction-family.pg contraction.pg )] }, From 0e0e2227954445176b621f8a0b30929d355aa6e8 Mon Sep 17 00:00:00 2001 From: cvvergara Date: Thu, 20 Mar 2025 13:25:05 -0600 Subject: [PATCH 03/11] (contraction/sql) The new signature and deprecation of the other --- sql/contraction/contraction.sql | 64 ++++++++++++++++++++------------- sql/sigs/pgrouting--3.8.sig | 1 + 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/sql/contraction/contraction.sql b/sql/contraction/contraction.sql index ce65e593056..f11bf646afb 100644 --- a/sql/contraction/contraction.sql +++ b/sql/contraction/contraction.sql @@ -27,25 +27,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ --------------------- --------------------- --- contraction --------------------- --------------------- - --------------------- --- pgr_contraction --------------------- - - ---v3.0 +--v3.8 CREATE FUNCTION pgr_contraction( TEXT, -- edges_sql (required) - BIGINT[], -- contraction_order (required) - - max_cycles INTEGER DEFAULT 1, - forbidden_vertices BIGINT[] DEFAULT ARRAY[]::BIGINT[], directed BOOLEAN DEFAULT true, + methods INTEGER[] DEFAULT ARRAY[1,2]::INTEGER[], + cycles INTEGER DEFAULT 1, + forbidden BIGINT[] DEFAULT ARRAY[]::BIGINT[], OUT type TEXT, OUT id BIGINT, @@ -55,22 +43,50 @@ CREATE FUNCTION pgr_contraction( OUT cost FLOAT) RETURNS SETOF RECORD AS $BODY$ - SELECT type, id, contracted_vertices, source, target, cost - FROM _pgr_contraction(_pgr_get_statement($1), $2::BIGINT[], $3, $4, $5); + SELECT type, id, contracted_vertices, source, target, cost + FROM _pgr_contraction(_pgr_get_statement($1), methods::BIGINT[], cycles, forbidden, directed); $BODY$ LANGUAGE SQL VOLATILE STRICT; --- COMMENTS - -COMMENT ON FUNCTION pgr_contraction(TEXT, BIGINT[], INTEGER, BIGINT[], BOOLEAN) +COMMENT ON FUNCTION pgr_contraction(TEXT, BOOLEAN, INTEGER[], INTEGER, BIGINT[]) IS 'pgr_contraction - Parameters: - Edges SQL with columns: id, source, target, cost [,reverse_cost] - - ARRAY [Contraction order] - Optional Parameters - - max_cycles := 1 - - forbidden_vertices := ARRAY[]::BIGINT[] - directed := true + - methods := ARRAY[1,2] + - cycles := 1 + - forbidden := ARRAY[]::BIGINT[] - Documentation: - ${PROJECT_DOC_LINK}/pgr_contraction.html '; + +--v3.0 +CREATE FUNCTION pgr_contraction( + TEXT, -- edges_sql (required) + BIGINT[], -- contraction_order (required) + + max_cycles INTEGER DEFAULT 1, + forbidden_vertices BIGINT[] DEFAULT ARRAY[]::BIGINT[], + directed BOOLEAN DEFAULT true, + + OUT type TEXT, + OUT id BIGINT, + OUT contracted_vertices BIGINT[], + OUT source BIGINT, + OUT target BIGINT, + OUT cost FLOAT) +RETURNS SETOF RECORD AS +$BODY$ +BEGIN + RAISE NOTICE 'Deprecated Signature pgr_contraction(text,boolean,integer[],integer,bigint[]) in v3.8.0'; + RETURN QUERY + SELECT a.type, a.id, a.contracted_vertices, a.source, a.target, a.cost + FROM _pgr_contraction(_pgr_get_statement($1), $2::BIGINT[], $3, $4, $5) AS a; +END; +$BODY$ +LANGUAGE plpgsql VOLATILE STRICT; + +COMMENT ON FUNCTION pgr_contraction(TEXT, BIGINT[], INTEGER, BIGINT[], BOOLEAN) +IS 'pgr_contraction deprecated in 3.8.0'; + diff --git a/sql/sigs/pgrouting--3.8.sig b/sql/sigs/pgrouting--3.8.sig index 59ae351e060..75b7ea1b979 100644 --- a/sql/sigs/pgrouting--3.8.sig +++ b/sql/sigs/pgrouting--3.8.sig @@ -88,6 +88,7 @@ _pgr_connectedcomponents(text) pgr_connectedcomponents(text) _pgr_contraction(text,bigint[],integer,bigint[],boolean) pgr_contraction(text,bigint[],integer,bigint[],boolean) +pgr_contraction(text,boolean,integer[],integer,bigint[]) _pgr_createindex(text,text,text,integer,text) _pgr_createindex(text,text,text,text,integer,text) pgr_createtopology(text,double precision,text,text,text,text,text,boolean) From fe9b0ecdc83317fd9d32554094bce18c19cdf379 Mon Sep 17 00:00:00 2001 From: cvvergara Date: Thu, 20 Mar 2025 13:27:28 -0600 Subject: [PATCH 04/11] (contraction/doc) Updating and refinement of the documentation --- doc/contraction/contraction-family.rst | 322 +------------------------ doc/contraction/pgr_contraction.rst | 307 +++++++++++++++++++---- 2 files changed, 262 insertions(+), 367 deletions(-) diff --git a/doc/contraction/contraction-family.rst b/doc/contraction/contraction-family.rst index 5d54ef45928..4495f0c9941 100644 --- a/doc/contraction/contraction-family.rst +++ b/doc/contraction/contraction-family.rst @@ -293,7 +293,7 @@ Linear vertex on directed graph - The green nodes are `linear`_ nodes - The blue nodes have an unlimited number of incoming and outgoing edges. -- The white node is not linear because the linearity is not symetrical. +- The white node is not linear because the linearity is not symmetrical. * It is possible to go :math:`y \rightarrow c \rightarrow z` * It's not possible to go :math:`z \rightarrow c \rightarrow y` @@ -400,326 +400,6 @@ Contracting :math:`v`: Edge :math:`u \rightarrow z` has the information of nodes that were contracted. -The cycle -------------------------------------------------------------------------------- - -Contracting a graph, can be done with more than one operation. -The order of the operations affect the resulting contracted graph, after -applying one operation, the set of vertices that can be contracted -by another operation changes. - -This implementation, cycles ``max_cycles`` times through ``operations_order`` . - -.. parsed-literal:: - - - do max_cycles times { - for (operation in operations_order) - { do operation } - } - - - -Contracting sample data -------------------------------------------------------------------------------- - -In this section, building and using a contracted graph will be shown by example. - -- The :doc:`sampledata` for an undirected graph is used -- a dead end operation first followed by a linear operation. - - -.. contents:: - :local: - -Construction of the graph in the database -............................................................................... - -.. rubric:: Original Data - -The following query shows the original data involved in the contraction -operation. - -.. literalinclude:: contraction-family.queries - :start-after: -- q00 - :end-before: -- q01 - -The original graph: - -.. image:: /images/Fig6-undirected.png - :scale: 25% - -Contraction results -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -The results do not represent the contracted graph. -They represent the changes done to the graph after applying the contraction -algorithm. - -Observe that vertices, for example, :math:`6` do not appear in the results -because it was not affected by the contraction algorithm. - -.. literalinclude:: contraction-family.queries - :start-after: -- q2 - :end-before: -- q3 - -After doing the dead end contraction operation: - -.. image:: images/undirected_sampledata_b.png - :scale: 25% - -After doing the linear contraction operation to the graph above: - -.. image:: images/undirected_sampledata_c.png - :scale: 25% - -The process to create the contraction graph on the database: - -.. contents:: - :local: - -Add additional columns -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Adding extra columns to the ``edge_table`` and ``edge_table_vertices_pgr`` -tables, where: - -.. list-table:: - :width: 80 - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``contracted_vertices`` - - The vertices set belonging to the vertex/edge - * - ``is_contracted`` - - On the vertex table - - * when ``true`` the vertex is contracted, its not part of the contracted - graph. - * when ``false`` the vertex is not contracted, its part of the contracted - graph. - * - ``is_new`` - - On the edge table - - * when ``true`` the edge was generated by the contraction algorithm. its - part of the contracted graph. - * when ``false`` the edge is an original edge, might be or not part of - the contracted graph. - -.. literalinclude:: contraction-family.queries - :start-after: -- q1 - :end-before: -- q2 - -Store contraction information -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Store the `contraction results`_ in a table - -.. literalinclude:: contraction-family.queries - :start-after: -- q3 - :end-before: -- q4 - - -The vertex table update -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Use ``is_contracted`` column to indicate the vertices that are contracted. - -.. literalinclude:: contraction-family.queries - :start-after: -- q4 - :end-before: -- q5 - -Fill ``contracted_vertices`` with the information from the results tha belong to -the vertices. - -.. literalinclude:: contraction-family.queries - :start-after: -- q6 - :end-before: -- q7 - -The modified vertices table: - -.. literalinclude:: contraction-family.queries - :start-after: -- q7 - :end-before: -- q8 - -The edge table update -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Insert the new edges generated by pgr_contraction. - -.. literalinclude:: contraction-family.queries - :start-after: -- q8 - :end-before: -- q9 - -The modified ``edge_table``. - -.. literalinclude:: contraction-family.queries - :start-after: -- q9 - :end-before: -- q10 - - -The contracted graph -............................................................................... - -Vertices that belong to the contracted graph. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -.. literalinclude:: contraction-family.queries - :start-after: -- q10 - :end-before: -- q11 - -Edges that belong to the contracted graph. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -.. literalinclude:: contraction-family.queries - :start-after: -- q11 - :end-before: -- case1 - -Contracted graph -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -.. image:: images/newgraph.png - :scale: 25% - -Using the contracted graph -............................................................................... - -Using the contracted graph with ``pgr_dijkstra`` - -There are three cases when calculating the shortest path between a given source -and target in a contracted graph: - -- Case 1: Both source and target belong to the contracted graph. -- Case 2: Source and/or target belong to an edge subgraph. -- Case 3: Source and/or target belong to a vertex. - -Case 1: Both source and target belong to the contracted graph. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Using the `Edges that belong to the contracted graph.`_ on lines 11 to 20. - -.. literalinclude:: contraction-family.queries - :emphasize-lines: 11-20 - :start-after: -- case1 - :end-before: -- use1 - :linenos: - -.. rubric:: Case 1 - -When both source and target belong to the contracted graph, a path is found. - -.. literalinclude:: contraction-family.queries - :start-after: -- use1 - :end-before: -- use1-1 - -.. rubric:: Case 2 - -When source and/or target belong to an edge subgraph then a path is not found. - -In this case, the contracted graph do not have an edge connecting with -node :math:`4`. - -.. literalinclude:: contraction-family.queries - :start-after: -- use1-1 - :end-before: -- use1-2 - -.. rubric:: Case 3 - -When source and/or target belong to a vertex then a path is not found. - -In this case, the contracted graph do not have an edge connecting with -node :math:`7` and of node :math:`4` of the second case. - -.. literalinclude:: contraction-family.queries - :start-after: -- use1-2 - :end-before: -- case2 - -Case 2: Source and/or target belong to an edge subgraph. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Refining the above function to include nodes that belong to an edge. - -- The vertices that need to be expanded are calculated on lines 11 to 17. -- Adding to the contracted graph that additional section on lines 26 to 28. - -.. literalinclude:: contraction-family.queries - :emphasize-lines: 11-17, 26-28 - :start-after: -- case2 - :end-before: -- use2 - :linenos: - -.. rubric:: Case 1 - -When both source and target belong to the contracted graph, a path is found. - -.. literalinclude:: contraction-family.queries - :start-after: -- use2 - :end-before: -- use2-1 - -.. rubric:: Case 2 - -When source and/or target belong to an edge subgraph, now, a path is found. - -The routing graph now has an edge connecting with node :math:`4`. - -.. literalinclude:: contraction-family.queries - :start-after: -- use2-1 - :end-before: -- use2-2 - -.. rubric:: Case 3 - -When source and/or target belong to a vertex then a path is not found. - -In this case, the contracted graph do not have an edge connecting with -node :math:`7`. - -.. literalinclude:: contraction-family.queries - :start-after: -- use2-2 - :end-before: -- case3 - -Case 3: Source and/or target belong to a vertex. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Refining the above function to include nodes that belong to an edge. - -- The vertices that need to be expanded are calculated on lines 19 to 24. -- Adding to the contracted graph that additional section on lines 38 to 40. - -.. literalinclude:: contraction-family.queries - :emphasize-lines: 19-24, 39-41 - :start-after: -- case3 - :end-before: -- use3 - :linenos: - -.. rubric:: Case 1 - -When both source and target belong to the contracted graph, a path is found. - -.. literalinclude:: contraction-family.queries - :start-after: -- use3 - :end-before: -- use3-1 - -.. rubric:: Case 2 - -The code change do not affect this case so when source and/or target belong -to an edge subgraph, a path is still found. - -.. literalinclude:: contraction-family.queries - :start-after: -- use3-1 - :end-before: -- use3-2 - -.. rubric:: Case 3 - -When source and/or target belong to a vertex, now, a path is found. - -Now, the routing graph has an edge connecting with node :math:`7`. - -.. literalinclude:: contraction-family.queries - :start-after: -- use3-2 - :end-before: -- end - See Also ------------------------------------------------------------------------------- diff --git a/doc/contraction/pgr_contraction.rst b/doc/contraction/pgr_contraction.rst index 98f7fd2a941..bb63e599712 100644 --- a/doc/contraction/pgr_contraction.rst +++ b/doc/contraction/pgr_contraction.rst @@ -8,7 +8,7 @@ **************************************************************************** -.. index:: +.. index:: single: Contraction Family ; pgr_contraction single: contraction @@ -22,21 +22,33 @@ vertices and edges. .. rubric:: Availability -* Version 3.0.0 +.. rubric:: Version 3.8.0 + +* New signature: + + * Previously compulsory parameter **Contraction order** is now optional with + name ``methods``. + * New name and order of optional parameters. + +* Deprecated signature pgr_contraction(text,bigint[],integer,bigint[],boolean) - * Result columns change: ``seq`` is removed - * Name change from ``pgr_contractGraph`` - * Bug fixes - * Function promoted to official. +.. rubric:: Version 3.0.0 -* Version 2.3.0 +* Result columns change: ``seq`` is removed +* Name change from ``pgr_contractGraph`` +* Bug fixes +* Function promoted to official. - * New experimental function. +.. rubric:: Version 2.3.0 + +* New experimental function. Description ------------------------------------------------------------------------------- +.. characteristics_start + Contraction reduces the size of the graph by removing some of the vertices and edges and, for example, might add edges that represent a sequence of original edges decreasing the total time and space used in graph algorithms. @@ -44,47 +56,45 @@ edges decreasing the total time and space used in graph algorithms. The main Characteristics are: - Process is done only on edges with positive costs. -- Does not return the full contracted graph +- Does not return the full contracted graph. + + - Only changes on the graph are returned. - - Only changes on the graph are returned +- The returned values include: -- Currnetly there are two types of contraction methods + - The new edges generated by linear contraction. + - The modified vertices generated by dead end contraction. - - Dead End Contraction - - Linear Contraction +- The returned values are ordered as follows: -- The returned values include + - column ``id`` ascending when its a modified vertex. + - column ``id`` with negative numbers descending when its a new edge. - - the added edges by linear contraction. - - the modified vertices by dead end contraction. +.. characteristics_end -- The returned values are ordered as follows: +- Currently there are two types of contraction methods included in this + function: - - column ``id`` ascending when type is ``v`` - - column ``id`` descending when type is ``e`` + - Dead End Contraction. See :doc:`contraction-family`. + - Linear Contraction. See :doc:`contraction-family`. |Boost| Boost Graph Inside Signatures ------------------------------------------------------------------------------- -.. rubric:: Summary - -The pgr_contraction function has the following signature: - .. index:: single: contraction .. admonition:: \ \ :class: signatures - | pgr_contraction(`Edges SQL`_, **contraction order**, [**options**]) + | pgr_contraction(`Edges SQL`_, [**options**]) - | **options:** ``[ max_cycles, forbidden_vertices, directed]`` + | **options:** ``[directed, methods, cycles, forbidden]`` | Returns set of |result-contract| -:Example: Making a dead end and linear contraction in that order on an - undirected graph. +:Example: Dead end and linear contraction in that order on an undirected graph. .. literalinclude:: contraction.queries :start-after: -- q1 @@ -104,12 +114,6 @@ Parameters * - `Edges SQL`_ - ``TEXT`` - `Edges SQL`_ as described below. - * - **contraction Order** - - ``ARRAY[`` **ANY-INTEGER** ``]`` - - Ordered contraction operations. - - - 1 = Dead end contraction - - 2 = Linear contraction Optional parameters ............................................................................... @@ -123,22 +127,29 @@ Contraction optional parameters .. list-table:: :width: 81 - :widths: 19 22 7 40 + :widths: auto :header-rows: 1 * - Column - Type - Default - Description - * - ``forbidden_vertices`` - - ``ARRAY[`` **ANY-INTEGER** ``]`` - - **Empty** - - Identifiers of vertices forbidden for contraction. - * - ``max_cycles`` + * - ``methods`` + - ``INTEGER[]`` + - ``ARRAY[1,2]`` + - Ordered contraction operations. + + - 1 = Dead end contraction + - 2 = Linear contraction + + * - ``cycles`` - ``INTEGER`` - :math:`1` - - Number of times the contraction operations on ``contraction_order`` will - be performed. + - Number of times the contraction methods will be performed. + * - ``forbidden`` + - ``BIGINT[]`` + - ``ARRAY[]::BIGINT[]`` + - Identifiers of vertices forbidden for contraction. Inner Queries ------------------------------------------------------------------------------- @@ -167,14 +178,14 @@ The function returns a single row. The columns of the row are: - Description * - ``type`` - ``TEXT`` - - Type of the ``id``. + - Type of the row. * ``v`` when the row is a vertex. - * Column ``id`` has a positive value + * Column ``id`` has a positive value. * ``e`` when the row is an edge. - * Column ``id`` has a negative value + * Column ``id`` has a negative value. * - ``id`` - ``BIGINT`` - All numbers on this column are ``DISTINCT`` @@ -210,18 +221,222 @@ The function returns a single row. The columns of the row are: Additional Examples ------------------------------------------------------------------------------- -:Example: Only dead end contraction +.. contents:: + :local: + +Only dead end contraction +................................................................................ .. literalinclude:: contraction.queries :start-after: -- q2 :end-before: -- q3 -:Example: Only linear contraction +Only linear contraction +................................................................................ .. literalinclude:: contraction.queries :start-after: -- q3 :end-before: -- q4 +The cycle +................................................................................ + +Contracting a graph, can be done with more than one operation. +The order of the operations affect the resulting contracted graph, after +applying one operation, the set of vertices that can be contracted +by another operation changes. + +This implementation, cycles ``cycles`` times through the ``methods`` . + +.. parsed-literal:: + + + do max_cycles times { + for (operation in operations_order) + { do operation } + } + + + +Contracting sample data +------------------------------------------------------------------------------- + +In this section, building and using a contracted graph will be shown by example. + +- The :doc:`sampledata` for an undirected graph is used +- a dead end operation first followed by a linear operation. + + +.. contents:: + :local: + +Construction of the graph in the database +............................................................................... + +The original graph: + +.. image:: /images/Fig6-undirected.png + :scale: 25% + +The results do not represent the contracted graph. +They represent the changes that need to be done to the graph after applying the +contraction methods. + +Observe that vertices, for example, :math:`6` do not appear in the results +because it was not affected by the contraction algorithm. + +.. literalinclude:: contraction.queries + :start-after: -- cg2 + :end-before: -- cg3 + +After doing the dead end contraction operation: + +.. image:: images/undirected_sampledata_b.png + :scale: 25% + +After doing the linear contraction operation to the graph above: + +.. image:: images/undirected_sampledata_c.png + :scale: 25% + +The process to create the contraction graph on the database: +------------------------------------------------------------------------------- + +.. contents:: + :local: + +Add additional columns +............................................................................... + +Adding extra columns to the edges and vertices tables. +In this documentation the following will be used: + +.. list-table:: + :width: 80 + :widths: auto + :header-rows: 1 + + * - Column. + - Description + * - ``contracted_vertices`` + - The vertices set belonging to the vertex/edge + * - ``is_contracted`` + - On the vertex table + + * when ``true`` the vertex is contracted, its not part of the contracted + graph. + * when ``false`` the vertex is not contracted, its part of the contracted + graph. + * - ``is_new`` + - On the edge table + + * when ``true`` the edge was generated by the contraction algorithm. its + part of the contracted graph. + * when ``false`` the edge is an original edge, might be or not part of + the contracted graph. + +.. literalinclude:: contraction.queries + :start-after: -- cg1 + :end-before: -- cg2 + +Store contraction information +............................................................................... + +Store the contraction results in a table. + +.. literalinclude:: contraction.queries + :start-after: -- cg3 + :end-before: -- cg4 + +Update the edges and vertices tables +............................................................................... + +Use ``is_contracted`` column to indicate the vertices that are contracted. + +.. literalinclude:: contraction.queries + :start-after: -- cg4 + :end-before: -- cg5 + +Fill ``contracted_vertices`` with the information from the results that belong +to the vertices. + +.. literalinclude:: contraction.queries + :start-after: -- cg6 + :end-before: -- cg7 + +Insert the new edges generated by pgr_contraction. + +.. literalinclude:: contraction.queries + :start-after: -- cg7 + :end-before: -- cg8 + +The contracted graph +............................................................................... + +Vertices that belong to the contracted graph. + +.. literalinclude:: contraction.queries + :start-after: -- cg8 + :end-before: -- cg9 + +Edges that belong to the contracted graph. + +.. literalinclude:: contraction.queries + :start-after: -- cg9 + :end-before: -- cg10 + +Visually: + +.. image:: images/newgraph.png + :scale: 25% + +Using the contracted graph +------------------------------------------------------------------------------- + +Depending on the final application the graph is to be prepared. +In this example the final application will be to calculate the cost from two +vertices in the original graph by using the contracted graph with ``pgr_dijkstraCost`` + +There are three cases when calculating the shortest path between a given source +and target in a contracted graph: + +- Case 1: Both source and target belong to the contracted graph. +- Case 2: Source and/or target belong to an edge subgraph. +- Case 3: Source and/or target belong to a vertex. + +The final application should consider all of those cases. + + +Create a view (or table) of the contracted graph: + +.. literalinclude:: contraction.queries + :start-after: -- cg10 + :end-before: -- cg11 + +Create the function that will use the contracted graph. + +.. literalinclude:: contraction.queries + :start-after: -- cg11 + :end-before: -- cg12 + +Case 1: Both source and target belong to the contracted graph. + +.. literalinclude:: contraction.queries + :start-after: -- cg12 + :end-before: -- cg13 + +Case 2: Source and/or target belong to an edge that has contracted vertices. + +.. literalinclude:: contraction.queries + :start-after: -- cg13 + :end-before: -- cg14 + +Case 3: Source and/or target belong to a vertex that has been contracted. + +.. literalinclude:: contraction.queries + :start-after: -- cg14 + :end-before: -- cg15 + See Also ------------------------------------------------------------------------------- From 81fc9ed4ac8298ac9e2bb9b2105a6d6e487a6f65 Mon Sep 17 00:00:00 2001 From: cvvergara Date: Thu, 20 Mar 2025 13:29:36 -0600 Subject: [PATCH 05/11] (lint) removing files no longer in use --- docqueries/contraction/contraction-family.pg | 199 --------- .../contraction/contraction-family.result | 393 ------------------ 2 files changed, 592 deletions(-) delete mode 100644 docqueries/contraction/contraction-family.pg delete mode 100644 docqueries/contraction/contraction-family.result diff --git a/docqueries/contraction/contraction-family.pg b/docqueries/contraction/contraction-family.pg deleted file mode 100644 index ea9c215de90..00000000000 --- a/docqueries/contraction/contraction-family.pg +++ /dev/null @@ -1,199 +0,0 @@ --- CopyRight(c) pgRouting developers --- Creative Commons Attribution-Share Alike 3.0 License : https://creativecommons.org/licenses/by-sa/3.0/ - -/* -- q00 */ -SELECT id, source, target, cost, reverse_cost -FROM edges ORDER BY id; -/* -- q01 */ -/* -- q1 */ -ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false; -ALTER TABLE vertices ADD contracted_vertices BIGINT[]; -ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false; -ALTER TABLE edges ADD contracted_vertices BIGINT[]; -/* -- q2 */ -SELECT * FROM pgr_contraction( - 'SELECT id, source, target, cost, reverse_cost FROM edges', - array[1, 2], directed => false); -/* -- q3 */ -SELECT * INTO contraction_results -FROM pgr_contraction( - 'SELECT id, source, target, cost, reverse_cost FROM edges', - array[1, 2], directed => false); -/* -- q4 */ -UPDATE vertices -SET is_contracted = true -WHERE id IN (SELECT unnest(contracted_vertices) FROM contraction_results); -/* -- q5 */ -SELECT id, is_contracted -FROM vertices -ORDER BY id; -/* -- q6 */ -UPDATE vertices -SET contracted_vertices = contraction_results.contracted_vertices -FROM contraction_results -WHERE type = 'v' AND vertices.id = contraction_results.id; -/* -- q7 */ -SELECT id, contracted_vertices, is_contracted -FROM vertices -ORDER BY id; -/* -- q8 */ -INSERT INTO edges(source, target, cost, reverse_cost, contracted_vertices, is_new) -SELECT source, target, cost, -1, contracted_vertices, true -FROM contraction_results -WHERE type = 'e'; -/* -- q9 */ -SELECT id, source, target, cost, reverse_cost, contracted_vertices, is_new -FROM edges -ORDER BY id; -/* -- q10 */ -SELECT id -FROM vertices -WHERE is_contracted = false -ORDER BY id; -/* -- q11 */ -WITH -vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false -) -SELECT id, source, target, cost, reverse_cost, contracted_vertices -FROM edges -WHERE source IN (SELECT * FROM vertices_in_graph) -AND target IN (SELECT * FROM vertices_in_graph) -ORDER BY id; -/* -- case1 */ -CREATE OR REPLACE FUNCTION my_dijkstra( - departure BIGINT, destination BIGINT, - OUT seq INTEGER, OUT path_seq INTEGER, - OUT start_vid BIGINT, OUT end_vid BIGINT, - OUT node BIGINT, OUT edge BIGINT, - OUT cost FLOAT, OUT agg_cost FLOAT) -RETURNS SETOF RECORD AS -$BODY$ -SELECT * FROM pgr_dijkstra( - $$ - WITH - vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false - ) - SELECT id, source, target, cost, reverse_cost - FROM edges - WHERE source IN (SELECT * FROM vertices_in_graph) - AND target IN (SELECT * FROM vertices_in_graph) - $$, - departure, destination, false); -$BODY$ -LANGUAGE SQL VOLATILE; -/* -- use1 */ -SELECT * FROM my_dijkstra(10, 12); -/* -- use1-1 */ -SELECT * FROM my_dijkstra(15, 12); -/* -- use1-2 */ -SELECT * FROM my_dijkstra(15, 1); -/* -- case2 */ -CREATE OR REPLACE FUNCTION my_dijkstra( - departure BIGINT, destination BIGINT, - OUT seq INTEGER, OUT path_seq INTEGER, - OUT start_vid BIGINT, OUT end_vid BIGINT, - OUT node BIGINT, OUT edge BIGINT, - OUT cost FLOAT, OUT agg_cost FLOAT) -RETURNS SETOF RECORD AS -$BODY$ -SELECT * FROM pgr_dijkstra( - $$ - WITH - edges_to_expand AS ( - SELECT id - FROM edges - WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices - OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices - ), - - vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false - - UNION - - SELECT unnest(contracted_vertices) - FROM edges - WHERE id IN (SELECT id FROM edges_to_expand) - ) - - SELECT id, source, target, cost, reverse_cost - FROM edges - WHERE source IN (SELECT * FROM vertices_in_graph) - AND target IN (SELECT * FROM vertices_in_graph) - $$, - departure, destination, false); -$BODY$ -LANGUAGE SQL VOLATILE; -/* -- use2 */ -SELECT * FROM my_dijkstra(10, 12); -/* -- use2-1 */ -SELECT * FROM my_dijkstra(15, 12); -/* -- use2-2 */ -SELECT * FROM my_dijkstra(15, 1); -/* -- case3 */ -CREATE OR REPLACE FUNCTION my_dijkstra( - departure BIGINT, destination BIGINT, - OUT seq INTEGER, OUT path_seq INTEGER, - OUT start_vid BIGINT, OUT end_vid BIGINT, - OUT node BIGINT, OUT edge BIGINT, - OUT cost FLOAT, OUT agg_cost FLOAT) -RETURNS SETOF RECORD AS -$BODY$ -SELECT * FROM pgr_dijkstra( - $$ - WITH - edges_to_expand AS ( - SELECT id - FROM edges - WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices - OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices - ), - - vertices_to_expand AS ( - SELECT id - FROM vertices - WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices - OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices - ), - - vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false - - UNION - - SELECT unnest(contracted_vertices) - FROM edges - WHERE id IN (SELECT id FROM edges_to_expand) - - UNION - - SELECT unnest(contracted_vertices) - FROM vertices - WHERE id IN (SELECT id FROM vertices_to_expand) - ) - - SELECT id, source, target, cost, reverse_cost - FROM edges - WHERE source IN (SELECT * FROM vertices_in_graph) - AND target IN (SELECT * FROM vertices_in_graph) - $$, - departure, destination, false); -$BODY$ -LANGUAGE SQL VOLATILE; -/* -- use3 */ -SELECT * FROM my_dijkstra(10, 12); -/* -- use3-1 */ -SELECT * FROM my_dijkstra(15, 12); -/* -- use3-2 */ -SELECT * FROM my_dijkstra(15, 1); -/* -- end */ diff --git a/docqueries/contraction/contraction-family.result b/docqueries/contraction/contraction-family.result deleted file mode 100644 index c9a3c2ddc95..00000000000 --- a/docqueries/contraction/contraction-family.result +++ /dev/null @@ -1,393 +0,0 @@ -BEGIN; -BEGIN -SET client_min_messages TO NOTICE; -SET -/* -- q00 */ -SELECT id, source, target, cost, reverse_cost -FROM edges ORDER BY id; - id | source | target | cost | reverse_cost -----+--------+--------+------+-------------- - 1 | 5 | 6 | 1 | 1 - 2 | 6 | 10 | -1 | 1 - 3 | 10 | 15 | -1 | 1 - 4 | 6 | 7 | 1 | 1 - 5 | 10 | 11 | 1 | -1 - 6 | 1 | 3 | 1 | 1 - 7 | 3 | 7 | 1 | 1 - 8 | 7 | 11 | 1 | 1 - 9 | 11 | 16 | 1 | 1 - 10 | 7 | 8 | 1 | 1 - 11 | 11 | 12 | 1 | -1 - 12 | 8 | 12 | 1 | -1 - 13 | 12 | 17 | 1 | -1 - 14 | 8 | 9 | 1 | 1 - 15 | 16 | 17 | 1 | 1 - 16 | 15 | 16 | 1 | 1 - 17 | 2 | 4 | 1 | 1 - 18 | 13 | 14 | 1 | 1 -(18 rows) - -/* -- q01 */ -/* -- q1 */ -ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false; -ALTER TABLE -ALTER TABLE vertices ADD contracted_vertices BIGINT[]; -ALTER TABLE -ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false; -ALTER TABLE -ALTER TABLE edges ADD contracted_vertices BIGINT[]; -ALTER TABLE -/* -- q2 */ -SELECT * FROM pgr_contraction( - 'SELECT id, source, target, cost, reverse_cost FROM edges', - array[1, 2], directed => false); - type | id | contracted_vertices | source | target | cost -------+----+---------------------+--------+--------+------ - v | 4 | {2} | -1 | -1 | -1 - v | 7 | {1,3} | -1 | -1 | -1 - v | 14 | {13} | -1 | -1 | -1 - e | -1 | {5,6} | 7 | 10 | 2 - e | -2 | {8,9} | 7 | 12 | 2 - e | -3 | {17} | 12 | 16 | 2 - e | -4 | {15} | 10 | 16 | 2 -(7 rows) - -/* -- q3 */ -SELECT * INTO contraction_results -FROM pgr_contraction( - 'SELECT id, source, target, cost, reverse_cost FROM edges', - array[1, 2], directed => false); -SELECT 7 -/* -- q4 */ -UPDATE vertices -SET is_contracted = true -WHERE id IN (SELECT unnest(contracted_vertices) FROM contraction_results); -UPDATE 10 -/* -- q5 */ -SELECT id, is_contracted -FROM vertices -ORDER BY id; - id | is_contracted -----+--------------- - 1 | t - 2 | t - 3 | t - 4 | f - 5 | t - 6 | t - 7 | f - 8 | t - 9 | t - 10 | f - 11 | f - 12 | f - 13 | t - 14 | f - 15 | t - 16 | f - 17 | t -(17 rows) - -/* -- q6 */ -UPDATE vertices -SET contracted_vertices = contraction_results.contracted_vertices -FROM contraction_results -WHERE type = 'v' AND vertices.id = contraction_results.id; -UPDATE 3 -/* -- q7 */ -SELECT id, contracted_vertices, is_contracted -FROM vertices -ORDER BY id; - id | contracted_vertices | is_contracted -----+---------------------+--------------- - 1 | | t - 2 | | t - 3 | | t - 4 | {2} | f - 5 | | t - 6 | | t - 7 | {1,3} | f - 8 | | t - 9 | | t - 10 | | f - 11 | | f - 12 | | f - 13 | | t - 14 | {13} | f - 15 | | t - 16 | | f - 17 | | t -(17 rows) - -/* -- q8 */ -INSERT INTO edges(source, target, cost, reverse_cost, contracted_vertices, is_new) -SELECT source, target, cost, -1, contracted_vertices, true -FROM contraction_results -WHERE type = 'e'; -INSERT 0 4 -/* -- q9 */ -SELECT id, source, target, cost, reverse_cost, contracted_vertices, is_new -FROM edges -ORDER BY id; - id | source | target | cost | reverse_cost | contracted_vertices | is_new -----+--------+--------+------+--------------+---------------------+-------- - 1 | 5 | 6 | 1 | 1 | | f - 2 | 6 | 10 | -1 | 1 | | f - 3 | 10 | 15 | -1 | 1 | | f - 4 | 6 | 7 | 1 | 1 | | f - 5 | 10 | 11 | 1 | -1 | | f - 6 | 1 | 3 | 1 | 1 | | f - 7 | 3 | 7 | 1 | 1 | | f - 8 | 7 | 11 | 1 | 1 | | f - 9 | 11 | 16 | 1 | 1 | | f - 10 | 7 | 8 | 1 | 1 | | f - 11 | 11 | 12 | 1 | -1 | | f - 12 | 8 | 12 | 1 | -1 | | f - 13 | 12 | 17 | 1 | -1 | | f - 14 | 8 | 9 | 1 | 1 | | f - 15 | 16 | 17 | 1 | 1 | | f - 16 | 15 | 16 | 1 | 1 | | f - 17 | 2 | 4 | 1 | 1 | | f - 18 | 13 | 14 | 1 | 1 | | f - 19 | 7 | 10 | 2 | -1 | {5,6} | t - 20 | 7 | 12 | 2 | -1 | {8,9} | t - 21 | 12 | 16 | 2 | -1 | {17} | t - 22 | 10 | 16 | 2 | -1 | {15} | t -(22 rows) - -/* -- q10 */ -SELECT id -FROM vertices -WHERE is_contracted = false -ORDER BY id; - id ----- - 4 - 7 - 10 - 11 - 12 - 14 - 16 -(7 rows) - -/* -- q11 */ -WITH -vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false -) -SELECT id, source, target, cost, reverse_cost, contracted_vertices -FROM edges -WHERE source IN (SELECT * FROM vertices_in_graph) -AND target IN (SELECT * FROM vertices_in_graph) -ORDER BY id; - id | source | target | cost | reverse_cost | contracted_vertices -----+--------+--------+------+--------------+--------------------- - 5 | 10 | 11 | 1 | -1 | - 8 | 7 | 11 | 1 | 1 | - 9 | 11 | 16 | 1 | 1 | - 11 | 11 | 12 | 1 | -1 | - 19 | 7 | 10 | 2 | -1 | {5,6} - 20 | 7 | 12 | 2 | -1 | {8,9} - 21 | 12 | 16 | 2 | -1 | {17} - 22 | 10 | 16 | 2 | -1 | {15} -(8 rows) - -/* -- case1 */ -CREATE OR REPLACE FUNCTION my_dijkstra( - departure BIGINT, destination BIGINT, - OUT seq INTEGER, OUT path_seq INTEGER, - OUT start_vid BIGINT, OUT end_vid BIGINT, - OUT node BIGINT, OUT edge BIGINT, - OUT cost FLOAT, OUT agg_cost FLOAT) -RETURNS SETOF RECORD AS -$BODY$ -SELECT * FROM pgr_dijkstra( - $$ - WITH - vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false - ) - SELECT id, source, target, cost, reverse_cost - FROM edges - WHERE source IN (SELECT * FROM vertices_in_graph) - AND target IN (SELECT * FROM vertices_in_graph) - $$, - departure, destination, false); -$BODY$ -LANGUAGE SQL VOLATILE; -CREATE FUNCTION -/* -- use1 */ -SELECT * FROM my_dijkstra(10, 12); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- - 1 | 1 | 10 | 12 | 10 | 5 | 1 | 0 - 2 | 2 | 10 | 12 | 11 | 11 | 1 | 1 - 3 | 3 | 10 | 12 | 12 | -1 | 0 | 2 -(3 rows) - -/* -- use1-1 */ -SELECT * FROM my_dijkstra(15, 12); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- -(0 rows) - -/* -- use1-2 */ -SELECT * FROM my_dijkstra(15, 1); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- -(0 rows) - -/* -- case2 */ -CREATE OR REPLACE FUNCTION my_dijkstra( - departure BIGINT, destination BIGINT, - OUT seq INTEGER, OUT path_seq INTEGER, - OUT start_vid BIGINT, OUT end_vid BIGINT, - OUT node BIGINT, OUT edge BIGINT, - OUT cost FLOAT, OUT agg_cost FLOAT) -RETURNS SETOF RECORD AS -$BODY$ -SELECT * FROM pgr_dijkstra( - $$ - WITH - edges_to_expand AS ( - SELECT id - FROM edges - WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices - OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices - ), - - vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false - - UNION - - SELECT unnest(contracted_vertices) - FROM edges - WHERE id IN (SELECT id FROM edges_to_expand) - ) - - SELECT id, source, target, cost, reverse_cost - FROM edges - WHERE source IN (SELECT * FROM vertices_in_graph) - AND target IN (SELECT * FROM vertices_in_graph) - $$, - departure, destination, false); -$BODY$ -LANGUAGE SQL VOLATILE; -CREATE FUNCTION -/* -- use2 */ -SELECT * FROM my_dijkstra(10, 12); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- - 1 | 1 | 10 | 12 | 10 | 5 | 1 | 0 - 2 | 2 | 10 | 12 | 11 | 11 | 1 | 1 - 3 | 3 | 10 | 12 | 12 | -1 | 0 | 2 -(3 rows) - -/* -- use2-1 */ -SELECT * FROM my_dijkstra(15, 12); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- - 1 | 1 | 15 | 12 | 15 | 16 | 1 | 0 - 2 | 2 | 15 | 12 | 16 | 21 | 2 | 1 - 3 | 3 | 15 | 12 | 12 | -1 | 0 | 3 -(3 rows) - -/* -- use2-2 */ -SELECT * FROM my_dijkstra(15, 1); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- -(0 rows) - -/* -- case3 */ -CREATE OR REPLACE FUNCTION my_dijkstra( - departure BIGINT, destination BIGINT, - OUT seq INTEGER, OUT path_seq INTEGER, - OUT start_vid BIGINT, OUT end_vid BIGINT, - OUT node BIGINT, OUT edge BIGINT, - OUT cost FLOAT, OUT agg_cost FLOAT) -RETURNS SETOF RECORD AS -$BODY$ -SELECT * FROM pgr_dijkstra( - $$ - WITH - edges_to_expand AS ( - SELECT id - FROM edges - WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices - OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices - ), - - vertices_to_expand AS ( - SELECT id - FROM vertices - WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices - OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices - ), - - vertices_in_graph AS ( - SELECT id - FROM vertices - WHERE is_contracted = false - - UNION - - SELECT unnest(contracted_vertices) - FROM edges - WHERE id IN (SELECT id FROM edges_to_expand) - - UNION - - SELECT unnest(contracted_vertices) - FROM vertices - WHERE id IN (SELECT id FROM vertices_to_expand) - ) - - SELECT id, source, target, cost, reverse_cost - FROM edges - WHERE source IN (SELECT * FROM vertices_in_graph) - AND target IN (SELECT * FROM vertices_in_graph) - $$, - departure, destination, false); -$BODY$ -LANGUAGE SQL VOLATILE; -CREATE FUNCTION -/* -- use3 */ -SELECT * FROM my_dijkstra(10, 12); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- - 1 | 1 | 10 | 12 | 10 | 5 | 1 | 0 - 2 | 2 | 10 | 12 | 11 | 11 | 1 | 1 - 3 | 3 | 10 | 12 | 12 | -1 | 0 | 2 -(3 rows) - -/* -- use3-1 */ -SELECT * FROM my_dijkstra(15, 12); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- - 1 | 1 | 15 | 12 | 15 | 16 | 1 | 0 - 2 | 2 | 15 | 12 | 16 | 21 | 2 | 1 - 3 | 3 | 15 | 12 | 12 | -1 | 0 | 3 -(3 rows) - -/* -- use3-2 */ -SELECT * FROM my_dijkstra(15, 1); - seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost ------+----------+-----------+---------+------+------+------+---------- - 1 | 1 | 15 | 1 | 15 | 3 | 1 | 0 - 2 | 2 | 15 | 1 | 10 | 19 | 2 | 1 - 3 | 3 | 15 | 1 | 7 | 7 | 1 | 3 - 4 | 4 | 15 | 1 | 3 | 6 | 1 | 4 - 5 | 5 | 15 | 1 | 1 | -1 | 0 | 5 -(5 rows) - -/* -- end */ -ROLLBACK; -ROLLBACK From 7ea07eb9a714336a41a4755ef54d4557dfb2ba63 Mon Sep 17 00:00:00 2001 From: cvvergara Date: Thu, 20 Mar 2025 13:32:11 -0600 Subject: [PATCH 06/11] (doc) documenting changes on release notes & NEWS --- NEWS.md | 11 +++++++++++ doc/src/release_notes.rst | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/NEWS.md b/NEWS.md index 9e9e0481868..2b27e1ebf24 100644 --- a/NEWS.md +++ b/NEWS.md @@ -27,6 +27,17 @@ * ``partial`` option is removed. * Function promoted to official. +**Official functions changes** + +* [#2786](https://github.com/pgRouting/pgrouting/issues/2786): pgr_contraction + + * New signature: + * Previously compulsory parameter **Contraction order** is now optional with + name ``methods``. + * New name and order of optional parameters. + * Deprecated signature pgr_contraction(text,bigint[],integer,bigint[],boolean) + + ## pgRouting 3.7 ### pgRouting 3.7.3 Release Notes diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index 1923acd8029..a5109bcdcb8 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -59,6 +59,15 @@ pgRouting 3.8.0 Release Notes :start-after: Version 3.8.0 :end-before: .. rubric +.. rubric:: Official functions changes + +* `#2786 `__: pgr_contraction + + .. include:: pgr_contraction.rst + :start-after: Version 3.8.0 + :end-before: .. rubric + + pgRouting 3.7 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ From e8c8bcdd84fd52e12e8ced98596e4bdc73567f3b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 04:11:34 +0000 Subject: [PATCH 07/11] Update locale: commit 7ea07eb9a --- .../en/LC_MESSAGES/pgrouting_doc_strings.po | 528 ++++++++---------- locale/pot/pgrouting_doc_strings.pot | 443 +++++++-------- 2 files changed, 443 insertions(+), 528 deletions(-) diff --git a/locale/en/LC_MESSAGES/pgrouting_doc_strings.po b/locale/en/LC_MESSAGES/pgrouting_doc_strings.po index 68f47f7affc..b1fbde5af52 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 v3.8\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-08 16:36+0000\n" +"POT-Creation-Date: 2025-03-21 04:11+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -2970,7 +2970,7 @@ msgstr "" msgid "Linear vertex on directed graph" msgstr "" -msgid "The white node is not linear because the linearity is not symetrical." +msgid "The white node is not linear because the linearity is not symmetrical." msgstr "" msgid "It is possible to go :math:`y \\rightarrow c \\rightarrow z`" @@ -3046,252 +3046,6 @@ msgid "" "contracted." msgstr "" -msgid "The cycle" -msgstr "" - -msgid "" -"Contracting a graph, can be done with more than one operation. The order " -"of the operations affect the resulting contracted graph, after applying " -"one operation, the set of vertices that can be contracted by another " -"operation changes." -msgstr "" - -msgid "" -"This implementation, cycles ``max_cycles`` times through " -"``operations_order`` ." -msgstr "" - -msgid "Contracting sample data" -msgstr "" - -msgid "" -"In this section, building and using a contracted graph will be shown by " -"example." -msgstr "" - -msgid "The :doc:`sampledata` for an undirected graph is used" -msgstr "" - -msgid "a dead end operation first followed by a linear operation." -msgstr "" - -msgid "Construction of the graph in the database" -msgstr "" - -msgid "Original Data" -msgstr "" - -msgid "" -"The following query shows the original data involved in the contraction " -"operation." -msgstr "" - -msgid "The original graph:" -msgstr "" - -msgid "Contraction results" -msgstr "" - -msgid "" -"The results do not represent the contracted graph. They represent the " -"changes done to the graph after applying the contraction algorithm." -msgstr "" - -msgid "" -"Observe that vertices, for example, :math:`6` do not appear in the " -"results because it was not affected by the contraction algorithm." -msgstr "" - -msgid "After doing the dead end contraction operation:" -msgstr "" - -msgid "After doing the linear contraction operation to the graph above:" -msgstr "" - -msgid "The process to create the contraction graph on the database:" -msgstr "" - -msgid "Add additional columns" -msgstr "" - -msgid "" -"Adding extra columns to the ``edge_table`` and " -"``edge_table_vertices_pgr`` tables, where:" -msgstr "" - -msgid "``contracted_vertices``" -msgstr "" - -msgid "The vertices set belonging to the vertex/edge" -msgstr "" - -msgid "``is_contracted``" -msgstr "" - -msgid "On the vertex table" -msgstr "" - -msgid "" -"when ``true`` the vertex is contracted, its not part of the contracted " -"graph." -msgstr "" - -msgid "" -"when ``false`` the vertex is not contracted, its part of the contracted " -"graph." -msgstr "" - -msgid "``is_new``" -msgstr "" - -msgid "On the edge table" -msgstr "" - -msgid "" -"when ``true`` the edge was generated by the contraction algorithm. its " -"part of the contracted graph." -msgstr "" - -msgid "" -"when ``false`` the edge is an original edge, might be or not part of the " -"contracted graph." -msgstr "" - -msgid "Store contraction information" -msgstr "" - -msgid "Store the `contraction results`_ in a table" -msgstr "" - -msgid "The vertex table update" -msgstr "" - -msgid "Use ``is_contracted`` column to indicate the vertices that are contracted." -msgstr "" - -msgid "" -"Fill ``contracted_vertices`` with the information from the results tha " -"belong to the vertices." -msgstr "" - -msgid "The modified vertices table:" -msgstr "" - -msgid "The edge table update" -msgstr "" - -msgid "Insert the new edges generated by pgr_contraction." -msgstr "" - -msgid "The modified ``edge_table``." -msgstr "" - -msgid "The contracted graph" -msgstr "" - -msgid "Vertices that belong to the contracted graph." -msgstr "" - -msgid "Edges that belong to the contracted graph." -msgstr "" - -msgid "Contracted graph" -msgstr "" - -msgid "Using the contracted graph" -msgstr "" - -msgid "Using the contracted graph with ``pgr_dijkstra``" -msgstr "" - -msgid "" -"There are three cases when calculating the shortest path between a given " -"source and target in a contracted graph:" -msgstr "" - -msgid "Case 1: Both source and target belong to the contracted graph." -msgstr "" - -msgid "Case 2: Source and/or target belong to an edge subgraph." -msgstr "" - -msgid "Case 3: Source and/or target belong to a vertex." -msgstr "" - -msgid "Using the `Edges that belong to the contracted graph.`_ on lines 11 to 20." -msgstr "" - -msgid "Case 1" -msgstr "" - -msgid "" -"When both source and target belong to the contracted graph, a path is " -"found." -msgstr "" - -msgid "Case 2" -msgstr "" - -msgid "" -"When source and/or target belong to an edge subgraph then a path is not " -"found." -msgstr "" - -msgid "" -"In this case, the contracted graph do not have an edge connecting with " -"node :math:`4`." -msgstr "" - -msgid "Case 3" -msgstr "" - -msgid "When source and/or target belong to a vertex then a path is not found." -msgstr "" - -msgid "" -"In this case, the contracted graph do not have an edge connecting with " -"node :math:`7` and of node :math:`4` of the second case." -msgstr "" - -msgid "Refining the above function to include nodes that belong to an edge." -msgstr "" - -msgid "The vertices that need to be expanded are calculated on lines 11 to 17." -msgstr "" - -msgid "Adding to the contracted graph that additional section on lines 26 to 28." -msgstr "" - -msgid "" -"When source and/or target belong to an edge subgraph, now, a path is " -"found." -msgstr "" - -msgid "The routing graph now has an edge connecting with node :math:`4`." -msgstr "" - -msgid "" -"In this case, the contracted graph do not have an edge connecting with " -"node :math:`7`." -msgstr "" - -msgid "The vertices that need to be expanded are calculated on lines 19 to 24." -msgstr "" - -msgid "Adding to the contracted graph that additional section on lines 38 to 40." -msgstr "" - -msgid "" -"The code change do not affect this case so when source and/or target " -"belong to an edge subgraph, a path is still found." -msgstr "" - -msgid "When source and/or target belong to a vertex, now, a path is found." -msgstr "" - -msgid "Now, the routing graph has an edge connecting with node :math:`7`." -msgstr "" - msgid "https://www.cs.cmu.edu/afs/cs/academic/class/15210-f12/www/lectures/lecture16.pdf" msgstr "" @@ -4435,6 +4189,30 @@ msgstr "" msgid "``partial`` option is removed." msgstr "" +msgid "Official functions changes" +msgstr "" + +msgid "" +"`#2786 `__: " +"pgr_contraction" +msgstr "" + +msgid "New signature:" +msgstr "" + +msgid "" +"Previously compulsory parameter **Contraction order** is now optional " +"with name ``methods``." +msgstr "" + +msgid "New name and order of optional parameters." +msgstr "" + +msgid "" +"Deprecated signature " +"pgr_contraction(text,bigint[],integer,bigint[],boolean)" +msgstr "" + msgid "All releases" msgstr "" @@ -9562,6 +9340,9 @@ msgid "" "contracted vertices and edges." msgstr "" +msgid "Version 3.8.0" +msgstr "" + msgid "Name change from ``pgr_contractGraph``" msgstr "" @@ -9575,57 +9356,63 @@ msgid "" "graph algorithms." msgstr "" -msgid "Does not return the full contracted graph" +msgid "Does not return the full contracted graph." msgstr "" -msgid "Only changes on the graph are returned" +msgid "Only changes on the graph are returned." msgstr "" -msgid "Currnetly there are two types of contraction methods" +msgid "The returned values include:" msgstr "" -msgid "Dead End Contraction" +msgid "The new edges generated by linear contraction." msgstr "" -msgid "Linear Contraction" +msgid "The modified vertices generated by dead end contraction." msgstr "" -msgid "The returned values include" +msgid "The returned values are ordered as follows:" msgstr "" -msgid "the added edges by linear contraction." +msgid "column ``id`` ascending when its a modified vertex." msgstr "" -msgid "the modified vertices by dead end contraction." +msgid "column ``id`` with negative numbers descending when its a new edge." msgstr "" -msgid "The returned values are ordered as follows:" +msgid "" +"Currently there are two types of contraction methods included in this " +"function:" msgstr "" -msgid "column ``id`` ascending when type is ``v``" +msgid "Dead End Contraction. See :doc:`contraction-family`." msgstr "" -msgid "column ``id`` descending when type is ``e``" +msgid "Linear Contraction. See :doc:`contraction-family`." msgstr "" -msgid "The pgr_contraction function has the following signature:" +msgid "pgr_contraction(`Edges SQL`_, [**options**])" msgstr "" -msgid "pgr_contraction(`Edges SQL`_, **contraction order**, [**options**])" +msgid "**options:** ``[directed, methods, cycles, forbidden]``" msgstr "" -msgid "**options:** ``[ max_cycles, forbidden_vertices, directed]``" +msgid "Returns set of |result-contract|" msgstr "" -msgid "Returns set of |result-contract|" +msgid "Dead end and linear contraction in that order on an undirected graph." msgstr "" -msgid "" -"Making a dead end and linear contraction in that order on an undirected " -"graph." +msgid "Contraction optional parameters" msgstr "" -msgid "**contraction Order**" +msgid "``methods``" +msgstr "" + +msgid "``INTEGER[]``" +msgstr "" + +msgid "``ARRAY[1,2]``" msgstr "" msgid "Ordered contraction operations." @@ -9637,24 +9424,25 @@ msgstr "" msgid "2 = Linear contraction" msgstr "" -msgid "Contraction optional parameters" +msgid "``cycles``" msgstr "" -msgid "``forbidden_vertices``" +msgid ":math:`1`" msgstr "" -msgid "**Empty**" +msgid "Number of times the contraction methods will be performed." msgstr "" -msgid "Identifiers of vertices forbidden for contraction." +msgid "``forbidden``" msgstr "" -msgid ":math:`1`" +msgid "``BIGINT[]``" msgstr "" -msgid "" -"Number of times the contraction operations on ``contraction_order`` will " -"be performed." +msgid "``ARRAY[]::BIGINT[]``" +msgstr "" + +msgid "Identifiers of vertices forbidden for contraction." msgstr "" msgid "The function returns a single row. The columns of the row are:" @@ -9663,19 +9451,19 @@ msgstr "" msgid "``type``" msgstr "" -msgid "Type of the ``id``." +msgid "Type of the row." msgstr "" msgid "``v`` when the row is a vertex." msgstr "" -msgid "Column ``id`` has a positive value" +msgid "Column ``id`` has a positive value." msgstr "" msgid "``e`` when the row is an edge." msgstr "" -msgid "Column ``id`` has a negative value" +msgid "Column ``id`` has a negative value." msgstr "" msgid "All numbers on this column are ``DISTINCT``" @@ -9698,6 +9486,9 @@ msgid "" "edges." msgstr "" +msgid "``contracted_vertices``" +msgstr "" + msgid "Array of contracted vertex identifiers." msgstr "" @@ -9725,6 +9516,178 @@ msgstr "" msgid "Only linear contraction" msgstr "" +msgid "The cycle" +msgstr "" + +msgid "" +"Contracting a graph, can be done with more than one operation. The order " +"of the operations affect the resulting contracted graph, after applying " +"one operation, the set of vertices that can be contracted by another " +"operation changes." +msgstr "" + +msgid "This implementation, cycles ``cycles`` times through the ``methods`` ." +msgstr "" + +msgid "Contracting sample data" +msgstr "" + +msgid "" +"In this section, building and using a contracted graph will be shown by " +"example." +msgstr "" + +msgid "The :doc:`sampledata` for an undirected graph is used" +msgstr "" + +msgid "a dead end operation first followed by a linear operation." +msgstr "" + +msgid "Construction of the graph in the database" +msgstr "" + +msgid "The original graph:" +msgstr "" + +msgid "" +"The results do not represent the contracted graph. They represent the " +"changes that need to be done to the graph after applying the contraction " +"methods." +msgstr "" + +msgid "" +"Observe that vertices, for example, :math:`6` do not appear in the " +"results because it was not affected by the contraction algorithm." +msgstr "" + +msgid "After doing the dead end contraction operation:" +msgstr "" + +msgid "After doing the linear contraction operation to the graph above:" +msgstr "" + +msgid "The process to create the contraction graph on the database:" +msgstr "" + +msgid "Add additional columns" +msgstr "" + +msgid "" +"Adding extra columns to the edges and vertices tables. In this " +"documentation the following will be used:" +msgstr "" + +msgid "Column." +msgstr "" + +msgid "The vertices set belonging to the vertex/edge" +msgstr "" + +msgid "``is_contracted``" +msgstr "" + +msgid "On the vertex table" +msgstr "" + +msgid "" +"when ``true`` the vertex is contracted, its not part of the contracted " +"graph." +msgstr "" + +msgid "" +"when ``false`` the vertex is not contracted, its part of the contracted " +"graph." +msgstr "" + +msgid "``is_new``" +msgstr "" + +msgid "On the edge table" +msgstr "" + +msgid "" +"when ``true`` the edge was generated by the contraction algorithm. its " +"part of the contracted graph." +msgstr "" + +msgid "" +"when ``false`` the edge is an original edge, might be or not part of the " +"contracted graph." +msgstr "" + +msgid "Store contraction information" +msgstr "" + +msgid "Store the contraction results in a table." +msgstr "" + +msgid "Update the edges and vertices tables" +msgstr "" + +msgid "Use ``is_contracted`` column to indicate the vertices that are contracted." +msgstr "" + +msgid "" +"Fill ``contracted_vertices`` with the information from the results that " +"belong to the vertices." +msgstr "" + +msgid "Insert the new edges generated by pgr_contraction." +msgstr "" + +msgid "The contracted graph" +msgstr "" + +msgid "Vertices that belong to the contracted graph." +msgstr "" + +msgid "Edges that belong to the contracted graph." +msgstr "" + +msgid "Visually:" +msgstr "" + +msgid "Using the contracted graph" +msgstr "" + +msgid "" +"Depending on the final application the graph is to be prepared. In this " +"example the final application will be to calculate the cost from two " +"vertices in the original graph by using the contracted graph with " +"``pgr_dijkstraCost``" +msgstr "" + +msgid "" +"There are three cases when calculating the shortest path between a given " +"source and target in a contracted graph:" +msgstr "" + +msgid "Case 1: Both source and target belong to the contracted graph." +msgstr "" + +msgid "Case 2: Source and/or target belong to an edge subgraph." +msgstr "" + +msgid "Case 3: Source and/or target belong to a vertex." +msgstr "" + +msgid "The final application should consider all of those cases." +msgstr "" + +msgid "Create a view (or table) of the contracted graph:" +msgstr "" + +msgid "Create the function that will use the contracted graph." +msgstr "" + +msgid "" +"Case 2: Source and/or target belong to an edge that has contracted " +"vertices." +msgstr "" + +msgid "Case 3: Source and/or target belong to a vertex that has been contracted." +msgstr "" + msgid "``pgr_createTopology``" msgstr "" @@ -10245,9 +10208,6 @@ msgid "" " of edges incident to the vertex." msgstr "" -msgid "Version 3.8.0" -msgstr "" - msgid "Calculates the degree of the vertices of an undirected graph" msgstr "" @@ -10343,9 +10303,6 @@ msgstr "" msgid "``in_edges``" msgstr "" -msgid "``BIGINT[]``" -msgstr "" - msgid "" "Array of identifiers of the edges that have the vertex ``id`` as *first " "end point*." @@ -15441,9 +15398,6 @@ msgstr "" msgid "pgr_betweennessCentrality" msgstr "" -msgid "Official functions changes" -msgstr "" - msgid "" "`#2605 `__ Standardize " "spanning tree functions output" diff --git a/locale/pot/pgrouting_doc_strings.pot b/locale/pot/pgrouting_doc_strings.pot index d153b50311e..62a8f0203a7 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 v3.8\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-08 16:36+0000\n" +"POT-Creation-Date: 2025-03-21 04:11+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -2725,7 +2725,7 @@ msgstr "" msgid "Linear vertex on directed graph" msgstr "" -msgid "The white node is not linear because the linearity is not symetrical." +msgid "The white node is not linear because the linearity is not symmetrical." msgstr "" msgid "It is possible to go :math:`y \\rightarrow c \\rightarrow z`" @@ -2785,210 +2785,6 @@ msgstr "" msgid "Edge :math:`u \\rightarrow z` has the information of nodes that were contracted." msgstr "" -msgid "The cycle" -msgstr "" - -msgid "Contracting a graph, can be done with more than one operation. The order of the operations affect the resulting contracted graph, after applying one operation, the set of vertices that can be contracted by another operation changes." -msgstr "" - -msgid "This implementation, cycles ``max_cycles`` times through ``operations_order`` ." -msgstr "" - -msgid "Contracting sample data" -msgstr "" - -msgid "In this section, building and using a contracted graph will be shown by example." -msgstr "" - -msgid "The :doc:`sampledata` for an undirected graph is used" -msgstr "" - -msgid "a dead end operation first followed by a linear operation." -msgstr "" - -msgid "Construction of the graph in the database" -msgstr "" - -msgid "Original Data" -msgstr "" - -msgid "The following query shows the original data involved in the contraction operation." -msgstr "" - -msgid "The original graph:" -msgstr "" - -msgid "Contraction results" -msgstr "" - -msgid "The results do not represent the contracted graph. They represent the changes done to the graph after applying the contraction algorithm." -msgstr "" - -msgid "Observe that vertices, for example, :math:`6` do not appear in the results because it was not affected by the contraction algorithm." -msgstr "" - -msgid "After doing the dead end contraction operation:" -msgstr "" - -msgid "After doing the linear contraction operation to the graph above:" -msgstr "" - -msgid "The process to create the contraction graph on the database:" -msgstr "" - -msgid "Add additional columns" -msgstr "" - -msgid "Adding extra columns to the ``edge_table`` and ``edge_table_vertices_pgr`` tables, where:" -msgstr "" - -msgid "``contracted_vertices``" -msgstr "" - -msgid "The vertices set belonging to the vertex/edge" -msgstr "" - -msgid "``is_contracted``" -msgstr "" - -msgid "On the vertex table" -msgstr "" - -msgid "when ``true`` the vertex is contracted, its not part of the contracted graph." -msgstr "" - -msgid "when ``false`` the vertex is not contracted, its part of the contracted graph." -msgstr "" - -msgid "``is_new``" -msgstr "" - -msgid "On the edge table" -msgstr "" - -msgid "when ``true`` the edge was generated by the contraction algorithm. its part of the contracted graph." -msgstr "" - -msgid "when ``false`` the edge is an original edge, might be or not part of the contracted graph." -msgstr "" - -msgid "Store contraction information" -msgstr "" - -msgid "Store the `contraction results`_ in a table" -msgstr "" - -msgid "The vertex table update" -msgstr "" - -msgid "Use ``is_contracted`` column to indicate the vertices that are contracted." -msgstr "" - -msgid "Fill ``contracted_vertices`` with the information from the results tha belong to the vertices." -msgstr "" - -msgid "The modified vertices table:" -msgstr "" - -msgid "The edge table update" -msgstr "" - -msgid "Insert the new edges generated by pgr_contraction." -msgstr "" - -msgid "The modified ``edge_table``." -msgstr "" - -msgid "The contracted graph" -msgstr "" - -msgid "Vertices that belong to the contracted graph." -msgstr "" - -msgid "Edges that belong to the contracted graph." -msgstr "" - -msgid "Contracted graph" -msgstr "" - -msgid "Using the contracted graph" -msgstr "" - -msgid "Using the contracted graph with ``pgr_dijkstra``" -msgstr "" - -msgid "There are three cases when calculating the shortest path between a given source and target in a contracted graph:" -msgstr "" - -msgid "Case 1: Both source and target belong to the contracted graph." -msgstr "" - -msgid "Case 2: Source and/or target belong to an edge subgraph." -msgstr "" - -msgid "Case 3: Source and/or target belong to a vertex." -msgstr "" - -msgid "Using the `Edges that belong to the contracted graph.`_ on lines 11 to 20." -msgstr "" - -msgid "Case 1" -msgstr "" - -msgid "When both source and target belong to the contracted graph, a path is found." -msgstr "" - -msgid "Case 2" -msgstr "" - -msgid "When source and/or target belong to an edge subgraph then a path is not found." -msgstr "" - -msgid "In this case, the contracted graph do not have an edge connecting with node :math:`4`." -msgstr "" - -msgid "Case 3" -msgstr "" - -msgid "When source and/or target belong to a vertex then a path is not found." -msgstr "" - -msgid "In this case, the contracted graph do not have an edge connecting with node :math:`7` and of node :math:`4` of the second case." -msgstr "" - -msgid "Refining the above function to include nodes that belong to an edge." -msgstr "" - -msgid "The vertices that need to be expanded are calculated on lines 11 to 17." -msgstr "" - -msgid "Adding to the contracted graph that additional section on lines 26 to 28." -msgstr "" - -msgid "When source and/or target belong to an edge subgraph, now, a path is found." -msgstr "" - -msgid "The routing graph now has an edge connecting with node :math:`4`." -msgstr "" - -msgid "In this case, the contracted graph do not have an edge connecting with node :math:`7`." -msgstr "" - -msgid "The vertices that need to be expanded are calculated on lines 19 to 24." -msgstr "" - -msgid "Adding to the contracted graph that additional section on lines 38 to 40." -msgstr "" - -msgid "The code change do not affect this case so when source and/or target belong to an edge subgraph, a path is still found." -msgstr "" - -msgid "When source and/or target belong to a vertex, now, a path is found." -msgstr "" - -msgid "Now, the routing graph has an edge connecting with node :math:`7`." -msgstr "" - msgid "https://www.cs.cmu.edu/afs/cs/academic/class/15210-f12/www/lectures/lecture16.pdf" msgstr "" @@ -3955,6 +3751,24 @@ msgstr "" msgid "``partial`` option is removed." msgstr "" +msgid "Official functions changes" +msgstr "" + +msgid "`#2786 `__: pgr_contraction" +msgstr "" + +msgid "New signature:" +msgstr "" + +msgid "Previously compulsory parameter **Contraction order** is now optional with name ``methods``." +msgstr "" + +msgid "New name and order of optional parameters." +msgstr "" + +msgid "Deprecated signature pgr_contraction(text,bigint[],integer,bigint[],boolean)" +msgstr "" + msgid "All releases" msgstr "" @@ -8200,6 +8014,9 @@ msgstr "" msgid "``pgr_contraction`` — Performs graph contraction and returns the contracted vertices and edges." msgstr "" +msgid "Version 3.8.0" +msgstr "" + msgid "Name change from ``pgr_contractGraph``" msgstr "" @@ -8209,55 +8026,61 @@ msgstr "" msgid "Contraction reduces the size of the graph by removing some of the vertices and edges and, for example, might add edges that represent a sequence of original edges decreasing the total time and space used in graph algorithms." msgstr "" -msgid "Does not return the full contracted graph" +msgid "Does not return the full contracted graph." msgstr "" -msgid "Only changes on the graph are returned" +msgid "Only changes on the graph are returned." msgstr "" -msgid "Currnetly there are two types of contraction methods" +msgid "The returned values include:" msgstr "" -msgid "Dead End Contraction" +msgid "The new edges generated by linear contraction." msgstr "" -msgid "Linear Contraction" +msgid "The modified vertices generated by dead end contraction." msgstr "" -msgid "The returned values include" +msgid "The returned values are ordered as follows:" msgstr "" -msgid "the added edges by linear contraction." +msgid "column ``id`` ascending when its a modified vertex." msgstr "" -msgid "the modified vertices by dead end contraction." +msgid "column ``id`` with negative numbers descending when its a new edge." msgstr "" -msgid "The returned values are ordered as follows:" +msgid "Currently there are two types of contraction methods included in this function:" msgstr "" -msgid "column ``id`` ascending when type is ``v``" +msgid "Dead End Contraction. See :doc:`contraction-family`." msgstr "" -msgid "column ``id`` descending when type is ``e``" +msgid "Linear Contraction. See :doc:`contraction-family`." msgstr "" -msgid "The pgr_contraction function has the following signature:" +msgid "pgr_contraction(`Edges SQL`_, [**options**])" msgstr "" -msgid "pgr_contraction(`Edges SQL`_, **contraction order**, [**options**])" +msgid "**options:** ``[directed, methods, cycles, forbidden]``" msgstr "" -msgid "**options:** ``[ max_cycles, forbidden_vertices, directed]``" +msgid "Returns set of |result-contract|" msgstr "" -msgid "Returns set of |result-contract|" +msgid "Dead end and linear contraction in that order on an undirected graph." +msgstr "" + +msgid "Contraction optional parameters" msgstr "" -msgid "Making a dead end and linear contraction in that order on an undirected graph." +msgid "``methods``" msgstr "" -msgid "**contraction Order**" +msgid "``INTEGER[]``" +msgstr "" + +msgid "``ARRAY[1,2]``" msgstr "" msgid "Ordered contraction operations." @@ -8269,22 +8092,25 @@ msgstr "" msgid "2 = Linear contraction" msgstr "" -msgid "Contraction optional parameters" +msgid "``cycles``" msgstr "" -msgid "``forbidden_vertices``" +msgid ":math:`1`" msgstr "" -msgid "**Empty**" +msgid "Number of times the contraction methods will be performed." msgstr "" -msgid "Identifiers of vertices forbidden for contraction." +msgid "``forbidden``" msgstr "" -msgid ":math:`1`" +msgid "``BIGINT[]``" msgstr "" -msgid "Number of times the contraction operations on ``contraction_order`` will be performed." +msgid "``ARRAY[]::BIGINT[]``" +msgstr "" + +msgid "Identifiers of vertices forbidden for contraction." msgstr "" msgid "The function returns a single row. The columns of the row are:" @@ -8293,19 +8119,19 @@ msgstr "" msgid "``type``" msgstr "" -msgid "Type of the ``id``." +msgid "Type of the row." msgstr "" msgid "``v`` when the row is a vertex." msgstr "" -msgid "Column ``id`` has a positive value" +msgid "Column ``id`` has a positive value." msgstr "" msgid "``e`` when the row is an edge." msgstr "" -msgid "Column ``id`` has a negative value" +msgid "Column ``id`` has a negative value." msgstr "" msgid "All numbers on this column are ``DISTINCT``" @@ -8326,6 +8152,9 @@ msgstr "" msgid "Representing a pseudo `id` as is not incorporated in the set of original edges." msgstr "" +msgid "``contracted_vertices``" +msgstr "" + msgid "Array of contracted vertex identifiers." msgstr "" @@ -8347,6 +8176,147 @@ msgstr "" msgid "Only linear contraction" msgstr "" +msgid "The cycle" +msgstr "" + +msgid "Contracting a graph, can be done with more than one operation. The order of the operations affect the resulting contracted graph, after applying one operation, the set of vertices that can be contracted by another operation changes." +msgstr "" + +msgid "This implementation, cycles ``cycles`` times through the ``methods`` ." +msgstr "" + +msgid "Contracting sample data" +msgstr "" + +msgid "In this section, building and using a contracted graph will be shown by example." +msgstr "" + +msgid "The :doc:`sampledata` for an undirected graph is used" +msgstr "" + +msgid "a dead end operation first followed by a linear operation." +msgstr "" + +msgid "Construction of the graph in the database" +msgstr "" + +msgid "The original graph:" +msgstr "" + +msgid "The results do not represent the contracted graph. They represent the changes that need to be done to the graph after applying the contraction methods." +msgstr "" + +msgid "Observe that vertices, for example, :math:`6` do not appear in the results because it was not affected by the contraction algorithm." +msgstr "" + +msgid "After doing the dead end contraction operation:" +msgstr "" + +msgid "After doing the linear contraction operation to the graph above:" +msgstr "" + +msgid "The process to create the contraction graph on the database:" +msgstr "" + +msgid "Add additional columns" +msgstr "" + +msgid "Adding extra columns to the edges and vertices tables. In this documentation the following will be used:" +msgstr "" + +msgid "Column." +msgstr "" + +msgid "The vertices set belonging to the vertex/edge" +msgstr "" + +msgid "``is_contracted``" +msgstr "" + +msgid "On the vertex table" +msgstr "" + +msgid "when ``true`` the vertex is contracted, its not part of the contracted graph." +msgstr "" + +msgid "when ``false`` the vertex is not contracted, its part of the contracted graph." +msgstr "" + +msgid "``is_new``" +msgstr "" + +msgid "On the edge table" +msgstr "" + +msgid "when ``true`` the edge was generated by the contraction algorithm. its part of the contracted graph." +msgstr "" + +msgid "when ``false`` the edge is an original edge, might be or not part of the contracted graph." +msgstr "" + +msgid "Store contraction information" +msgstr "" + +msgid "Store the contraction results in a table." +msgstr "" + +msgid "Update the edges and vertices tables" +msgstr "" + +msgid "Use ``is_contracted`` column to indicate the vertices that are contracted." +msgstr "" + +msgid "Fill ``contracted_vertices`` with the information from the results that belong to the vertices." +msgstr "" + +msgid "Insert the new edges generated by pgr_contraction." +msgstr "" + +msgid "The contracted graph" +msgstr "" + +msgid "Vertices that belong to the contracted graph." +msgstr "" + +msgid "Edges that belong to the contracted graph." +msgstr "" + +msgid "Visually:" +msgstr "" + +msgid "Using the contracted graph" +msgstr "" + +msgid "Depending on the final application the graph is to be prepared. In this example the final application will be to calculate the cost from two vertices in the original graph by using the contracted graph with ``pgr_dijkstraCost``" +msgstr "" + +msgid "There are three cases when calculating the shortest path between a given source and target in a contracted graph:" +msgstr "" + +msgid "Case 1: Both source and target belong to the contracted graph." +msgstr "" + +msgid "Case 2: Source and/or target belong to an edge subgraph." +msgstr "" + +msgid "Case 3: Source and/or target belong to a vertex." +msgstr "" + +msgid "The final application should consider all of those cases." +msgstr "" + +msgid "Create a view (or table) of the contracted graph:" +msgstr "" + +msgid "Create the function that will use the contracted graph." +msgstr "" + +msgid "Case 2: Source and/or target belong to an edge that has contracted vertices." +msgstr "" + +msgid "Case 3: Source and/or target belong to a vertex that has been contracted." +msgstr "" + msgid "``pgr_createTopology``" msgstr "" @@ -8752,9 +8722,6 @@ msgstr "" msgid "``pgr_degree`` — For each vertex in an undirected graph, return the count of edges incident to the vertex." msgstr "" -msgid "Version 3.8.0" -msgstr "" - msgid "Calculates the degree of the vertices of an undirected graph" msgstr "" @@ -8839,9 +8806,6 @@ msgstr "" msgid "``in_edges``" msgstr "" -msgid "``BIGINT[]``" -msgstr "" - msgid "Array of identifiers of the edges that have the vertex ``id`` as *first end point*." msgstr "" @@ -12973,9 +12937,6 @@ msgstr "" msgid "pgr_betweennessCentrality" msgstr "" -msgid "Official functions changes" -msgstr "" - msgid "`#2605 `__ Standardize spanning tree functions output" msgstr "" From 4110936880a9a4d72f0cba8c596bd09a26c0c26e Mon Sep 17 00:00:00 2001 From: cvvergara Date: Fri, 21 Mar 2025 10:47:46 -0600 Subject: [PATCH 08/11] (contraction/pgtap) moving functions to function file --- .../edge_cases/compare_dijkstra_deadend.pg | 75 +- .../edge_cases/compare_dijkstra_linear.pg | 93 +-- .../edge_cases/edge_cases_deadend.pg | 273 +------ .../edge_cases/edge_cases_linear.pg | 259 +------ tools/testers/contraction_tapfuncs.sql | 671 ++++++++++++++++++ 5 files changed, 688 insertions(+), 683 deletions(-) diff --git a/pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg index e96cb05ac27..c38db3041b3 100644 --- a/pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg +++ b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_deadend.pg @@ -24,86 +24,15 @@ UPDATE edges SET cost = sign(cost) + 0.001 * id * id, reverse_cost = sign(revers ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; -CREATE OR REPLACE FUNCTION check_cg(BOOLEAN) -RETURNS SETOF TEXT AS -$BODY$ -BEGIN - IF NOT min_version('3.8.0') THEN - RETURN QUERY SELECT skip(1, 'contraction function/signature is new on 3.8.0'); - RETURN; - END IF; - - IF $1 THEN - RETURN QUERY - SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, - $$ VALUES ('v',7,ARRAY[1,3],-1,-1), ('v',4,ARRAY[2],-1,-1), ('v',8,ARRAY[9],-1,-1), - ('v',6,ARRAY[5],-1,-1), ('v',14,ARRAY[13],-1,-1) $$); - - RETURN QUERY SELECT is_empty($$SELECT id FROM edges WHERE is_new$$); - - PREPARE c_expected_graph AS - SELECT source, target, cost, reverse_cost - FROM (VALUES - (16,17,'1.225'::TEXT,'1.225'::TEXT), - (10,15,'-0.991','1.009'), - (12,17,'1.169','-0.831'), - (15,16,'1.256','1.256'), - (6, 10, '-0.996', '1.004'), - (6, 7, '1.016', '1.016'), - (10, 11, '1.025', '-0.975'), - (7, 11, '1.064', '1.064'), - (11, 16, '1.081', '1.081'), - (11, 12, '1.121', '-0.879'), - (8, 12, '1.144', '-0.856'), - (7, 8, '1.100', '1.100')) - AS t(source, target, cost, reverse_cost); - - RETURN QUERY - SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', - 'c_expected_graph', 'The contracted graph'); - ELSE - RETURN QUERY - SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, - $$ VALUES ('v',7,ARRAY[1,3],-1,-1), ('v',4,ARRAY[2],-1,-1), ('v',8,ARRAY[9],-1,-1), - ('v',6,ARRAY[5],-1,-1), ('v',14,ARRAY[13],-1,-1) $$); - - RETURN QUERY SELECT is_empty($$SELECT id FROM edges WHERE is_new$$); - - PREPARE c_expected_graph AS - SELECT source, target, cost, reverse_cost - FROM (VALUES - (6, 10, '-0.996', '1.004'), - (6, 7, '1.016', '1.016'), - (10, 11, '1.025', '-0.975'), - (7, 11, '1.064', '1.064'), - (11, 16, '1.081', '1.081'), - (11, 12, '1.121', '-0.879'), - (8, 12, '1.144', '-0.856'), - (7, 8, '1.100', '1.100'), - (16,17,'1.225'::TEXT,'1.225'::TEXT), - (10,15,'-0.991','1.009'), - (12,17,'1.169','-0.831'), - (15,16,'1.256','1.256')) - AS t(source, target, cost, reverse_cost); - - RETURN QUERY - SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', - 'c_expected_graph', 'The contracted graph'); - - END IF; - DEALLOCATE PREPARE c_expected_graph; -END -$BODY$ -LANGUAGE plpgsql; CALL create_contracted_graph(false,'pgr_contraction', ARRAY[1]); -SELECT check_cg(false); +SELECT check_contracted_graph_deadend(false); SELECT compare_dijkstra_contraction(false); CALL create_contracted_graph(true,'pgr_contraction', ARRAY[1]); -SELECT check_cg(true); +SELECT check_contracted_graph_deadend(true); SELECT compare_dijkstra_contraction(true); SELECT finish(); diff --git a/pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg index 87be224389a..42f800e7f1a 100644 --- a/pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg +++ b/pgtap/contraction/contraction/edge_cases/compare_dijkstra_linear.pg @@ -24,101 +24,12 @@ UPDATE edges SET cost = sign(cost) + 0.001 * id * id, reverse_cost = sign(revers ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false, ADD contracted_vertices integer[]; -CREATE OR REPLACE FUNCTION check_cg(BOOLEAN) -RETURNS SETOF TEXT AS -$BODY$ -BEGIN - - IF NOT min_version('3.8.0') THEN - RETURN QUERY SELECT skip(1, 'contraction function/signature is new on 3.8.0'); - RETURN; - END IF; - - IF $1 THEN - RETURN QUERY - SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, - $$ VALUES ('e',-1,ARRAY[3],7,1), ('e',-2,ARRAY[3],1,7)$$, 'The edges') ; - - RETURN QUERY - SELECT set_eq( - $$SELECT id FROM edges WHERE is_new$$, - $$SELECT unnest(ARRAY[19, 20])$$, 'The vertices' - ); - - PREPARE c_expected_graph AS - SELECT source, target, cost, reverse_cost - FROM (VALUES - (16,17,'1.225'::TEXT,'1.225'::TEXT), - (10,15,'-0.991','1.009'), - (12,17,'1.169','-0.831'), - (15,16,'1.256','1.256'), - (6, 10, '-0.996', '1.004'), - (6, 7, '1.016', '1.016'), - (10, 11, '1.025', '-0.975'), - (7, 11, '1.064', '1.064'), - (11, 16, '1.081', '1.081'), - (11, 12, '1.121', '-0.879'), - (8, 12, '1.144', '-0.856'), - (7, 8, '1.100', '1.100'), - (1,7,'2.085','-1.000'), - (7,1,'2.085','-1.000'), - (5, 6, '1.001', '1.001'), - (8, 9, '1.196', '1.196'), - (2, 4, '1.289', '1.289'), - (13, 14, '1.324', '1.324')) - AS t(source, target, cost, reverse_cost); - - RETURN QUERY - SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', - 'c_expected_graph', 'The contracted graph'); - ELSE - RETURN QUERY - SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, - $$ VALUES ('e',-3,ARRAY[17],16,12), ('e',-2,ARRAY[3],7,1), ('e', -1, ARRAY[15], 10, 16)$$) ; - - RETURN QUERY - SELECT set_eq( - $$SELECT id FROM edges WHERE is_new$$, - $$SELECT unnest(ARRAY[19, 20, 21])$$ - ); - - PREPARE c_expected_graph AS - SELECT source, target, cost, reverse_cost - FROM (VALUES - (6, 10, '-0.996', '1.004'), - (6, 7, '1.016', '1.016'), - (10, 11, '1.025', '-0.975'), - (7, 11, '1.064', '1.064'), - (11, 16, '1.081', '1.081'), - (11, 12, '1.121', '-0.879'), - (8, 12, '1.144', '-0.856'), - (7, 8, '1.100', '1.100'), - (10,16,'2.265','-1.000'), - (7,1,'2.085','-1.000'), - (16,12,'2.394','-1.000'), - (5, 6, '1.001', '1.001'), - (8, 9, '1.196', '1.196'), - (2, 4, '1.289', '1.289'), - (13, 14, '1.324', '1.324')) - AS t(source, target, cost, reverse_cost); - - RETURN QUERY - SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', - 'c_expected_graph', 'The contracted graph'); - - END IF; - DEALLOCATE PREPARE c_expected_graph; -END -$BODY$ -LANGUAGE plpgsql; - - CALL create_contracted_graph(false,'pgr_contraction', ARRAY[2]); -SELECT check_cg(false); +SELECT check_contracted_graph_linear(false); SELECT compare_dijkstra_contraction(false); CALL create_contracted_graph(true,'pgr_contraction', ARRAY[2]); -SELECT check_cg(true); +SELECT check_contracted_graph_linear(true); SELECT compare_dijkstra_contraction(true); SELECT finish(); diff --git a/pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg b/pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg index c26ac6ddc6f..b0dd533ff7f 100644 --- a/pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg +++ b/pgtap/contraction/contraction/edge_cases/edge_cases_deadend.pg @@ -21,268 +21,6 @@ BEGIN; UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost); SELECT CASE WHEN min_version('3.8.0') THEN plan(128) ELSE plan(1) END; -CREATE TABLE graphs ( - id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - source BIGINT, - target BIGINT, - cost BIGINT default 1, - reverse_cost BIGINT default 1, - dead_case INTEGER -); - -/* 2 -- {3 -- 4} ; 3 -- 4 */ -INSERT INTO graphs(source, target, dead_case) -VALUES -(2, 3, 0), -(2, 4, 0), -(3, 4, 0); - -INSERT INTO graphs(source, target, cost, reverse_cost, dead_case) -VALUES -/* 2->{3->4 [dir=both]} [dir=both]; 1->2 */ -(1, 2, 1, -1, 1), - -/* 2->{3->4 [dir=both]} [dir=both]; 2->1 */ -(2, 1, 1, -1, 2), - -/* 2->{3->4 [dir=both]} [dir=both]; 2->1 [dir=both] */ -(1, 2, 1, 1, 3), - -/* 2->{3->4 [dir=both]} [dir=both]; 2->1,2->1 */ -(2, 1, 1, -1, 4), -(2, 1, 1, -1, 4), - -/* 2->{3->4 [dir=both]} [dir=both]; {2,3}->1 */ -(2, 1, 1, -1, 5), -(3, 1, 1, -1, 5), - -/* 2->{3->4 [dir=both]} [dir=both]; 2->1;2->1;3->1 */ -(2, 1, 1, -1, 6), -(2, 1, 1, -1, 6), -(3, 1, 1, -1, 6); - -CREATE TABLE results ( - type text, - id INTEGER, - contracted_vertices BIGINT[], - result_case INTEGER -); - -INSERT INTO results(type, id, contracted_vertices, result_case) -VALUES -('v',6,ARRAY[5]::BIGINT[], 1), -('v',5,ARRAY[6], 2), -('v',15,ARRAY[10], 3), -('v',10,ARRAY[15], 4), -('v',12,ARRAY[8], 5), -('v',8,ARRAY[12], 6), -('v',15,ARRAY[6,10], 7), -('v',6,ARRAY[10,15], 8), -('v',10,ARRAY[6,15], 9), -('v',10,ARRAY[15], 10), -('v',10,ARRAY[6], 11), -('v',8,ARRAY[11,12], 12), -('v',8,ARRAY[12], 13), -('v',11,ARRAY[12], 13), -('v',11,ARRAY[8,12], 113), -('v',12,ARRAY[8,11], 14), -('v',12,ARRAY[11], 15), - -('v',10,ARRAY[6], 16), -('v',12,ARRAY[8], 16), -('v',6,ARRAY[10], 17), -('v',12,ARRAY[8], 17), -('v',10,ARRAY[6], 18), -('v',8,ARRAY[12], 18), -('v',6,ARRAY[10], 19), -('v',8,ARRAY[12], 19), -('v',6,ARRAY[10], 20), - -('v',17,ARRAY[10,11,12], 21), -('v',10,ARRAY[11,12,17], 22), -('v',11,ARRAY[10,12,17], 23), -('v',12,ARRAY[10,11,17], 24), - -('v',8,ARRAY[9], 25), -('v',7,ARRAY[1,3], 25), -('v',6,ARRAY[5], 25), - -('v',8,ARRAY[9], 26), -('v',3,ARRAY[1], 26), -('v',6,ARRAY[5], 26) - -; - -prepare get_solution(integer, integer, text) AS -WITH a AS (SELECT CASE WHEN $3::BOOLEAN THEN $1 ELSE $2 END r) -SELECT type,id,contracted_vertices FROM results, a WHERE result_case = r; - -CREATE OR REPLACE FUNCTION edge_cases_sampledata(directed text) -RETURNS SETOF TEXT AS -$BODY$ -BEGIN - - -- SINGLE edge - - RETURN QUERY - SELECT set_eq($$"graph1" ('1','{}',$$||directed||$$)$$, $$"get_solution" (1,1,$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('1','{6}',$$||directed||$$)$$, $$"get_solution" (1,1,$$||directed||$$) $$, '5 <=> 6: Directed=' || directed ||', forbid 5'); - RETURN QUERY - SELECT set_eq($$"graph1" ('1','{5}',$$||directed||$$)$$, $$"get_solution" (2,2,$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', forbid 6'); - RETURN QUERY - SELECT is_empty($$"graph1" ('1','{5,6}',$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', forbid 5,6'); - - RETURN QUERY - SELECT set_eq($$"graph1" ('3','{}',$$||directed||$$)$$, $$"get_solution" (3,3,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('3','{10}',$$||directed||$$)$$, $$"get_solution" (4,4,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', forbid 10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('3','{15}',$$||directed||$$)$$, $$"get_solution" (3,3,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', forbid 15'); - RETURN QUERY - SELECT is_empty($$"graph1" ('3','{10,15}',$$||directed||$$) $$, '5 <=> 6: Directed=' || directed ||', forbid 10,15'); - - RETURN QUERY - SELECT set_eq($$"graph1" ('12','{}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('12','{8}',$$||directed||$$)$$, $$"get_solution" (6,6,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', forbid 8'); - RETURN QUERY - SELECT set_eq($$"graph1" ('12','{12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', forbid 12'); - - -- TWO edges - - RETURN QUERY - SELECT set_eq($$"graph1" ('2,3','{}',$$||directed||$$)$$, $$"get_solution" (7,7,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,3','{6}',$$||directed||$$)$$, $$"get_solution" (8,8,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,3','{10}',$$||directed||$$)$$, $$"get_solution" (9,9,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,3','{15}',$$||directed||$$)$$, $$"get_solution" (7,7,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 15'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,3','{6,10}',$$||directed||$$)$$, $$"get_solution" (10,10,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,10'); - RETURN QUERY - SELECT is_empty($$"graph1" ('2,3','{6,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,15'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,3','{10,15}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 10,15'); - RETURN QUERY - SELECT is_empty($$"graph1" ('2,3','{6,10,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,10,15'); - - - RETURN QUERY - SELECT set_eq($$"graph1" ('11,12','{}',$$||directed||$$)$$, $$"get_solution" (12,12,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('11,12','{8}',$$||directed||$$)$$, $$"get_solution" (12,12,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8'); - RETURN QUERY - SELECT set_eq($$"graph1" ('11,12','{11}',$$||directed||$$)$$, $$"get_solution" (13,113,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 11'); - RETURN QUERY - SELECT set_eq($$"graph1" ('11,12','{12}',$$||directed||$$)$$, $$"get_solution" (14,14,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('11,12','{8,11}',$$||directed||$$)$$, $$"get_solution" (13,213,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,11'); - RETURN QUERY - SELECT set_eq($$"graph1" ('11,12','{8,12}',$$||directed||$$)$$, $$"get_solution" (15,15,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('11,12','{11,12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 11,12'); - RETURN QUERY - SELECT is_empty($$"graph1" ('11,12','{8,11,12}',$$||directed||$$)$$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,11,12'); - - - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{6}',$$||directed||$$)$$, $$"get_solution" (17,17,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{8}',$$||directed||$$)$$, $$"get_solution" (18,18,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{10}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{12}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{6,8}',$$||directed||$$)$$, $$"get_solution" (19,19,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{6,10}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{6,12}',$$||directed||$$)$$, $$"get_solution" (17,17,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{8,10}',$$||directed||$$)$$, $$"get_solution" (18,18,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{8,12}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{6,8,10}',$$||directed||$$)$$, $$"get_solution" (6,6,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{6,8,12}',$$||directed||$$)$$, $$"get_solution" (20,20,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{6,10,12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,10,12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,12','{8,10,12}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,10,12'); - RETURN QUERY - SELECT is_empty($$"graph1" ('2,12','{6,8,10,12}',$$||directed||$$)$$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,10,12'); - - - -- THREE edges - RETURN QUERY - SELECT set_eq($$"graph1" ('5,11,13','{}',$$||directed||$$)$$, $$"get_solution" (21,21,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('5,11,13','{10}',$$||directed||$$)$$, $$"get_solution" (22,22,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('5,11,13','{11}',$$||directed||$$)$$, $$"get_solution" (23,23,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 11'); - RETURN QUERY - SELECT set_eq($$"graph1" ('5,11,13','{12}',$$||directed||$$)$$, $$"get_solution" (24,24,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 12'); - RETURN QUERY - SELECT set_eq($$"graph1" ('5,11,13','{17}',$$||directed||$$)$$, $$"get_solution" (21,21,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 17'); - RETURN QUERY - SELECT is_empty($$"graph1" ('5,11,13','{10,17}',$$||directed||$$)$$, '10 -> 11 -> 12 -> 17: Directed Directed=' || directed ||', forbid 10,17'); - - -- The graph1 - RETURN QUERY - SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{}',$$||directed||$$)$$, $$"get_solution" (25,25,$$||directed||$$) $$, 'the graph1: Directed=' || directed ||', no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{3}',$$||directed||$$)$$, $$"get_solution" (26,26,$$||directed||$$) $$, 'the graph1: Directed=' || directed ||', forbid 3'); - -END; -$BODY$ -LANGUAGE plpgsql; - - -CREATE OR REPLACE FUNCTION edge_cases(directed text) -RETURNS SETOF TEXT AS -$BODY$ -BEGIN - -RETURN QUERY SELECT is_empty(format($$"graph" ('0',%1$s)$$,directed),'empty graph: 0,'||directed); - -RETURN QUERY SELECT isnt_empty(format($$"graph" ('1',%1$s)$$,directed), 'not empty graph: 1,'||directed); -RETURN QUERY SELECT set_eq(format($$"graph" ('1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 1,'||directed) ; - -RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,1',%1$s)$$,directed), 'not empty graph: 0,1,'||directed); -RETURN QUERY SELECT set_eq(format($$"graph" ('0,1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,1,'||directed) ; - -RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,2',%1$s)$$,directed), 'not empty graph: 0,2,'||directed); -RETURN QUERY SELECT set_eq(format($$"graph" ('0,2',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,2,'||directed) ; - -RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,3',%1$s)$$,directed), 'not empty graph: 0,3,'||directed); -RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,3,'||directed) ; - -RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,4',%1$s)$$,directed), 'not empty graph: 0,4,'||directed); -RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed) ; - -RETURN QUERY -SELECT CASE WHEN directed::BOOLEAN THEN - collect_tap( - isnt_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), - set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed), - isnt_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed), - set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,6,'||directed)) -ELSE - collect_tap( - is_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), - is_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed)) -END; - -END; -$BODY$ -LANGUAGE plpgsql; - CREATE OR REPLACE FUNCTION edge_cases() RETURNS SETOF TEXT AS $BODY$ @@ -294,6 +32,9 @@ BEGIN RETURN; END IF; + CALL create_deadend_edge_cases(); + + PREPARE graph1(text,text,text) AS SELECT type, id, contracted_vertices FROM pgr_contraction( format($$SELECT id, source, target, cost, reverse_cost FROM edges WHERE id IN (%s) ORDER BY id$$, $1), @@ -304,10 +45,10 @@ BEGIN format($$SELECT * FROM graphs WHERE dead_case IN (%1$s) ORDER BY id$$, $1), $2::boolean,ARRAY[1]); - RETURN QUERY SELECT edge_cases('true'); - RETURN QUERY SELECT edge_cases('false'); - RETURN QUERY SELECT edge_cases_sampledata('true'); - RETURN QUERY SELECT edge_cases_sampledata('false'); + RETURN QUERY SELECT deadend_edge_cases('true'); + RETURN QUERY SELECT deadend_edge_cases('false'); + RETURN QUERY SELECT deadend_edge_cases_sampledata('true'); + RETURN QUERY SELECT deadend_edge_cases_sampledata('false'); END; $BODY$ diff --git a/pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg b/pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg index 800afda4c4e..7eeceaae63a 100644 --- a/pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg +++ b/pgtap/contraction/contraction/edge_cases/edge_cases_linear.pg @@ -21,255 +21,6 @@ BEGIN; UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost); SELECT CASE WHEN min_version('3.8.0') THEN plan(112) ELSE plan(1) END; -CREATE TABLE graphs ( - id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - source BIGINT, - target BIGINT, - cost BIGINT default 1, - reverse_cost BIGINT default 1, - dead_case INTEGER -); - -/* 11 -> {12 -> {13, 14} [dir=both]} [dir=both]; 13 ->14 [dir=both] */ -INSERT INTO graphs(source, target, dead_case) -VALUES -(11, 12, 0), -(11, 13, 0), -(11, 14, 0), -(12, 13, 0), -(12, 14, 0), -(13, 14, 0); - -INSERT INTO graphs(source, target, cost, reverse_cost, dead_case) -VALUES -/* 1->11 */ -(1, 11, 1, -1, 1), - -/* 11->1 */ -(11, 1, 1, -1, 2), - -/* 1 -> 2 -> 11 */ -(1, 2, 1, -1, 3), -(2, 11, 1, -1, 3), - -/* 11 -> 2 -> 1 */ -(11, 2, 1, -1, 4), -(2, 1, 1, -1, 4), - -/* 11 -> 2 [dir=both]; 2 -> 1 [dir=both] */ -(11, 2, 1, 1, 5), -(2, 1, 1, 1, 5), - -/* 11 -> {1,3} [dir=both]; 1->3 [dir=both]*/ -(11, 1, 1, 1, 6), -(1, 3, 1, 1, 6), -(3, 11, 1, 1, 6), - -/* 11 -> {1,3} [dir=both]; 2 -> {1,3} [dir=both]; 2->3 [dir=both]*/ -(11, 1, 1, 1, 7), -(1, 2, 1, 1, 7), -(2, 3, 1, 1, 7), -(3, 11, 1, -1, 7); - -CREATE TABLE results ( - type text, - contracted_vertices BIGINT[], - source BIGINT, - target BIGINT, - cost FLOAT, - result_case INTEGER -); - -INSERT INTO results(type, contracted_vertices, source, target, cost, result_case) -VALUES -('e',ARRAY[3]::BIGINT[],1,7,2, 1), -('e',ARRAY[3],7,1,2, 1), -('e',ARRAY[3],1,7,2, 2), -('e',ARRAY[3],7,1,2, 2), -('e',ARRAY[3,7],1,11,3, 3), -('e',ARRAY[3,7],11,1,3, 3), -('e',ARRAY[7],3,11,2, 4), -('e',ARRAY[7],11,3,2, 4), -('e',ARRAY[16],15,11,2, 5), -('e',ARRAY[16],11,15,2, 5), -('e',ARRAY[10],15,11,2, 5), -('e',ARRAY[16],15,11,2, 6), -('e',ARRAY[16],11,15,2, 6), -('e',ARRAY[10],15,11,2, 7), -('e',ARRAY[7],6,11,2, 8), -('e',ARRAY[7],11,6,2, 8), -('e',ARRAY[3],1,7,2, 9), -('e',ARRAY[3],7,1,2, 9), -('e',ARRAY[3],1,7,2, 11), -('e',ARRAY[3],7,1,2, 12), -('e',ARRAY[3,7],1,11,3, 13), -('e',ARRAY[7],3,11,2, 14), -('e',ARRAY[10,15],11,16,3, 15), -('e',ARRAY[10,11],15,16,3, 25), -('e',ARRAY[15,16],10,11,3, 16), -('e',ARRAY[10,15],11,16,3, 17), -('e',ARRAY[6,10],7,11,3, 18), -('e',ARRAY[10,11],6,7,3, 28), -('e',ARRAY[6,7],10,11,3, 38), -('e',ARRAY[3],7,1,2, 19), -('e',ARRAY[15],10,16,2, 19), -('e',ARRAY[17],16,12,2, 19), -('e',ARRAY[15],10,16,2, 20), -('e',ARRAY[17],16,12,2, 20) -; - -prepare get_solution(integer, integer, text) AS -WITH a AS (SELECT CASE WHEN $3::BOOLEAN THEN $1 ELSE $2 END r) -SELECT type,contracted_vertices,source,target,cost FROM results, a WHERE result_case = r; - -CREATE OR REPLACE FUNCTION edge_cases_sampledata(directed text) -RETURNS SETOF TEXT AS -$BODY$ -BEGIN - - -- SINGLE edge - - RETURN QUERY SELECT is_empty($$"graph1" ('6','{}',$$||directed||$$)$$, '1<=>3: Directed=' || directed ||' no forbidden vertices'); - - -- TWO edges - - RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7','{}',$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7','{}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$ , '1<=>3<=>7: Directed=' || directed ||' no forbidden'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7','{1}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 1'); - RETURN QUERY SELECT is_empty($$"graph1" ('6,7','{3}',$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 3'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7','{7}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 7'); - - -- T shape - - RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7,4,10','{}',$$||directed||$$)$$, '1<=>3<=>7<->6,8: Directed=' || directed ||' no forbidden vertices'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,4,10','{}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||' no forbidden'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,4,10','{1}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 1'); - RETURN QUERY - SELECT is_empty($$"graph1" ('6,7,4,10','{3}',$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 3'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,4,10','{7}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 7'); - - - -- THREE edges - - RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7,8','{}',$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||' no forbidden'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,8','{}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||' no forbidden'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,8','{1}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 1'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,8','{11}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 11'); - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,8','{3}',$$||directed||$$)$$, $$"get_solution" (4,14,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 3'); - - RETURN QUERY - SELECT set_eq($$"graph1" ('6,7,8','{7}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 7'); - - -- FOUR edges - -- circling square - RETURN QUERY SELECT isnt_empty($$"graph1" ('3,5,9,16','{}',$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||' no forbidden'); - RETURN QUERY - SELECT set_eq($$"graph1" ('3,5,9,16','{}',$$||directed||$$)$$, $$"get_solution" (5,15,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||' no forbidden'); - RETURN QUERY - SELECT set_eq($$"graph1" ('3,5,9,16','{11}',$$||directed||$$)$$, $$"get_solution" (5,15,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 11'); - RETURN QUERY - SELECT set_eq($$"graph1" ('3,5,9,16','{15}',$$||directed||$$)$$, $$"get_solution" (5,25,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 15'); - RETURN QUERY - SELECT set_eq($$"graph1" ('3,5,9,16','{10}',$$||directed||$$)$$, $$"get_solution" (6,16,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 10'); - RETURN QUERY - SELECT set_eq($$"graph1" ('3,5,9,16','{16}',$$||directed||$$)$$, $$"get_solution" (7,17,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 16'); - - -- non circling square - RETURN QUERY SELECT isnt_empty($$"graph1" ('2,4,5,8','{}',$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' no forbidden'); - - RETURN QUERY - SELECT set_eq($$"graph1" ('2,4,5,8','{}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' no forbidden'); - - if directed THEN - RETURN QUERY - SELECT is_empty($$"graph1" ('2,4,5,8','{7}',$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 7'); - ELSE - RETURN QUERY - SELECT set_eq($$"graph1" ('2,4,5,8','{7}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 7'); - END IF; - RETURN QUERY - SELECT set_eq($$"graph1" ('2,4,5,8','{11}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 11'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,4,5,8','{6}',$$||directed||$$)$$, $$"get_solution" (8,28,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 6'); - RETURN QUERY - SELECT set_eq($$"graph1" ('2,4,5,8','{10}',$$||directed||$$)$$, $$"get_solution" (8,38,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 10'); - - -- The graph1 - RETURN QUERY - SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{}',$$||directed||$$)$$, $$"get_solution" (9,19,$$||directed||$$)$$, 'the graph: Directed=' || directed ||' no forbidden'); - IF directed THEN - RETURN QUERY - SELECT is_empty($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{3}',$$||directed||$$)$$, 'the graph1: Directed=' || directed ||', forbid 3'); - ELSE - RETURN QUERY - SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{3}',$$||directed||$$)$$, $$"get_solution" (1,20,$$||directed||$$)$$, 'the graph1: Directed=' || directed ||', forbid 3'); - END IF; - - -END; -$BODY$ -LANGUAGE plpgsql; - - -CREATE OR REPLACE FUNCTION edge_cases(directed text) -RETURNS SETOF TEXT AS -$BODY$ -BEGIN - - RETURN QUERY SELECT is_empty(format($$"graph" ('0',%1$s)$$,directed),'empty graph: 0,'||directed); - RETURN QUERY SELECT is_empty(format($$"graph" ('1',%1$s)$$,directed),'empty graph: 1,'||directed); - RETURN QUERY SELECT is_empty(format($$"graph" ('2',%1$s)$$,directed),'empty graph: 2,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('3',%1$s)$$,directed),'not empty graph: 3,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('4',%1$s)$$,directed),'not empty graph: 4,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('5',%1$s)$$,directed),'not empty graph: 5,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('6',%1$s)$$,directed),'not empty graph: 6,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('7',%1$s)$$,directed),'not empty graph: 7,'||directed); - - RETURN QUERY SELECT is_empty(format($$"graph" ('0,1',%1$s)$$,directed), 'empty graph: 0,1,'||directed); - RETURN QUERY SELECT is_empty(format($$"graph" ('0,2',%1$s)$$,directed), 'empty graph: 0,2,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,3',%1$s)$$,directed), 'not empty graph: 0,3,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,4',%1$s)$$,directed), 'not empty graph: 0,4,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'not empty graph: 0,5,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'not empty graph: 0,6,'||directed); - RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,7',%1$s)$$,directed), 'not empty graph: 0,7,'||directed); - - RETURN QUERY SELECT set_eq(format($$"graph" ('3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 3,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 4,'||directed) ; - - if directed THEN - RETURN QUERY SELECT set_eq(format($$"graph" ('5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2),('e',-2,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 5,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[11]::BIGINT[],1,3,2), ('e',-2,ARRAY[11]::BIGINT[],3,1,2) $$, 'expected graph: 6,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3), ('e',-2,ARRAY[1,2]::BIGINT[],3,11,3) $$, 'expected graph: 7,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 0,3,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,4,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2),('e',-2,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 0,5,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1]::BIGINT[],11,3,2),('e',-2,ARRAY[1]::BIGINT[],3,11,2) $$, 'expected graph: 0,6,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3),('e',-2,ARRAY[1,2]::BIGINT[],3,11,3) $$, 'expected graph: 0,7,'||directed) ; - ELSE - RETURN QUERY SELECT set_eq(format($$"graph" ('5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 5,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[11]::BIGINT[],1,3,2) $$, 'expected graph: 6,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,11]::BIGINT[],2,3,3) $$, 'expected graph: 7,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,3,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,4,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,5,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1]::BIGINT[],11,3,2) $$, 'expected graph: 0,6,'||directed) ; - RETURN QUERY SELECT set_eq(format($$"graph" ('0,7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3) $$, 'expected graph: 0,7,'||directed) ; - END IF; - -END; -$BODY$ -LANGUAGE plpgsql; - CREATE OR REPLACE FUNCTION edge_cases() RETURNS SETOF TEXT AS $BODY$ @@ -281,6 +32,8 @@ BEGIN RETURN; END IF; + CALL create_linear_edge_cases(); + PREPARE graph1(text,text,text) AS SELECT type, contracted_vertices,source,target,cost FROM pgr_contraction( format($$SELECT id, source, target, cost, reverse_cost FROM edges WHERE id IN (%s) ORDER BY id$$, $1), @@ -289,10 +42,10 @@ BEGIN prepare graph(text, text) AS SELECT * FROM pgr_contraction(format($$SELECT * FROM graphs WHERE dead_case IN (%1$s)$$, $1), $2::boolean,ARRAY[2]); - RETURN QUERY SELECT edge_cases('true'); - RETURN QUERY SELECT edge_cases('false'); - RETURN QUERY SELECT edge_cases_sampledata('true'); - RETURN QUERY SELECT edge_cases_sampledata('false'); + RETURN QUERY SELECT linear_edge_cases('true'); + RETURN QUERY SELECT linear_edge_cases('false'); + RETURN QUERY SELECT linear_edge_cases_sampledata('true'); + RETURN QUERY SELECT linear_edge_cases_sampledata('false'); END; $BODY$ diff --git a/tools/testers/contraction_tapfuncs.sql b/tools/testers/contraction_tapfuncs.sql index d565ee7f84f..585bb44d02b 100644 --- a/tools/testers/contraction_tapfuncs.sql +++ b/tools/testers/contraction_tapfuncs.sql @@ -152,6 +152,677 @@ END $BODY$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION check_contracted_graph_deadend(BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY SELECT skip(1, 'contraction function/signature is new on 3.8.0'); + RETURN; + END IF; + + IF $1 THEN + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('v',7,ARRAY[1,3],-1,-1), ('v',4,ARRAY[2],-1,-1), ('v',8,ARRAY[9],-1,-1), + ('v',6,ARRAY[5],-1,-1), ('v',14,ARRAY[13],-1,-1) $$); + + RETURN QUERY SELECT is_empty($$SELECT id FROM edges WHERE is_new$$); + + ELSE + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('v',7,ARRAY[1,3],-1,-1), ('v',4,ARRAY[2],-1,-1), ('v',8,ARRAY[9],-1,-1), + ('v',6,ARRAY[5],-1,-1), ('v',14,ARRAY[13],-1,-1) $$); + + RETURN QUERY SELECT is_empty($$SELECT id FROM edges WHERE is_new$$); + + END IF; + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (6, 10, '-0.996', '1.004'), + (6, 7, '1.016', '1.016'), + (7, 11, '1.064', '1.064'), + (7, 8, '1.100', '1.100'), + (8, 12, '1.144', '-0.856'), + (10, 11, '1.025', '-0.975'), + (10, 15, '-0.991', '1.009'), + (11, 16, '1.081', '1.081'), + (11, 12, '1.121', '-0.879'), + (12, 17, '1.169', '-0.831'), + (15, 16, '1.256', '1.256'), + (15, 16, '1.256', '1.256'), + (16, 17, '1.225', '1.225')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + + DEALLOCATE PREPARE c_expected_graph; + +END +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE PROCEDURE create_linear_edge_cases() AS +$BODY$ + +BEGIN + + CREATE TABLE graphs ( + id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + source BIGINT, + target BIGINT, + cost BIGINT default 1, + reverse_cost BIGINT default 1, + dead_case INTEGER +); + +/* 11 -> {12 -> {13, 14} [dir=both]} [dir=both]; 13 ->14 [dir=both] */ +INSERT INTO graphs(source, target, dead_case) +VALUES +(11, 12, 0), +(11, 13, 0), +(11, 14, 0), +(12, 13, 0), +(12, 14, 0), +(13, 14, 0); + +INSERT INTO graphs(source, target, cost, reverse_cost, dead_case) +VALUES +/* 1->11 */ +(1, 11, 1, -1, 1), + +/* 11->1 */ +(11, 1, 1, -1, 2), + +/* 1 -> 2 -> 11 */ +(1, 2, 1, -1, 3), +(2, 11, 1, -1, 3), + +/* 11 -> 2 -> 1 */ +(11, 2, 1, -1, 4), +(2, 1, 1, -1, 4), + +/* 11 -> 2 [dir=both]; 2 -> 1 [dir=both] */ +(11, 2, 1, 1, 5), +(2, 1, 1, 1, 5), + +/* 11 -> {1,3} [dir=both]; 1->3 [dir=both]*/ +(11, 1, 1, 1, 6), +(1, 3, 1, 1, 6), +(3, 11, 1, 1, 6), + +/* 11 -> {1,3} [dir=both]; 2 -> {1,3} [dir=both]; 2->3 [dir=both]*/ +(11, 1, 1, 1, 7), +(1, 2, 1, 1, 7), +(2, 3, 1, 1, 7), +(3, 11, 1, -1, 7); + +CREATE TABLE results ( + type text, + contracted_vertices BIGINT[], + source BIGINT, + target BIGINT, + cost FLOAT, + result_case INTEGER +); + +INSERT INTO results(type, contracted_vertices, source, target, cost, result_case) +VALUES +('e',ARRAY[3]::BIGINT[],1,7,2, 1), +('e',ARRAY[3],7,1,2, 1), +('e',ARRAY[3],1,7,2, 2), +('e',ARRAY[3],7,1,2, 2), +('e',ARRAY[3,7],1,11,3, 3), +('e',ARRAY[3,7],11,1,3, 3), +('e',ARRAY[7],3,11,2, 4), +('e',ARRAY[7],11,3,2, 4), +('e',ARRAY[16],15,11,2, 5), +('e',ARRAY[16],11,15,2, 5), +('e',ARRAY[10],15,11,2, 5), +('e',ARRAY[16],15,11,2, 6), +('e',ARRAY[16],11,15,2, 6), +('e',ARRAY[10],15,11,2, 7), +('e',ARRAY[7],6,11,2, 8), +('e',ARRAY[7],11,6,2, 8), +('e',ARRAY[3],1,7,2, 9), +('e',ARRAY[3],7,1,2, 9), +('e',ARRAY[3],1,7,2, 11), +('e',ARRAY[3],7,1,2, 12), +('e',ARRAY[3,7],1,11,3, 13), +('e',ARRAY[7],3,11,2, 14), +('e',ARRAY[10,15],11,16,3, 15), +('e',ARRAY[10,11],15,16,3, 25), +('e',ARRAY[15,16],10,11,3, 16), +('e',ARRAY[10,15],11,16,3, 17), +('e',ARRAY[6,10],7,11,3, 18), +('e',ARRAY[10,11],6,7,3, 28), +('e',ARRAY[6,7],10,11,3, 38), +('e',ARRAY[3],7,1,2, 19), +('e',ARRAY[15],10,16,2, 19), +('e',ARRAY[17],16,12,2, 19), +('e',ARRAY[15],10,16,2, 20), +('e',ARRAY[17],16,12,2, 20) +; + +prepare get_solution(integer, integer, text) AS +WITH a AS (SELECT CASE WHEN $3::BOOLEAN THEN $1 ELSE $2 END r) +SELECT type,contracted_vertices,source,target,cost FROM results, a WHERE result_case = r; + +END +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE PROCEDURE create_deadend_edge_cases() AS +$BODY$ + +BEGIN + + CREATE TABLE graphs ( + id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + source BIGINT, + target BIGINT, + cost BIGINT default 1, + reverse_cost BIGINT default 1, + dead_case INTEGER + ); + + /* 2 -- {3 -- 4} ; 3 -- 4 */ + INSERT INTO graphs(source, target, dead_case) + VALUES + (2, 3, 0), + (2, 4, 0), + (3, 4, 0); + + INSERT INTO graphs(source, target, cost, reverse_cost, dead_case) + VALUES + /* 2->{3->4 [dir=both]} [dir=both]; 1->2 */ + (1, 2, 1, -1, 1), + + /* 2->{3->4 [dir=both]} [dir=both]; 2->1 */ + (2, 1, 1, -1, 2), + + /* 2->{3->4 [dir=both]} [dir=both]; 2->1 [dir=both] */ + (1, 2, 1, 1, 3), + + /* 2->{3->4 [dir=both]} [dir=both]; 2->1,2->1 */ + (2, 1, 1, -1, 4), + (2, 1, 1, -1, 4), + + /* 2->{3->4 [dir=both]} [dir=both]; {2,3}->1 */ + (2, 1, 1, -1, 5), + (3, 1, 1, -1, 5), + + /* 2->{3->4 [dir=both]} [dir=both]; 2->1;2->1;3->1 */ + (2, 1, 1, -1, 6), + (2, 1, 1, -1, 6), + (3, 1, 1, -1, 6); + + CREATE TABLE results ( + type text, + id INTEGER, + contracted_vertices BIGINT[], + result_case INTEGER + ); + + INSERT INTO results(type, id, contracted_vertices, result_case) + VALUES + ('v',6,ARRAY[5]::BIGINT[], 1), + ('v',5,ARRAY[6], 2), + ('v',15,ARRAY[10], 3), + ('v',10,ARRAY[15], 4), + ('v',12,ARRAY[8], 5), + ('v',8,ARRAY[12], 6), + ('v',15,ARRAY[6,10], 7), + ('v',6,ARRAY[10,15], 8), + ('v',10,ARRAY[6,15], 9), + ('v',10,ARRAY[15], 10), + ('v',10,ARRAY[6], 11), + ('v',8,ARRAY[11,12], 12), + ('v',8,ARRAY[12], 13), + ('v',11,ARRAY[12], 13), + ('v',11,ARRAY[8,12], 113), + ('v',12,ARRAY[8,11], 14), + ('v',12,ARRAY[11], 15), + + ('v',10,ARRAY[6], 16), + ('v',12,ARRAY[8], 16), + ('v',6,ARRAY[10], 17), + ('v',12,ARRAY[8], 17), + ('v',10,ARRAY[6], 18), + ('v',8,ARRAY[12], 18), + ('v',6,ARRAY[10], 19), + ('v',8,ARRAY[12], 19), + ('v',6,ARRAY[10], 20), + + ('v',17,ARRAY[10,11,12], 21), + ('v',10,ARRAY[11,12,17], 22), + ('v',11,ARRAY[10,12,17], 23), + ('v',12,ARRAY[10,11,17], 24), + + ('v',8,ARRAY[9], 25), + ('v',7,ARRAY[1,3], 25), + ('v',6,ARRAY[5], 25), + + ('v',8,ARRAY[9], 26), + ('v',3,ARRAY[1], 26), + ('v',6,ARRAY[5], 26) + ; + + PREPARE get_solution(integer, integer, text) AS + WITH a AS (SELECT CASE WHEN $3::BOOLEAN THEN $1 ELSE $2 END r) + SELECT type,id,contracted_vertices FROM results, a WHERE result_case = r; + +END +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION deadend_edge_cases(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + +RETURN QUERY SELECT is_empty(format($$"graph" ('0',%1$s)$$,directed),'empty graph: 0,'||directed); + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('1',%1$s)$$,directed), 'not empty graph: 1,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 1,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,1',%1$s)$$,directed), 'not empty graph: 0,1,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,1',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,1,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,2',%1$s)$$,directed), 'not empty graph: 0,2,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,2',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,2,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,3',%1$s)$$,directed), 'not empty graph: 0,3,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,3,'||directed) ; + +RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,4',%1$s)$$,directed), 'not empty graph: 0,4,'||directed); +RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed) ; + +RETURN QUERY +SELECT CASE WHEN directed::BOOLEAN THEN + collect_tap( + isnt_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), + set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,4,'||directed), + isnt_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed), + set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('v',2,ARRAY[1]::BIGINT[],-1,-1,-1), ('v',3,ARRAY[1]::BIGINT[],-1,-1,-1) $$, 'expected graph: 0,6,'||directed)) +ELSE + collect_tap( + is_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'empty graph: 0,5,'||directed), + is_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'empty graph: 0,6,'||directed)) +END; + +END; +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION deadend_edge_cases_sampledata(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + -- SINGLE edge + + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{}',$$||directed||$$)$$, $$"get_solution" (1,1,$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{6}',$$||directed||$$)$$, $$"get_solution" (1,1,$$||directed||$$) $$, '5 <=> 6: Directed=' || directed ||', forbid 5'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1','{5}',$$||directed||$$)$$, $$"get_solution" (2,2,$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', forbid 6'); + RETURN QUERY + SELECT is_empty($$"graph1" ('1','{5,6}',$$||directed||$$)$$, '5 <=> 6: Directed=' || directed ||', forbid 5,6'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{}',$$||directed||$$)$$, $$"get_solution" (3,3,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{10}',$$||directed||$$)$$, $$"get_solution" (4,4,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3','{15}',$$||directed||$$)$$, $$"get_solution" (3,3,$$||directed||$$) $$, '10 -> 15: Directed=' || directed ||', forbid 15'); + RETURN QUERY + SELECT is_empty($$"graph1" ('3','{10,15}',$$||directed||$$) $$, '5 <=> 6: Directed=' || directed ||', forbid 10,15'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{8}',$$||directed||$$)$$, $$"get_solution" (6,6,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('12','{12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '8 -> 12: Directed=' || directed ||', forbid 12'); + + -- TWO edges + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{}',$$||directed||$$)$$, $$"get_solution" (7,7,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{6}',$$||directed||$$)$$, $$"get_solution" (8,8,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{10}',$$||directed||$$)$$, $$"get_solution" (9,9,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{15}',$$||directed||$$)$$, $$"get_solution" (7,7,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{6,10}',$$||directed||$$)$$, $$"get_solution" (10,10,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,10'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,3','{6,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,3','{10,15}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 10,15'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,3','{6,10,15}',$$||directed||$$)$$, '15 -> 10 -> 6: Directed=' || directed ||', forbid 6,10,15'); + + + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{}',$$||directed||$$)$$, $$"get_solution" (12,12,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8}',$$||directed||$$)$$, $$"get_solution" (12,12,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{11}',$$||directed||$$)$$, $$"get_solution" (13,113,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{12}',$$||directed||$$)$$, $$"get_solution" (14,14,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8,11}',$$||directed||$$)$$, $$"get_solution" (13,213,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{8,12}',$$||directed||$$)$$, $$"get_solution" (15,15,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('11,12','{11,12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 11,12'); + RETURN QUERY + SELECT is_empty($$"graph1" ('11,12','{8,11,12}',$$||directed||$$)$$, '11 -> 12 <- 8: Directed=' || directed ||', forbid 8,11,12'); + + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6}',$$||directed||$$)$$, $$"get_solution" (17,17,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8}',$$||directed||$$)$$, $$"get_solution" (18,18,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{10}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{12}',$$||directed||$$)$$, $$"get_solution" (16,16,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8}',$$||directed||$$)$$, $$"get_solution" (19,19,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,10}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,12}',$$||directed||$$)$$, $$"get_solution" (17,17,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,10}',$$||directed||$$)$$, $$"get_solution" (18,18,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,12}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8,10}',$$||directed||$$)$$, $$"get_solution" (6,6,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,8,12}',$$||directed||$$)$$, $$"get_solution" (20,20,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{6,10,12}',$$||directed||$$)$$, $$"get_solution" (5,5,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,10,12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,12','{8,10,12}',$$||directed||$$)$$, $$"get_solution" (11,11,$$||directed||$$) $$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 8,10,12'); + RETURN QUERY + SELECT is_empty($$"graph1" ('2,12','{6,8,10,12}',$$||directed||$$)$$, '10 -> 6, 8 -> 12: Directed=' || directed ||', forbid 6,8,10,12'); + + + -- THREE edges + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{}',$$||directed||$$)$$, $$"get_solution" (21,21,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{10}',$$||directed||$$)$$, $$"get_solution" (22,22,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{11}',$$||directed||$$)$$, $$"get_solution" (23,23,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{12}',$$||directed||$$)$$, $$"get_solution" (24,24,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 12'); + RETURN QUERY + SELECT set_eq($$"graph1" ('5,11,13','{17}',$$||directed||$$)$$, $$"get_solution" (21,21,$$||directed||$$) $$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 17'); + RETURN QUERY + SELECT is_empty($$"graph1" ('5,11,13','{10,17}',$$||directed||$$)$$, '10 -> 11 -> 12 -> 17: Directed=' || directed ||', forbid 10,17'); + + -- The graph1 + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{}',$$||directed||$$)$$, $$"get_solution" (25,25,$$||directed||$$) $$, 'the graph1: Directed=' || directed ||', no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16','{3}',$$||directed||$$)$$, $$"get_solution" (26,26,$$||directed||$$) $$, 'the graph1: Directed=' || directed ||', forbid 3'); + +END; +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION check_contracted_graph_linear(BOOLEAN) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('3.8.0') THEN + RETURN QUERY SELECT skip(1, 'contraction function/signature is new on 3.8.0'); + RETURN; + END IF; + + IF $1 THEN + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('e',-1,ARRAY[3],7,1), ('e',-2,ARRAY[3],1,7)$$, 'The edges') ; + + RETURN QUERY + SELECT set_eq( + $$SELECT id FROM edges WHERE is_new$$, + $$SELECT unnest(ARRAY[19, 20])$$, 'The vertices' + ); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (1, 7, '2.085', '-1.000'), + (2, 4, '1.289', '1.289'), + (5, 6, '1.001', '1.001'), + (6, 7, '1.016', '1.016'), + (6, 10, '-0.996', '1.004'), + (7, 1, '2.085', '-1.000'), + (7, 8, '1.100', '1.100'), + (7, 11, '1.064', '1.064'), + (8, 9, '1.196', '1.196'), + (8, 12, '1.144', '-0.856'), + (10, 11, '1.025', '-0.975'), + (10, 15, '-0.991', '1.009'), + (11, 12, '1.121', '-0.879'), + (11, 16, '1.081', '1.081'), + (12, 17, '1.169', '-0.831'), + (13, 14, '1.324', '1.324'), + (15, 16, '1.256', '1.256'), + (16, 17, '1.225', '1.225')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + ELSE + RETURN QUERY + SELECT set_eq($$SELECT type, id, contracted_vertices, source, target FROM contraction_info$$, + $$ VALUES ('e',-3,ARRAY[17],16,12), ('e',-2,ARRAY[3],7,1), ('e', -1, ARRAY[15], 10, 16)$$) ; + + RETURN QUERY + SELECT set_eq( + $$SELECT id FROM edges WHERE is_new$$, + $$SELECT unnest(ARRAY[19, 20, 21])$$ + ); + + PREPARE c_expected_graph AS + SELECT source, target, cost, reverse_cost + FROM (VALUES + (2, 4, '1.289', '1.289'), + (5, 6, '1.001', '1.001'), + (6, 10, '-0.996', '1.004'), + (6, 7, '1.016', '1.016'), + (7, 1, '2.085', '-1.000'), + (7, 8, '1.100', '1.100'), + (7, 11, '1.064', '1.064'), + (8, 9, '1.196', '1.196'), + (8, 12, '1.144', '-0.856'), + (10, 11, '1.025', '-0.975'), + (10, 16, '2.265', '-1.000'), + (11, 12, '1.121', '-0.879'), + (11, 16, '1.081', '1.081'), + (13, 14, '1.324', '1.324'), + (16, 12, '2.394', '-1.000')) + AS t(source, target, cost, reverse_cost); + + RETURN QUERY + SELECT set_eq('SELECT source, target, round(cost::numeric, 3)::TEXT AS cost, round(reverse_cost::numeric, 3)::TEXT FROM contracted_graph', + 'c_expected_graph', 'The contracted graph'); + + END IF; + DEALLOCATE PREPARE c_expected_graph; +END +$BODY$ +LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION linear_edge_cases_sampledata(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + -- SINGLE edge + + RETURN QUERY SELECT is_empty($$"graph1" ('6','{}',$$||directed||$$)$$, '1<=>3: Directed=' || directed ||' no forbidden vertices'); + + -- TWO edges + + RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7','{}',$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7','{}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$ , '1<=>3<=>7: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7','{1}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 1'); + RETURN QUERY SELECT is_empty($$"graph1" ('6,7','{3}',$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 3'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7','{7}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7: Directed=' || directed ||' , forbid 7'); + + -- T shape + + RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7,4,10','{}',$$||directed||$$)$$, '1<=>3<=>7<->6,8: Directed=' || directed ||' no forbidden vertices'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,4,10','{}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,4,10','{1}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 1'); + RETURN QUERY + SELECT is_empty($$"graph1" ('6,7,4,10','{3}',$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 3'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,4,10','{7}',$$||directed||$$)$$, $$"get_solution" (2,12,$$||directed||$$)$$, '1<=>3<=>7<->6,8 : Directed=' || directed ||', forbid 7'); + + + -- THREE edges + + RETURN QUERY SELECT isnt_empty($$"graph1" ('6,7,8','{}',$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{1}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 1'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{11}',$$||directed||$$)$$, $$"get_solution" (3,13,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{3}',$$||directed||$$)$$, $$"get_solution" (4,14,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 3'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('6,7,8','{7}',$$||directed||$$)$$, $$"get_solution" (1,11,$$||directed||$$)$$, '1<=>3<=>7<=>11: Directed=' || directed ||', forbid 7'); + + -- FOUR edges + -- circling square + RETURN QUERY SELECT isnt_empty($$"graph1" ('3,5,9,16','{}',$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{}',$$||directed||$$)$$, $$"get_solution" (5,15,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||' no forbidden'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{11}',$$||directed||$$)$$, $$"get_solution" (5,15,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{15}',$$||directed||$$)$$, $$"get_solution" (5,25,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 15'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{10}',$$||directed||$$)$$, $$"get_solution" (6,16,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 10'); + RETURN QUERY + SELECT set_eq($$"graph1" ('3,5,9,16','{16}',$$||directed||$$)$$, $$"get_solution" (7,17,$$||directed||$$)$$, '10->11<=>16<=>15->10: Directed=' || directed ||', forbid 16'); + + -- non circling square + RETURN QUERY SELECT isnt_empty($$"graph1" ('2,4,5,8','{}',$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' no forbidden'); + + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' no forbidden'); + + if directed THEN + RETURN QUERY + SELECT is_empty($$"graph1" ('2,4,5,8','{7}',$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 7'); + ELSE + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{7}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 7'); + END IF; + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{11}',$$||directed||$$)$$, $$"get_solution" (8,18,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 11'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{6}',$$||directed||$$)$$, $$"get_solution" (8,28,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 6'); + RETURN QUERY + SELECT set_eq($$"graph1" ('2,4,5,8','{10}',$$||directed||$$)$$, $$"get_solution" (8,38,$$||directed||$$)$$, '11<-10->6<=>7<=>11->10: Directed=' || directed ||' forbid 10'); + + -- The graph1 + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{}',$$||directed||$$)$$, $$"get_solution" (9,19,$$||directed||$$)$$, 'the graph: Directed=' || directed ||' no forbidden'); + IF directed THEN + RETURN QUERY + SELECT is_empty($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{3}',$$||directed||$$)$$, 'the graph1: Directed=' || directed ||', forbid 3'); + ELSE + RETURN QUERY + SELECT set_eq($$"graph1" ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18','{3}',$$||directed||$$)$$, $$"get_solution" (1,20,$$||directed||$$)$$, 'the graph1: Directed=' || directed ||', forbid 3'); + END IF; + + +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION linear_edge_cases(directed text) +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + RETURN QUERY SELECT is_empty(format($$"graph" ('0',%1$s)$$,directed),'empty graph: 0,'||directed); + RETURN QUERY SELECT is_empty(format($$"graph" ('1',%1$s)$$,directed),'empty graph: 1,'||directed); + RETURN QUERY SELECT is_empty(format($$"graph" ('2',%1$s)$$,directed),'empty graph: 2,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('3',%1$s)$$,directed),'not empty graph: 3,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('4',%1$s)$$,directed),'not empty graph: 4,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('5',%1$s)$$,directed),'not empty graph: 5,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('6',%1$s)$$,directed),'not empty graph: 6,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('7',%1$s)$$,directed),'not empty graph: 7,'||directed); + + RETURN QUERY SELECT is_empty(format($$"graph" ('0,1',%1$s)$$,directed), 'empty graph: 0,1,'||directed); + RETURN QUERY SELECT is_empty(format($$"graph" ('0,2',%1$s)$$,directed), 'empty graph: 0,2,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,3',%1$s)$$,directed), 'not empty graph: 0,3,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,4',%1$s)$$,directed), 'not empty graph: 0,4,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,5',%1$s)$$,directed), 'not empty graph: 0,5,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,6',%1$s)$$,directed), 'not empty graph: 0,6,'||directed); + RETURN QUERY SELECT isnt_empty(format($$"graph" ('0,7',%1$s)$$,directed), 'not empty graph: 0,7,'||directed); + + RETURN QUERY SELECT set_eq(format($$"graph" ('3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 3,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 4,'||directed) ; + + if directed THEN + RETURN QUERY SELECT set_eq(format($$"graph" ('5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2),('e',-2,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[11]::BIGINT[],1,3,2), ('e',-2,ARRAY[11]::BIGINT[],3,1,2) $$, 'expected graph: 6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3), ('e',-2,ARRAY[1,2]::BIGINT[],3,11,3) $$, 'expected graph: 7,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 0,3,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,4,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2),('e',-2,ARRAY[2]::BIGINT[],1,11,2) $$, 'expected graph: 0,5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1]::BIGINT[],11,3,2),('e',-2,ARRAY[1]::BIGINT[],3,11,2) $$, 'expected graph: 0,6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3),('e',-2,ARRAY[1,2]::BIGINT[],3,11,3) $$, 'expected graph: 0,7,'||directed) ; + ELSE + RETURN QUERY SELECT set_eq(format($$"graph" ('5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[11]::BIGINT[],1,3,2) $$, 'expected graph: 6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,11]::BIGINT[],2,3,3) $$, 'expected graph: 7,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,3',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,3,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,4',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,4,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,5',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[2]::BIGINT[],11,1,2) $$, 'expected graph: 0,5,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,6',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1]::BIGINT[],11,3,2) $$, 'expected graph: 0,6,'||directed) ; + RETURN QUERY SELECT set_eq(format($$"graph" ('0,7',%1$s)$$,directed), $$ VALUES ('e',-1,ARRAY[1,2]::BIGINT[],11,3,3) $$, 'expected graph: 0,7,'||directed) ; + END IF; + +END; +$BODY$ +LANGUAGE plpgsql; + CREATE OR REPLACE FUNCTION test_ids_size(pow INTEGER, directed BOOLEAN) RETURNS SETOF TEXT AS From 435c54a8c40b33b7ebbc2960ebb65dcb43acb153 Mon Sep 17 00:00:00 2001 From: cvvergara Date: Fri, 21 Mar 2025 10:52:07 -0600 Subject: [PATCH 09/11] (contraction/sql) fixing parameter mismatch on notice --- sql/contraction/contraction.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/contraction/contraction.sql b/sql/contraction/contraction.sql index f11bf646afb..4ac224f04dc 100644 --- a/sql/contraction/contraction.sql +++ b/sql/contraction/contraction.sql @@ -79,7 +79,7 @@ CREATE FUNCTION pgr_contraction( RETURNS SETOF RECORD AS $BODY$ BEGIN - RAISE NOTICE 'Deprecated Signature pgr_contraction(text,boolean,integer[],integer,bigint[]) in v3.8.0'; + RAISE NOTICE 'Deprecated Signature pgr_contraction(text,bigint[],integer,integer[],bigint[],boolean) in v3.8.0'; RETURN QUERY SELECT a.type, a.id, a.contracted_vertices, a.source, a.target, a.cost FROM _pgr_contraction(_pgr_get_statement($1), $2::BIGINT[], $3, $4, $5) AS a; From cf2d5af00a28c93180370fb4f4ccc0bf9595f422 Mon Sep 17 00:00:00 2001 From: cvvergara Date: Fri, 21 Mar 2025 10:55:42 -0600 Subject: [PATCH 10/11] (contraction/doc) improving readability --- doc/contraction/pgr_contraction.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/contraction/pgr_contraction.rst b/doc/contraction/pgr_contraction.rst index bb63e599712..c48a51c3d83 100644 --- a/doc/contraction/pgr_contraction.rst +++ b/doc/contraction/pgr_contraction.rst @@ -241,12 +241,12 @@ Only linear contraction The cycle ................................................................................ -Contracting a graph, can be done with more than one operation. +Contracting a graph can be done with more than one operation. The order of the operations affect the resulting contracted graph, after applying one operation, the set of vertices that can be contracted by another operation changes. -This implementation, cycles ``cycles`` times through the ``methods`` . +This implementation cycles ``cycles`` times through the ``methods`` . .. parsed-literal:: From 3068330c37d27e5b12ecac762d474ee1d3678d89 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 17:02:44 +0000 Subject: [PATCH 11/11] Update locale: commit cf2d5af00 --- locale/en/LC_MESSAGES/pgrouting_doc_strings.po | 6 +++--- locale/pot/pgrouting_doc_strings.pot | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/locale/en/LC_MESSAGES/pgrouting_doc_strings.po b/locale/en/LC_MESSAGES/pgrouting_doc_strings.po index b1fbde5af52..9334756764f 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 v3.8\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-21 04:11+0000\n" +"POT-Creation-Date: 2025-03-21 17:02+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -9520,13 +9520,13 @@ msgid "The cycle" msgstr "" msgid "" -"Contracting a graph, can be done with more than one operation. The order " +"Contracting a graph can be done with more than one operation. The order " "of the operations affect the resulting contracted graph, after applying " "one operation, the set of vertices that can be contracted by another " "operation changes." msgstr "" -msgid "This implementation, cycles ``cycles`` times through the ``methods`` ." +msgid "This implementation cycles ``cycles`` times through the ``methods`` ." msgstr "" msgid "Contracting sample data" diff --git a/locale/pot/pgrouting_doc_strings.pot b/locale/pot/pgrouting_doc_strings.pot index 62a8f0203a7..258d34c676e 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 v3.8\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-21 04:11+0000\n" +"POT-Creation-Date: 2025-03-21 17:02+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -8179,10 +8179,10 @@ msgstr "" msgid "The cycle" msgstr "" -msgid "Contracting a graph, can be done with more than one operation. The order of the operations affect the resulting contracted graph, after applying one operation, the set of vertices that can be contracted by another operation changes." +msgid "Contracting a graph can be done with more than one operation. The order of the operations affect the resulting contracted graph, after applying one operation, the set of vertices that can be contracted by another operation changes." msgstr "" -msgid "This implementation, cycles ``cycles`` times through the ``methods`` ." +msgid "This implementation cycles ``cycles`` times through the ``methods`` ." msgstr "" msgid "Contracting sample data"