From 14e9b43aa8f062fc11f8aede24ee38adc56c5097 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:10:00 +0530 Subject: [PATCH 01/20] [ci] Add style-lint check to GitHub Actions --- .github/workflows/check-files.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/check-files.yml b/.github/workflows/check-files.yml index 2d8d02b58..61ed93602 100644 --- a/.github/workflows/check-files.yml +++ b/.github/workflows/check-files.yml @@ -46,3 +46,18 @@ jobs: sudo apt install -y shellcheck - name: Run Shell Check run: ./tools/scripts/test_shell.sh + + style-check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install Requirements + uses: actions/checkout@v2 + with: + repository: 'google/styleguide' + ref: "gh-pages" + path: "code_linter/styleguide" + - name: Run linter + run: | + bash ./tools/scripts/code_checker.sh \ No newline at end of file From 870596567db6b9e7cfb05071a4842f01ae1a0399 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:11:38 +0530 Subject: [PATCH 02/20] [tools] Fix code checker: Exit with non-zero status in case of error --- tools/scripts/code_checker.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/scripts/code_checker.sh b/tools/scripts/code_checker.sh index eea13778e..83d3e6b29 100644 --- a/tools/scripts/code_checker.sh +++ b/tools/scripts/code_checker.sh @@ -28,6 +28,8 @@ # DEALINGS IN THE SOFTWARE. ############################################################################### +set -e + if ! test -d code_linter; then # Get our fork of codespell that adds --words-white-list and full filename support for -S option mkdir code_linter @@ -84,4 +86,3 @@ else test_cpp_files "$(git ls-files | grep -w 'cpp' | grep ${DIRECTORY})" fi fi - From 388b69fc4de1edcd23f17ae54e4c6c5dba9d5ab0 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:13:24 +0530 Subject: [PATCH 03/20] [editorconfig] Modify editorconfig according to code checker --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 979609fd6..7a915e98a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ indent_size = 4 indent_style = space charset = utf-8 end_of_line = lf -insert_final_newline = false +insert_final_newline = true trim_trailing_whitespace = true # C++ files want tab indentation From 74f99a9c37bba7d4f0bee8be86e502445184168c Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:17:14 +0530 Subject: [PATCH 04/20] [lint] Linting C/C++ code for fixing code checker errors --- include/problem/matrix.h | 2 +- src/optimize/optimize_driver.cpp | 3 +- .../pickDeliverEuclidean_driver.cpp | 31 +++++++++---------- src/pickDeliver/pickDeliver.c | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/problem/matrix.h b/include/problem/matrix.h index 1858360cb..9cbe705fd 100644 --- a/include/problem/matrix.h +++ b/include/problem/matrix.h @@ -57,7 +57,7 @@ class Matrix : public base::Base_Matrix { Matrix(Matrix_cell_t *, size_t, const Identifiers&, Multiplier = 1.0); /** brief constructor for euclidean version default multipliers */ - Matrix(const std::map, Id>&, Multiplier = 1.0); + explicit Matrix(const std::map, Id>&, Multiplier = 1.0); /** @brief retrun the travel time times when using the time dependant multipliers */ TInterval travel_time(Id, Id, TTimestamp) const; diff --git a/src/optimize/optimize_driver.cpp b/src/optimize/optimize_driver.cpp index 88b383492..85fbce4ed 100644 --- a/src/optimize/optimize_driver.cpp +++ b/src/optimize/optimize_driver.cpp @@ -184,7 +184,8 @@ get_initial_stops( * @param[in] new_values subset of stops that are to be used for the update */ void -update_stops(std::vector& the_stops, const std::vector new_values) { +update_stops(std::vector& the_stops, // NOLINT [runtime/references] + const std::vector new_values) { for (const auto &v : new_values) { auto v_id = v.id; auto v_to_modify = std::find_if( diff --git a/src/pgr_pickDeliver/pickDeliverEuclidean_driver.cpp b/src/pgr_pickDeliver/pickDeliverEuclidean_driver.cpp index 30dc65e42..92746c1ad 100644 --- a/src/pgr_pickDeliver/pickDeliverEuclidean_driver.cpp +++ b/src/pgr_pickDeliver/pickDeliverEuclidean_driver.cpp @@ -72,8 +72,8 @@ bool are_shipments_ok( PickDeliveryOrders_t *customers_arr, size_t total_customers, - std::string &err_string, - std::string &hint_string) { + std::string *err_string, + std::string *hint_string) { /** * - demand > 0 (the type is unsigned so no need to check for negative values, only for it to be non 0 * - pick_service_t >=0 @@ -83,35 +83,34 @@ are_shipments_ok( */ for (size_t i = 0; i < total_customers; ++i) { if (customers_arr[i].demand == 0) { - err_string = "Unexpected zero value found on column 'demand' of shipments"; - hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); + *err_string = "Unexpected zero value found on column 'demand' of shipments"; + *hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); return false; } if (customers_arr[i].pick_service_t < 0) { - err_string = "Unexpected negative value found on column 'p_service_t' of shipments"; - hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); + *err_string = "Unexpected negative value found on column 'p_service_t' of shipments"; + *hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); return false; } if (customers_arr[i].deliver_service_t < 0) { - err_string = "Unexpected negative value found on column 'd_service_t' of shipments"; - hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); + *err_string = "Unexpected negative value found on column 'd_service_t' of shipments"; + *hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); return false; } if (customers_arr[i].pick_open_t > customers_arr[i].pick_close_t) { - err_string = "Unexpected pickup time windows found on shipments"; - hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); + *err_string = "Unexpected pickup time windows found on shipments"; + *hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); return false; } if (customers_arr[i].deliver_open_t > customers_arr[i].deliver_close_t) { - err_string = "Unexpected delivery time windows found on shipments"; - hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); + *err_string = "Unexpected delivery time windows found on shipments"; + *hint_string = "Check shipment id #:" + std::to_string(customers_arr[i].id); return false; } - } return true; } @@ -144,7 +143,7 @@ do_pgr_pickDeliverEuclidean( *return_count = 0; std::string err_string; std::string hint_string; - if (!are_shipments_ok(customers_arr, total_customers, err_string, hint_string)) { + if (!are_shipments_ok(customers_arr, total_customers, &err_string, &hint_string)) { *err_msg = pgr_msg(err_string.c_str()); *log_msg = pgr_msg(hint_string.c_str()); return; @@ -161,8 +160,8 @@ do_pgr_pickDeliverEuclidean( std::map, Id> matrix_data; for (const auto &o : orders) { - pgassert(o.pick_node_id==0); - pgassert(o.deliver_node_id==0); + pgassert(o.pick_node_id == 0); + pgassert(o.deliver_node_id == 0); matrix_data[std::pair(o.pick_x, o.pick_y)] = 0; matrix_data[std::pair(o.deliver_x, o.deliver_y)] = 0; } diff --git a/src/pickDeliver/pickDeliver.c b/src/pickDeliver/pickDeliver.c index 64460e224..cc9485d49 100644 --- a/src/pickDeliver/pickDeliver.c +++ b/src/pickDeliver/pickDeliver.c @@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include "c_common/postgres_connection.h" -#include +#include // NOLINT [build/include_order] #include "c_common/debug_macro.h" #include "c_common/e_report.h" #include "c_common/time_msg.h" From 6a367aec1b7be1f0a1bb7e5e7d89c23beda93376 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:19:08 +0530 Subject: [PATCH 05/20] [vroom][sql] Added SQL code for VROOM category functions --- sql/sigs/vrprouting--0.2.sig | 4 + sql/vroom/CMakeLists.txt | 13 +++ sql/vroom/_vrp_vroom.sql | 59 +++++++++++ sql/vroom/vrp_vroom.sql | 170 +++++++++++++++++++++++++++++++ sql/vroom/vrp_vroomJobs.sql | 117 +++++++++++++++++++++ sql/vroom/vrp_vroomShipments.sql | 119 ++++++++++++++++++++++ 6 files changed, 482 insertions(+) create mode 100644 sql/vroom/CMakeLists.txt create mode 100644 sql/vroom/_vrp_vroom.sql create mode 100644 sql/vroom/vrp_vroom.sql create mode 100644 sql/vroom/vrp_vroomJobs.sql create mode 100644 sql/vroom/vrp_vroomShipments.sql diff --git a/sql/sigs/vrprouting--0.2.sig b/sql/sigs/vrprouting--0.2.sig index 8f7b46f84..0d35746a9 100644 --- a/sql/sigs/vrprouting--0.2.sig +++ b/sql/sigs/vrprouting--0.2.sig @@ -32,3 +32,7 @@ _vrp_vehiclesattime(text,timestamp without time zone,boolean) vrp_version() vrp_viewrouteraw(text,text,text,text,bigint,double precision) vrp_viewroute(text,text,text,text,bigint,double precision) +vrp_vroomjobs(text,text,text,text,text,text) +vrp_vroomshipments(text,text,text,text,text,text) +vrp_vroom(text,text,text,text,text,text,text,text) +_vrp_vroom(text,text,text,text,text,text,text,text,smallint) diff --git a/sql/vroom/CMakeLists.txt b/sql/vroom/CMakeLists.txt new file mode 100644 index 000000000..d50610ef3 --- /dev/null +++ b/sql/vroom/CMakeLists.txt @@ -0,0 +1,13 @@ +SET(LOCAL_FILES + _vrp_vroom.sql + vrp_vroom.sql + vrp_vroomJobs.sql + vrp_vroomShipments.sql + ) + +foreach (f ${LOCAL_FILES}) + configure_file(${f} ${f}) + list(APPEND PACKAGE_SQL_FILES ${CMAKE_CURRENT_BINARY_DIR}/${f}) +endforeach() + +set(PROJECT_SQL_FILES ${PROJECT_SQL_FILES} ${PACKAGE_SQL_FILES} PARENT_SCOPE) diff --git a/sql/vroom/_vrp_vroom.sql b/sql/vroom/_vrp_vroom.sql new file mode 100644 index 000000000..2c5334393 --- /dev/null +++ b/sql/vroom/_vrp_vroom.sql @@ -0,0 +1,59 @@ +/*PGR-GNU***************************************************************** +File: _vrp_vroom.sql + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +-- v0.2 +CREATE FUNCTION _vrp_vroom( + jobs_sql TEXT, + jobs_time_windows_sql TEXT, + shipments_sql TEXT, + shipments_time_windows_sql TEXT, + vehicles_sql TEXT, + breaks_sql TEXT, + breaks_time_windows_sql TEXT, + matrix_sql TEXT, + fn SMALLINT, + + OUT seq BIGINT, + OUT vehicle_seq BIGINT, + OUT vehicle_id BIGINT, + OUT step_seq BIGINT, + OUT step_type INTEGER, + OUT task_id BIGINT, + OUT arrival INTEGER, + OUT travel_time INTEGER, + OUT service_time INTEGER, + OUT waiting_time INTEGER, + OUT load BIGINT[]) +RETURNS SETOF RECORD AS + 'MODULE_PATHNAME' +LANGUAGE C VOLATILE; + +-- COMMENTS + +COMMENT ON FUNCTION _vrp_vroom(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, SMALLINT) +IS 'pgRouting internal function'; diff --git a/sql/vroom/vrp_vroom.sql b/sql/vroom/vrp_vroom.sql new file mode 100644 index 000000000..8f982ae07 --- /dev/null +++ b/sql/vroom/vrp_vroom.sql @@ -0,0 +1,170 @@ +/*PGR-GNU***************************************************************** +File: vrp_vroom.sql + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +/* +signature start + +.. code-block:: none + + vrp_vroom( + Jobs SQL, Jobs Time Windows SQL, + Shipments SQL, Shipments Time Windows SQL, + Vehicles SQL, Breaks SQL, Breaks Time Windows SQL, + Matrix SQL) -- Experimental on v0.2 + + RETURNS SET OF + (seq, vehicle_seq, vehicle_id, step_seq, step_type, task_id, + arrival, travel_time, service_time, waiting_time, load) + +signature end + +parameters start + +============================== =========== ========================================================= +Parameter Type Description +============================== =========== ========================================================= +**Jobs SQL** ``TEXT`` `Jobs SQL`_ query describing the single-location + pickup and/or delivery tasks. +**Jobs Time Windows SQL** ``TEXT`` `Time Windows SQL`_ query describing valid slots + for job service start. +**Shipments SQL** ``TEXT`` `Shipments SQL`_ query describing pickup and delivery + tasks that should happen within same route. +**Shipments Time Windows SQL** ``TEXT`` `Time Windows SQL`_ query describing valid slots + for pickup and delivery service start. +**Vehicles SQL** ``TEXT`` `Vehicles SQL`_ query describing the available vehicles. +**Breaks SQL** ``TEXT`` `Breaks SQL`_ query describing the driver breaks. +**Breaks Time Windows SQL** ``TEXT`` `Time Windows SQL`_ query describing valid slots for + break start. +**Matrix SQL** ``TEXT`` `Time Matrix SQL`_ query containing the distance or + travel times between the locations. +============================== =========== ========================================================= + +parameters end + +result start + +=================== ============= ================================================= +Column Type Description +=================== ============= ================================================= +**seq** ``BIGINT`` Sequential value starting from **1**. + +**vehicle_seq** ``BIGINT`` Sequential value starting from **1** for current vehicles. + The :math:`n^{th}` vehicle in the solution. + +**vehicle_id** ``BIGINT`` Current vehicle identifier. + +**step_seq** ``BIGINT`` Sequential value starting from **1** for the stops + made by the current vehicle. The :math:`m^{th}` stop + of the current vehicle. + +**step_type** ``INTEGER`` Kind of the step location the vehicle is at: + + - ``1``: Starting location + - ``2``: Job location + - ``3``: Pickup location + - ``4``: Delivery location + - ``5``: Break location + - ``6``: Ending location + +**task_id** ``BIGINT`` Identifier of the task performed at this step. + + - ``-1``: If the step is starting/ending location. + +**arrival** ``INTEGER`` Estimated time of arrival at this step, in seconds. + +**travel_time** ``INTEGER`` Cumulated travel time upon arrival at this step, in seconds + +**service_time** ``INTEGER`` Service time at this step, in seconds + +**waiting_time** ``INTEGER`` Waiting time upon arrival at this step, in seconds. + +**load** ``BIGINT`` Vehicle load after step completion (with capacity constraints) +=================== ============= ================================================= + +result end +*/ + +-- v0.2 +CREATE FUNCTION vrp_vroom( + TEXT, -- jobs_sql (required) + TEXT, -- jobs_time_windows_sql (required) + TEXT, -- shipments_sql (required) + TEXT, -- shipments_time_windows_sql (required) + TEXT, -- vehicles_sql (required) + TEXT, -- breaks_sql (required) + TEXT, -- breaks_time_windows_sql (required) + TEXT, -- matrix_sql (required) + + OUT seq BIGINT, + OUT vehicle_seq BIGINT, + OUT vehicle_id BIGINT, + OUT step_seq BIGINT, + OUT step_type INTEGER, + OUT task_id BIGINT, + OUT arrival INTEGER, + OUT travel_time INTEGER, + OUT service_time INTEGER, + OUT waiting_time INTEGER, + OUT load BIGINT[]) +RETURNS SETOF RECORD AS +$BODY$ + SELECT * + FROM _vrp_vroom(_pgr_get_statement($1), _pgr_get_statement($2), _pgr_get_statement($3), + _pgr_get_statement($4), _pgr_get_statement($5), _pgr_get_statement($6), + _pgr_get_statement($7), _pgr_get_statement($8), 0::SMALLINT); +$BODY$ +LANGUAGE SQL VOLATILE; + + +-- COMMENTS + +COMMENT ON FUNCTION vrp_vroom(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, TEXT) +IS 'vrp_vroom + - EXPERIMENTAL + - Parameters: + - Jobs SQL with columns: + id, location_index [, service, delivery, pickup, skills, priority, time_windows] + - Jobs Time Windows SQL with columns: + id, tw_open, tw_close + - Shipments SQL with columns: + p_id, p_location_index [, p_service, p_time_windows], + d_id, d_location_index [, d_service, d_time_windows] [, amount, skills, priority] + - Shipments Time Windows SQL with columns: + id, kind, tw_open, tw_close + - Vehicles SQL with columns: + id, start_index, end_index + [, service, delivery, pickup, skills, priority, time_window, breaks_sql, steps_sql] + - Breaks SQL with columns: + id [, service] + - Breaks Time Windows SQL with columns: + id, tw_open, tw_close + - Matrix SQL with columns: + start_vid, end_vid, agg_cost + - Documentation: + - ${PROJECT_DOC_LINK}/vrp_vroom.html +'; diff --git a/sql/vroom/vrp_vroomJobs.sql b/sql/vroom/vrp_vroomJobs.sql new file mode 100644 index 000000000..37b4d1efc --- /dev/null +++ b/sql/vroom/vrp_vroomJobs.sql @@ -0,0 +1,117 @@ +/*PGR-GNU***************************************************************** +File: vrp_vroomJobs.sql + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +/* +signature start + +.. code-block:: none + + vrp_vroomJobs( + Jobs SQL, Jobs Time Windows SQL, + Vehicles SQL, Breaks SQL, Breaks Time Windows SQL, + Matrix SQL) -- Experimental on v0.2 + + RETURNS SET OF + (seq, vehicle_seq, vehicle_id, step_seq, step_type, task_id, + arrival, travel_time, service_time, waiting_time, load) + +signature end + +parameters start + +============================== =========== ========================================================= +Parameter Type Description +============================== =========== ========================================================= +**Jobs SQL** ``TEXT`` `Jobs SQL`_ query describing the single-location + pickup and/or delivery tasks. +**Jobs Time Windows SQL** ``TEXT`` `Time Windows SQL`_ query describing valid slots + for job service start. +**Vehicles SQL** ``TEXT`` `Vehicles SQL`_ query describing the available vehicles. +**Breaks SQL** ``TEXT`` `Breaks SQL`_ query describing the driver breaks. +**Breaks Time Windows SQL** ``TEXT`` `Time Windows SQL`_ query describing valid slots for + break start. +**Matrix SQL** ``TEXT`` `Time Matrix SQL`_ query containing the distance or + travel times between the locations. +============================== =========== ========================================================= + +parameters end + +*/ + +-- v0.2 +CREATE FUNCTION vrp_vroomJobs( + TEXT, -- jobs_sql (required) + TEXT, -- jobs_time_windows_sql (required) + TEXT, -- vehicles_sql (required) + TEXT, -- breaks_sql (required) + TEXT, -- breaks_time_windows_sql (required) + TEXT, -- matrix_sql (required) + + OUT seq BIGINT, + OUT vehicle_seq BIGINT, + OUT vehicle_id BIGINT, + OUT step_seq BIGINT, + OUT step_type INTEGER, + OUT task_id BIGINT, + OUT arrival INTEGER, + OUT travel_time INTEGER, + OUT service_time INTEGER, + OUT waiting_time INTEGER, + OUT load BIGINT[]) +RETURNS SETOF RECORD AS +$BODY$ + SELECT * + FROM _vrp_vroom(_pgr_get_statement($1), _pgr_get_statement($2), NULL, NULL, + _pgr_get_statement($3), _pgr_get_statement($4), + _pgr_get_statement($5), _pgr_get_statement($6), 1::SMALLINT); +$BODY$ +LANGUAGE SQL VOLATILE; + + +-- COMMENTS + +COMMENT ON FUNCTION vrp_vroomJobs(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT) +IS 'vrp_vroomJobs + - EXPERIMENTAL + - Parameters: + - Jobs SQL with columns: + id, location_index [, service, delivery, pickup, skills, priority, time_windows] + - Jobs Time Windows SQL with columns: + id, tw_open, tw_close + - Vehicles SQL with columns: + id, start_index, end_index + [, service, delivery, pickup, skills, priority, time_window, breaks_sql, steps_sql] + - Breaks SQL with columns: + id [, service] + - Breaks Time Windows SQL with columns: + id, tw_open, tw_close + - Matrix SQL with columns: + start_vid, end_vid, agg_cost + - Documentation: + - ${PROJECT_DOC_LINK}/vrp_vroomJobs.html +'; diff --git a/sql/vroom/vrp_vroomShipments.sql b/sql/vroom/vrp_vroomShipments.sql new file mode 100644 index 000000000..0d4a66bd9 --- /dev/null +++ b/sql/vroom/vrp_vroomShipments.sql @@ -0,0 +1,119 @@ +/*PGR-GNU***************************************************************** +File: vrp_vroomShipments.sql + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +/* +signature start + +.. code-block:: none + + vrp_vroomShipments( + Shipments SQL, Shipments Time Windows SQL, + Vehicles SQL, Breaks SQL, Breaks Time Windows SQL, + Matrix SQL) -- Experimental on v0.2 + + RETURNS SET OF + (seq, vehicle_seq, vehicle_id, step_seq, step_type, task_id, + arrival, travel_time, service_time, waiting_time, load) + +signature end + +parameters start + +============================== =========== ========================================================= +Parameter Type Description +============================== =========== ========================================================= +**Shipments SQL** ``TEXT`` `Shipments SQL`_ query describing pickup and delivery + tasks that should happen within same route. +**Shipments Time Windows SQL** ``TEXT`` `Time Windows SQL`_ query describing valid slots + for pickup and delivery service start. +**Vehicles SQL** ``TEXT`` `Vehicles SQL`_ query describing the available vehicles. +**Breaks SQL** ``TEXT`` `Breaks SQL`_ query describing the driver breaks. +**Breaks Time Windows SQL** ``TEXT`` `Time Windows SQL`_ query describing valid slots for + break start. +**Matrix SQL** ``TEXT`` `Time Matrix SQL`_ query containing the distance or + travel times between the locations. +============================== =========== ========================================================= + +parameters end + +*/ + +-- v0.2 +CREATE FUNCTION vrp_vroomShipments( + TEXT, -- shipments_sql (required) + TEXT, -- shipments_time_windows_sql (required) + TEXT, -- vehicles_sql (required) + TEXT, -- breaks_sql (required) + TEXT, -- breaks_time_windows_sql (required) + TEXT, -- matrix_sql (required) + + OUT seq BIGINT, + OUT vehicle_seq BIGINT, + OUT vehicle_id BIGINT, + OUT step_seq BIGINT, + OUT step_type INTEGER, + OUT task_id BIGINT, + OUT arrival INTEGER, + OUT travel_time INTEGER, + OUT service_time INTEGER, + OUT waiting_time INTEGER, + OUT load BIGINT[]) +RETURNS SETOF RECORD AS +$BODY$ + SELECT * + FROM _vrp_vroom(NULL, NULL, _pgr_get_statement($1), + _pgr_get_statement($2), _pgr_get_statement($3), + _pgr_get_statement($4), _pgr_get_statement($5), + _pgr_get_statement($6), 2::SMALLINT); +$BODY$ +LANGUAGE SQL VOLATILE; + + +-- COMMENTS + +COMMENT ON FUNCTION vrp_vroomShipments(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT) +IS 'vrp_vroomShipments + - EXPERIMENTAL + - Parameters: + - Shipments SQL with columns: + p_id, p_location_index [, p_service, p_time_windows], + d_id, d_location_index [, d_service, d_time_windows] [, amount, skills, priority] + - Shipments Time Windows SQL with columns: + id, kind, tw_open, tw_close + - Vehicles SQL with columns: + id, start_index, end_index + [, service, delivery, pickup, skills, priority, time_window, breaks_sql, steps_sql] + - Breaks SQL with columns: + id [, service] + - Breaks Time Windows SQL with columns: + id, tw_open, tw_close + - Matrix SQL with columns: + start_vid, end_vid, agg_cost + - Documentation: + - ${PROJECT_DOC_LINK}/vrp_vroomShipments.html +'; From e44afc4d951cc65ed3c65282ba6359485a02e518 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:20:40 +0530 Subject: [PATCH 06/20] [vroom][src] Added VROOM driver and C code --- src/vroom/CMakeLists.txt | 4 + src/vroom/vroom.c | 421 +++++++++++++++++++++++++++++++++++++ src/vroom/vroom_driver.cpp | 212 +++++++++++++++++++ 3 files changed, 637 insertions(+) create mode 100644 src/vroom/CMakeLists.txt create mode 100644 src/vroom/vroom.c create mode 100644 src/vroom/vroom_driver.cpp diff --git a/src/vroom/CMakeLists.txt b/src/vroom/CMakeLists.txt new file mode 100644 index 000000000..c1054e66c --- /dev/null +++ b/src/vroom/CMakeLists.txt @@ -0,0 +1,4 @@ +ADD_LIBRARY(vroom OBJECT + vroom.c + vroom_driver.cpp + ) diff --git a/src/vroom/vroom.c b/src/vroom/vroom.c new file mode 100644 index 000000000..b54039d4e --- /dev/null +++ b/src/vroom/vroom.c @@ -0,0 +1,421 @@ +/*PGR-GNU***************************************************************** +File: vroom.c + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +/** @file vroom.c + * @brief Connecting code with postgres. + * + */ + +#include +#include + +#include "c_common/postgres_connection.h" +#include // NOLINT [build/include_order] + +#include "catalog/pg_type.h" +#include "utils/lsyscache.h" + +#ifndef INT8ARRAYOID +#define INT8ARRAYOID 1016 +#endif + +#include "c_common/debug_macro.h" +#include "c_common/e_report.h" +#include "c_common/time_msg.h" + +#include "c_types/vroom/vroom_rt.h" +#include "c_types/vroom/vroom_job_t.h" +#include "c_types/vroom/vroom_shipment_t.h" +#include "c_types/vroom/vroom_vehicle_t.h" + +#include "c_common/vroom/jobs_input.h" +#include "c_common/vroom/breaks_input.h" +#include "c_common/vroom/time_windows_input.h" +#include "c_common/vroom/shipments_input.h" +#include "c_common/vroom/vehicles_input.h" +#include "c_common/matrixRows_input.h" + +#include "drivers/vroom/vroom_driver.h" + +PGDLLEXPORT Datum _vrp_vroom(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(_vrp_vroom); + +/** @brief Static function, loads the data from postgres to C types for further processing. + * + * It first connects the C function to the SPI manager. Then converts + * the postgres array to C array and loads the edges belonging to the graph + * in C types. Then it calls the function `do_vrp_vroom` defined + * in the `vroom_driver.h` file for further processing. + * Finally, it frees the memory and disconnects the C function to the SPI manager. + * + * @param jobs_sql SQL query describing the jobs + * @param jobs_tw_sql SQL query describing the time window for jobs + * @param shipments_sql SQL query describing the shipments + * @param shipments_tw_sql SQL query describing the time windows for shipment + * @param vehicles_sql SQL query describing the vehicles + * @param breaks_sql SQL query describing the driver breaks. + * @param breaks_tws_sql SQL query describing the time windows for break start. + * @param matrix_sql SQL query describing the cells of the cost matrix + * @param fn Value denoting the function used. + * @param result_tuples the rows in the result + * @param result_count the count of rows in the result + * + * @returns void + */ +static +void +process( + char *jobs_sql, + char *jobs_tws_sql, + char *shipments_sql, + char *shipments_tws_sql, + char *vehicles_sql, + char *breaks_sql, + char *breaks_tws_sql, + char *matrix_sql, + int16_t fn, + + Vroom_rt **result_tuples, + size_t *result_count) { + pgr_SPI_connect(); + + (*result_tuples) = NULL; + (*result_count) = 0; + + Vroom_job_t *jobs = NULL; + size_t total_jobs = 0; + if (jobs_sql) { + get_vroom_jobs(jobs_sql, &jobs, &total_jobs); + } + + Vroom_shipment_t *shipments = NULL; + size_t total_shipments = 0; + if (shipments_sql) { + get_vroom_shipments(shipments_sql, &shipments, &total_shipments); + } + + if (total_jobs == 0 && total_shipments == 0) { + if (fn == 0) { + ereport(WARNING, (errmsg("Insufficient data found on Jobs SQL and Shipments SQL query."), + errhint("%s, %s", jobs_sql, shipments_sql))); + } else if (fn == 1) { + ereport(WARNING, (errmsg("Insufficient data found on Jobs SQL query."), + errhint("%s", jobs_sql))); + } else if (fn == 2) { + ereport(WARNING, (errmsg("Insufficient data found on Shipments SQL query."), + errhint("%s", shipments_sql))); + } + (*result_count) = 0; + (*result_tuples) = NULL; + pgr_SPI_finish(); + return; + } + + Vroom_time_window_t *jobs_tws = NULL; + size_t total_jobs_tws = 0; + if (jobs_tws_sql) { + get_vroom_time_windows(jobs_tws_sql, &jobs_tws, &total_jobs_tws); + } + + Vroom_time_window_t *shipments_tws = NULL; + size_t total_shipments_tws = 0; + if (shipments_tws_sql) { + get_vroom_shipments_time_windows(shipments_tws_sql, &shipments_tws, &total_shipments_tws); + } + + Vroom_vehicle_t *vehicles = NULL; + size_t total_vehicles = 0; + get_vroom_vehicles(vehicles_sql, &vehicles, &total_vehicles); + + if (total_vehicles == 0) { + ereport(WARNING, (errmsg("Insufficient data found on Vehicles SQL query."), + errhint("%s", vehicles_sql))); + (*result_count) = 0; + (*result_tuples) = NULL; + pgr_SPI_finish(); + return; + } + + Vroom_break_t *breaks = NULL; + size_t total_breaks = 0; + if (breaks_sql) { + get_vroom_breaks(breaks_sql, &breaks, &total_breaks); + } + + Vroom_time_window_t *breaks_tws = NULL; + size_t total_breaks_tws = 0; + if (breaks_tws_sql) { + get_vroom_time_windows(breaks_tws_sql, &breaks_tws, &total_breaks_tws); + } + + Matrix_cell_t *matrix_cells_arr = NULL; + size_t total_cells = 0; + get_matrixRows_vroom_plain(matrix_sql, &matrix_cells_arr, &total_cells); + + if (total_cells == 0) { + ereport(WARNING, (errmsg("Insufficient data found on Matrix SQL query."), + errhint("%s", matrix_sql))); + (*result_count) = 0; + (*result_tuples) = NULL; + pgr_SPI_finish(); + return; + } + + clock_t start_t = clock(); + char *log_msg = NULL; + char *notice_msg = NULL; + char *err_msg = NULL; + + do_vrp_vroom( + jobs, total_jobs, + jobs_tws, total_jobs_tws, + shipments, total_shipments, + shipments_tws, total_shipments_tws, + vehicles, total_vehicles, + breaks, total_breaks, + breaks_tws, total_breaks_tws, + matrix_cells_arr, total_cells, + + result_tuples, + result_count, + + &log_msg, + ¬ice_msg, + &err_msg); + + time_msg("processing vrp_vroom", start_t, clock()); + + if (err_msg && (*result_tuples)) { + pfree(*result_tuples); + (*result_tuples) = NULL; + (*result_count) = 0; + } + + pgr_global_report(log_msg, notice_msg, err_msg); + + if (log_msg) pfree(log_msg); + if (notice_msg) pfree(notice_msg); + if (err_msg) pfree(err_msg); + + if (jobs) pfree(jobs); + if (shipments) pfree(shipments); + if (vehicles) pfree(vehicles); + if (matrix_cells_arr) pfree(matrix_cells_arr); + + pgr_SPI_finish(); +} + + +/** @brief Helps in converting postgres variables to C variables, and returns the result. + * + */ + +PGDLLEXPORT Datum _vrp_vroom(PG_FUNCTION_ARGS) { + FuncCallContext *funcctx; + TupleDesc tuple_desc; + + /**********************************************************************/ + Vroom_rt *result_tuples = NULL; + size_t result_count = 0; + /**********************************************************************/ + + if (SRF_IS_FIRSTCALL()) { + MemoryContext oldcontext; + funcctx = SRF_FIRSTCALL_INIT(); + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + /*********************************************************************** + * + * _vrp_vroom( + * jobs_sql TEXT, + * jobs_time_windows_sql TEXT, + * shipments_sql TEXT, + * shipments_time_windows_sql TEXT, + * vehicles_sql TEXT, + * breaks_sql TEXT, + * breaks_time_windows_sql TEXT, + * matrix_sql TEXT, + * fn SMALLINT + * ); + * + **********************************************************************/ + + char *args[8]; + for (int i = 0; i < 8; i++) { + if (PG_ARGISNULL(i)) { + args[i] = NULL; + } else { + args[i] = text_to_cstring(PG_GETARG_TEXT_P(i)); + } + } + + int16_t fn = PG_GETARG_INT16(8); + + // Verify that both jobs_sql and shipments_sql are not NULL + if (args[0] == NULL && args[2] == NULL) { + if (fn == 0) { + elog(ERROR, "Both Jobs SQL and Shipments NULL must not be NULL"); + } else if (fn == 1) { + elog(ERROR, "Jobs SQL must not be NULL"); + } else if (fn == 2) { + elog(ERROR, "Shipments SQL must not be NULL"); + } + } + + if (args[4] == NULL) { + elog(ERROR, "Vehicles SQL must not be NULL"); + } + + if (args[7] == NULL) { + elog(ERROR, "Matrix SQL must not be NULL"); + } + + process( + args[0], + args[1], + args[2], + args[3], + args[4], + args[5], + args[6], + args[7], + fn, + &result_tuples, + &result_count); + + /**********************************************************************/ + + +#if PGSQL_VERSION > 95 + funcctx->max_calls = result_count; +#else + funcctx->max_calls = (uint32_t)result_count; +#endif + funcctx->user_fctx = result_tuples; + if (get_call_result_type(fcinfo, NULL, &tuple_desc) + != TYPEFUNC_COMPOSITE) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context " + "that cannot accept type record"))); + } + + funcctx->tuple_desc = tuple_desc; + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (Vroom_rt*) funcctx->user_fctx; + + if (funcctx->call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool* nulls; + int16 typlen; + size_t call_cntr = funcctx->call_cntr; + + /*********************************************************************** + * + * OUT seq BIGINT, + * OUT vehicles_seq BIGINT, + * OUT vehicles_id BIGINT, + * OUT step_seq BIGINT, + * OUT step_type INTEGER, + * OUT task_id BIGINT, + * OUT arrival INTEGER, + * OUT duration INTEGER, + * OUT service_time INTEGER, + * OUT waiting_time INTEGER, + * OUT load BIGINT + * + **********************************************************************/ + + size_t num = 11; + values = palloc(num * sizeof(Datum)); + nulls = palloc(num * sizeof(bool)); + + size_t i; + for (i = 0; i < num; ++i) { + nulls[i] = false; + } + + size_t load_size = (size_t)result_tuples[call_cntr].load_size; + Datum* load = (Datum*) palloc(sizeof(Datum) * (size_t)load_size); + + for (i = 0; i < load_size; ++i) { + load[i] = Int64GetDatum(result_tuples[call_cntr].load[i]); + } + + bool typbyval; + char typalign; + get_typlenbyvalalign(INT8OID, &typlen, &typbyval, &typalign); + ArrayType* arrayType; + /* + https://doxygen.postgresql.org/arrayfuncs_8c.html + ArrayType* construct_array( + Datum* elems, + int nelems, + Oid elmtype, int elmlen, bool elmbyval, char elmalign + ) + */ + arrayType = construct_array(load, (int)load_size, INT8OID, typlen, + typbyval, typalign); + /* + void TupleDescInitEntry( + TupleDesc desc, + AttrNumber attributeNumber, + const char * attributeName, + Oid oidtypeid, + int32 typmod, + int attdim + ) + */ + TupleDescInitEntry(tuple_desc, (AttrNumber) 11, "load", INT8ARRAYOID, -1, 0); + + values[0] = Int64GetDatum(funcctx->call_cntr + 1); + values[1] = Int32GetDatum(result_tuples[call_cntr].vehicle_seq); + values[2] = Int32GetDatum(result_tuples[call_cntr].vehicle_id); + values[3] = Int32GetDatum(result_tuples[call_cntr].step_seq); + values[4] = Int32GetDatum(result_tuples[call_cntr].step_type); + values[5] = Int32GetDatum(result_tuples[call_cntr].task_id); + values[6] = Int32GetDatum(result_tuples[call_cntr].arrival_time); + values[7] = Int32GetDatum(result_tuples[call_cntr].travel_time); + values[8] = Int32GetDatum(result_tuples[call_cntr].service_time); + values[9] = Int32GetDatum(result_tuples[call_cntr].waiting_time); + values[10] = PointerGetDatum(arrayType); + + /**********************************************************************/ + + tuple = heap_form_tuple(tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } else { + SRF_RETURN_DONE(funcctx); + } +} diff --git a/src/vroom/vroom_driver.cpp b/src/vroom/vroom_driver.cpp new file mode 100644 index 000000000..de43d1a3d --- /dev/null +++ b/src/vroom/vroom_driver.cpp @@ -0,0 +1,212 @@ +/*PGR-GNU***************************************************************** +File: vroom_driver.cpp + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#include "drivers/vroom/vroom_driver.h" + +#include +#include +#include +#include +#include + +#include "c_common/pgr_alloc.hpp" +#include "cpp_common/pgr_assert.h" +#include "cpp_common/vrp_vroom_problem.hpp" + +/** @file vroom_driver.cpp + * @brief Handles actual calling of function in the `vrp_vroom.hpp` file. + * + */ + +/** @brief Performs exception handling and converts the results to postgres. + * + * @pre log_msg is empty + * @pre notice_msg is empty + * @pre err_msg is empty + * @pre return_tuples is empty + * @pre return_count is 0 + * + * It converts the C types to the C++ types, and passes these variables to the + * function `vrp_vroom` which calls the main function defined in the + * C++ Header file. It also does exception handling. + * + * @param jobs_sql SQL query describing the jobs + * @param jobs_tw_sql SQL query describing the time window for jobs + * @param shipments_sql SQL query describing the shipments + * @param shipments_tw_sql SQL query describing the time windows for shipment + * @param vehicles_sql SQL query describing the vehicles + * @param breaks_sql SQL query describing the driver breaks. + * @param breaks_tws_sql SQL query describing the time windows for break start. + * @param matrix_sql SQL query describing the cells of the cost matrix + * @param result_tuples the rows in the result + * @param result_count the count of rows in the result + * @param log_msg stores the log message + * @param notice_msg stores the notice message + * @param err_msg stores the error message + * + * @returns void + */ +void +do_vrp_vroom( + Vroom_job_t *jobs, size_t total_jobs, + Vroom_time_window_t *jobs_tws, size_t total_jobs_tws, + Vroom_shipment_t *shipments, size_t total_shipments, + Vroom_time_window_t *shipments_tws, size_t total_shipments_tws, + Vroom_vehicle_t *vehicles, size_t total_vehicles, + Vroom_break_t *breaks, size_t total_breaks, + Vroom_time_window_t *breaks_tws, size_t total_breaks_tws, + Matrix_cell_t *matrix_cells_arr, size_t total_cells, + + Vroom_rt **return_tuples, + size_t *return_count, + + char ** log_msg, + char ** notice_msg, + char ** err_msg) { + std::ostringstream log; + std::ostringstream err; + std::ostringstream notice; + try { + pgassert(!(*log_msg)); + pgassert(!(*notice_msg)); + pgassert(!(*err_msg)); + pgassert(!(*return_tuples)); + pgassert(!(*return_count)); + pgassert(jobs || shipments); + pgassert(vehicles); + pgassert(matrix_cells_arr); + pgassert(total_jobs || total_shipments); + pgassert(total_vehicles); + pgassert(total_cells); + + Identifiers location_ids; + + for (size_t i = 0; i < total_jobs; ++i) { + location_ids += jobs[i].location_index; + } + + for (size_t i = 0; i < total_shipments; ++i) { + location_ids += shipments[i].p_location_index; + location_ids += shipments[i].d_location_index; + } + + for (size_t i = 0; i < total_vehicles; ++i) { + if (vehicles[i].start_index != -1) { + location_ids += vehicles[i].start_index; + } + if (vehicles[i].end_index != -1) { + location_ids += vehicles[i].end_index; + } + } + + vrprouting::base::Base_Matrix time_matrix(matrix_cells_arr, total_cells, location_ids); + + /* + * Verify matrix cells preconditions + */ + if (!time_matrix.has_no_infinity()) { + (*return_tuples) = NULL; + (*return_count) = 0; + err << "An Infinity value was found on the Matrix. Might be missing information of a node"; + *err_msg = pgr_msg(err.str()); + return; + } + + /* + * Verify size of matrix cell lies in the limit + */ + if (time_matrix.size() > (std::numeric_limits::max)()) { + (*return_tuples) = NULL; + (*return_count) = 0; + err << "The size of time matrix exceeds the limit"; + *err_msg = pgr_msg(err.str()); + return; + } + + vrprouting::Vrp_vroom_problem problem; + problem.add_matrix(time_matrix); + problem.add_vehicles(vehicles, total_vehicles, + breaks, total_breaks, + breaks_tws, total_breaks_tws); + problem.add_jobs(jobs, total_jobs, + jobs_tws, total_jobs_tws); + problem.add_shipments(shipments, total_shipments, + shipments_tws, total_shipments_tws); + + std::vector < Vroom_rt > results = problem.solve(); + + auto count = results.size(); + if (count == 0) { + (*return_tuples) = NULL; + (*return_count) = 0; + notice << "No results found"; + *notice_msg = notice.str().empty()? + *notice_msg : + pgr_msg(notice.str().c_str()); + return; + } + + (*return_tuples) = pgr_alloc(count, (*return_tuples)); + for (size_t i = 0; i < count; i++) { + *((*return_tuples) + i) = results[i]; + } + + (*return_count) = count; + + pgassert(*err_msg == NULL); + *log_msg = log.str().empty()? + *log_msg : + pgr_msg(log.str().c_str()); + *notice_msg = notice.str().empty()? + *notice_msg : + pgr_msg(notice.str().c_str()); + } catch (AssertFailedException &except) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << except.what(); + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } catch (const vroom::Exception &except) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << except.message; + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } catch (std::exception &except) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << except.what(); + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } catch(...) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << "Caught unknown exception!"; + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } +} From 2c9171021b8c89f5954bc802c0fba54babd4b1a1 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:23:54 +0530 Subject: [PATCH 07/20] [vroom][src] Added vroom common files, to take input --- src/common/CMakeLists.txt | 6 + src/common/arrays_input.c | 94 +++++++++ src/common/get_check_data.c | 285 +++++++++++++++++++++++--- src/common/matrixRows_input.c | 41 ++++ src/common/orders_input.c | 1 - src/common/vroom/breaks_input.c | 172 ++++++++++++++++ src/common/vroom/jobs_input.c | 229 +++++++++++++++++++++ src/common/vroom/shipments_input.c | 233 +++++++++++++++++++++ src/common/vroom/time_windows_input.c | 238 +++++++++++++++++++++ src/common/vroom/vehicles_input.c | 243 ++++++++++++++++++++++ src/cpp_common/base_matrix.cpp | 85 +++++++- 11 files changed, 1602 insertions(+), 25 deletions(-) create mode 100644 src/common/vroom/breaks_input.c create mode 100644 src/common/vroom/jobs_input.c create mode 100644 src/common/vroom/shipments_input.c create mode 100644 src/common/vroom/time_windows_input.c create mode 100644 src/common/vroom/vehicles_input.c diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index ab99b26f7..010783ab9 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -11,4 +11,10 @@ ADD_LIBRARY(common OBJECT time_msg.c e_report.c pgr_alloc.cpp + + vroom/time_windows_input.c + vroom/breaks_input.c + vroom/jobs_input.c + vroom/shipments_input.c + vroom/vehicles_input.c ) diff --git a/src/common/arrays_input.c b/src/common/arrays_input.c index 8b19adf79..24cbd7aea 100644 --- a/src/common/arrays_input.c +++ b/src/common/arrays_input.c @@ -125,6 +125,95 @@ pgr_get_bigIntArr(ArrayType *v, size_t *arrlen, bool allow_empty) { } +static +uint32_t* +pgr_get_positiveIntArr(ArrayType *v, size_t *arrlen, bool allow_empty) { +#ifdef PROFILE + clock_t start_t = clock(); +#endif + + uint32_t *c_array = NULL; + + Oid element_type = ARR_ELEMTYPE(v); + int *dim = ARR_DIMS(v); + int ndim = ARR_NDIM(v); + int nitems = ArrayGetNItems(ndim, dim); + Datum *elements; + bool *nulls; + int16 typlen; + bool typbyval; + char typalign; + + assert((*arrlen) == 0); + + + if (allow_empty && (ndim == 0 || nitems <= 0)) { + return (uint32_t*) NULL; + } + /* the array is not empty*/ + + if (ndim != 1) { + elog(ERROR, "One dimension expected"); + } + + if (nitems <= 0) { + elog(ERROR, "No elements found"); + } + + get_typlenbyvalalign(element_type, + &typlen, &typbyval, &typalign); + + /* validate input data type */ + switch (element_type) { + case INT2OID: + case INT4OID: + break; + default: + elog(ERROR, "Expected array of INTEGER"); + } + + deconstruct_array(v, element_type, typlen, typbyval, + typalign, &elements, &nulls, + &nitems); + + c_array = (uint32_t *) palloc(sizeof(uint32_t) * (size_t)nitems); + if (!c_array) { + elog(ERROR, "Out of memory!"); + } + + + int i; + for (i = 0; i < nitems; i++) { + if (nulls[i]) { + pfree(c_array); + elog(ERROR, "NULL value found in Array!"); + } else { + int32_t element; + switch (element_type) { + case INT2OID: + element = (int32_t) DatumGetInt16(elements[i]); + break; + case INT4OID: + element = (int32_t) DatumGetInt32(elements[i]); + break; + } + if (element < 0) { + elog(ERROR, "Unexpected Negative value %d in array", element); + } + c_array[i] = (uint32_t) element; + } + } + (*arrlen) = (size_t)nitems; + + pfree(elements); + pfree(nulls); +#ifdef PROFILE + time_msg("reading Array", start_t, clock()); +#endif + return c_array; +} + + int64_t* pgr_get_bigIntArray(size_t *arrlen, ArrayType *input) { return pgr_get_bigIntArr(input, arrlen, false); } @@ -134,3 +223,8 @@ int64_t* pgr_get_bigIntArray(size_t *arrlen, ArrayType *input) { int64_t* pgr_get_bigIntArray_allowEmpty(size_t *arrlen, ArrayType *input) { return pgr_get_bigIntArr(input, arrlen, true); } + + +uint32_t* pgr_get_positiveIntArray_allowEmpty(size_t *arrlen, ArrayType *input) { + return pgr_get_positiveIntArr(input, arrlen, true); +} diff --git a/src/common/get_check_data.c b/src/common/get_check_data.c index 2addec7f6..cacbea651 100644 --- a/src/common/get_check_data.c +++ b/src/common/get_check_data.c @@ -28,8 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include #include "c_common/postgres_connection.h" -#include -#include +#include // NOLINT [build/include_order] +#include // NOLINT [build/include_order] #include "c_common/get_check_data.h" #include "c_common/arrays_input.h" @@ -69,6 +69,16 @@ check_text_type(Column_info_t info) { } } +static +void +check_integer_type(Column_info_t info) { + if (!(info.type == INT2OID || info.type == INT4OID)) { + ereport(ERROR, + (errmsg_internal("Unexpected type in column '%s'.", info.name), + errhint("Expected SMALLINT or INTEGER"))); + } +} + static void check_any_integer_type(Column_info_t info) { @@ -81,6 +91,17 @@ check_any_integer_type(Column_info_t info) { } } +static +void +check_integerarray_type(Column_info_t info) { + if (!(info.type == INT2ARRAYOID + || info.type == INT4ARRAYOID)) { + elog(ERROR, + "Unexpected Column '%s' type. Expected SMALLINT-ARRAY or INTEGER-ARRAY", + info.name); + } +} + static void check_any_integerarray_type(Column_info_t info) { @@ -144,6 +165,31 @@ fetch_column_info( return false; } +static +int32_t +spi_getInt(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { + Datum binval; + bool isnull; + int32_t value = 0; + binval = SPI_getbinval(*tuple, *tupdesc, info.colNumber, &isnull); + + if (isnull) elog(ERROR, "Unexpected Null value in column %s", info.name); + + switch (info.type) { + case INT2OID: + value = (int32_t) DatumGetInt16(binval); + break; + case INT4OID: + value = (int32_t) DatumGetInt32(binval); + break; + default: + ereport(ERROR, + (errmsg_internal("Unexpected type in column '%s'.", info.name), + errhint("Found: %lu\nExpected INTEGER", info.type))); + } + return value; +} + static int64_t spi_getBigInt(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { @@ -197,7 +243,6 @@ spi_getTimeStamp(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { static TInterval spi_getInterval(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { - Datum binval; bool isnull; Interval* interval; @@ -229,7 +274,6 @@ spi_getInterval(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { @param[in] tuple input row to be examined. @param[in] tupdesc input row description. @param[in] info contain column information. - @param[in] strict boolean value of strict. @param[in] default_value returned when column contain NULL value. @throw ERROR Unexpected Column type. Expected column type is CHAR. @@ -244,8 +288,7 @@ spi_getInterval(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { */ char spi_getChar( - HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, - bool strict, char default_value) { + HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, char default_value) { Datum binval; bool isNull; char value = default_value; @@ -257,7 +300,7 @@ spi_getChar( if (!isNull) { value = ((char*)binval)[1]; } else { - if (strict) { + if (info.strict) { elog(ERROR, "Unexpected Null value in column %s", info.name); } value = default_value; @@ -306,11 +349,46 @@ spi_getBigIntArr_allowEmpty( return pgr_get_bigIntArray_allowEmpty(the_size, pg_array); } +int64_t* +spi_getPositiveBigIntArr_allowEmpty( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t info, + size_t *the_size) { + int64_t *array = spi_getBigIntArr_allowEmpty(tuple, tupdesc, info, the_size); + for (size_t i = 0; i < *the_size; i++) { + if (array[i] < 0) { + elog(ERROR, "Unexpected Negative value %ld in array", array[i]); + } + } + return array; +} + + +uint32_t* +spi_getPositiveIntArr_allowEmpty( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t info, + size_t *the_size) { + bool is_null = false; + + Datum raw_array = SPI_getbinval(*tuple, *tupdesc, info.colNumber, &is_null); + if (!raw_array) { + *the_size = 0; + return NULL; + } + + ArrayType *pg_array = DatumGetArrayTypeP(raw_array); + + return pgr_get_positiveIntArray_allowEmpty(the_size, pg_array); +} + /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -326,7 +404,7 @@ get_TTimestamp_plain(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, T /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -345,7 +423,7 @@ get_PositiveTTimestamp_plain(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -361,7 +439,7 @@ get_TTimestamp(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, TTimest /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -380,7 +458,7 @@ get_PositiveTTimestamp(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -396,7 +474,7 @@ get_TInterval(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, TInterva /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -415,7 +493,7 @@ get_PositiveTInterval(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -431,7 +509,7 @@ get_TInterval_plain(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, TI /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -450,7 +528,7 @@ get_PositiveTInterval_plain(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -466,7 +544,48 @@ get_Id(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, Id opt_value) { /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched + * @params [in] opt_value default value when the column does not exist + * + * @returns The value found + * @returns opt_value when the column does not exist + * + * exceptions when the value is negative + * @pre for non-negative values only + */ +Idx +get_Idx(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, Idx opt_value) { + Id value = get_Id(tuple, tupdesc, info, 0); + if (value < 0) elog(ERROR, "Unexpected Negative value in column %s", info.name); + return column_found(info.colNumber)? (Idx) value : opt_value; +} + +/** + * @params [in] tuple + * @params [in] tupdesc + * @params [in] info about the column been fetched + * @params [in] opt_value default value when the column does not exist + * + * @returns The value found + * @returns opt_value when the column does not exist + */ +StepType get_StepType(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, + StepType opt_value) { + StepType step_type = column_found(info.colNumber) + ? spi_getInt(tuple, tupdesc, info) + : opt_value; + StepType min_value = 1; + StepType max_value = 6; + if (step_type < min_value || step_type > max_value) { + elog(ERROR, "Step value should lie between %d and %d", min_value, max_value); + } + return step_type; +} + +/** + * @params [in] tuple + * @params [in] tupdesc + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found @@ -482,14 +601,14 @@ get_Amount(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, Amount opt_ /** * @params [in] tuple * @params [in] tupdesc - * @params [in] info about the colum been fetched + * @params [in] info about the column been fetched * @params [in] opt_value default value when the column does not exist * * @returns The value found * @returns opt_value when the column does not exist * * exceptions when the value is negative - * @pre for positive values only + * @pre for non-negative values only */ PAmount get_PositiveAmount(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, PAmount opt_value) { @@ -499,6 +618,118 @@ get_PositiveAmount(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, PAm } +/** + * @params [in] tuple + * @params [in] tupdesc + * @params [in] info about the column been fetched + * @params [in] opt_value default value when the column does not exist + * + * @returns The value found + * @returns opt_value when the column does not exist + * + * exceptions when the value is negative + * @pre for non-negative values only + */ +MatrixIndex +get_MatrixIndex(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, MatrixIndex opt_value) { + if (column_found(info.colNumber)) { + int64_t value = spi_getBigInt(tuple, tupdesc, info); + if (value < 0) elog(ERROR, "Unexpected Negative value in column %s", info.name); + return (MatrixIndex) value; + } + return opt_value; +} + + +/** + * @params [in] tuple + * @params [in] tupdesc + * @params [in] info about the column been fetched + * @params [in] opt_value default value when the column does not exist + * + * @returns The value found + * @returns opt_value when the column does not exist + * + * exceptions when the value is negative + * @pre for non-negative values only + */ +Duration +get_Duration(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, Duration opt_value) { + if (column_found(info.colNumber)) { + int32_t value = spi_getInt(tuple, tupdesc, info); + if (value < 0) elog(ERROR, "Unexpected Negative value in column %s", info.name); + return (Duration) value; + } + return opt_value; +} + +/** + * @params [in] tuple + * @params [in] tupdesc + * @params [in] info about the column been fetched + * @params [in] opt_value default value when the column does not exist + * + * @returns The value found + * @returns opt_value when the column does not exist + * + */ +char +get_Kind(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, char opt_value) { + if (column_found(info.colNumber)) { + char value = spi_getChar(tuple, tupdesc, info, opt_value); + return value; + } + return opt_value; +} + + +/** + * @params [in] tuple + * @params [in] tupdesc + * @params [in] info about the column been fetched + * @params [in] opt_value default value when the column does not exist + * + * @returns The value found + * @returns opt_value when the column does not exist + * + * exceptions when the value is negative + * @pre for non-negative values only + */ +Priority +get_Priority(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, Priority opt_value) { + if (column_found(info.colNumber)) { + int32_t value = spi_getInt(tuple, tupdesc, info); + if (value < 0) elog(ERROR, "Unexpected Negative value in column %s", info.name); + if (value > 100) elog(ERROR, "Priority exceeds the max priority 100"); + return (Priority) value; + } + return opt_value; +} + + +/** + * @params [in] tuple + * @params [in] tupdesc + * @params [in] info about the column been fetched + * @params [in] opt_value default value when the column does not exist + * + * @returns The value found + * @returns opt_value when the column does not exist + * + * exceptions when the value is negative + * @pre for non-negative values only + */ +Distance +get_Distance(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, Distance opt_value) { + if (column_found(info.colNumber)) { + int32_t value = spi_getInt(tuple, tupdesc, info); + if (value < 0) elog(ERROR, "Unexpected Negative value in column %s", info.name); + return (Distance) value; + } + return opt_value; +} + + double spi_getFloat8(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { Datum binval; @@ -550,8 +781,12 @@ spi_getCoordinate(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, Coor * [DatumGetCString](https://doxygen.postgresql.org/postgres_8h.html#ae401c8476d1a12b420e3061823a206a7) */ char* -pgr_SPI_getText(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { - return DatumGetCString(SPI_getvalue(*tuple, *tupdesc, info.colNumber)); +spi_getText(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) { + char *val = DatumGetCString(SPI_getvalue(*tuple, *tupdesc, info.colNumber)); + if (!val) { + elog(ERROR, "Unexpected Null value in column %s", info.name); + } + return val; } /** @@ -628,6 +863,9 @@ void pgr_fetch_column_info( for (int i = 0; i < info_size; ++i) { if (fetch_column_info(&info[i])) { switch (info[i].eType) { + case INTEGER: + check_integer_type(info[i]); + break; case ANY_INTEGER: check_any_integer_type(info[i]); break; @@ -640,6 +878,9 @@ void pgr_fetch_column_info( case CHAR1: check_char_type(info[i]); break; + case INTEGER_ARRAY: + check_integerarray_type(info[i]); + break; case ANY_INTEGER_ARRAY: check_any_integerarray_type(info[i]); break; @@ -655,5 +896,3 @@ void pgr_fetch_column_info( } } } - - diff --git a/src/common/matrixRows_input.c b/src/common/matrixRows_input.c index eeddb91f9..5e9fe8f86 100644 --- a/src/common/matrixRows_input.c +++ b/src/common/matrixRows_input.c @@ -56,6 +56,24 @@ Column Type Description .. pgr_pickDeliver end +.. vrp_vroom start + +A ``SELECT`` statement that returns the following columns: + +:: + + start_vid, end_vid, agg_cost + +=============== ================= ================================================== +Column Type Description +=============== ================= ================================================== +**start_vid** ``ANY-INTEGER`` Identifier of the start node. +**end_vid** ``ANY-INTEGER`` Identifier of the end node. +**agg_cost** ``INTEGER`` Time to travel from ``start_vid`` to ``end_vid`` +=============== ================= ================================================== + +.. vrp_vroom end + */ static @@ -220,3 +238,26 @@ get_matrixRows_plain( info[2].eType = ANY_NUMERICAL; get_matrixRows_general(sql, info, 1, rows, total_rows); } + +/** + * @param [in] sql SQL query that has the following columns: start_vid, end_vid, agg_cost + * @param [out] rows C Container that holds all the matrix rows + * @param [out] total_rows Total rows recieved + */ +void get_matrixRows_vroom_plain(char *sql, Matrix_cell_t **rows, size_t *total_rows) { + Column_info_t info[3]; + + int i; + for (i = 0; i < 3; ++i) { + info[i].colNumber = -1; + info[i].type = 0; + info[i].strict = true; + info[i].eType = ANY_INTEGER; + } + info[0].name = "start_vid"; + info[1].name = "end_vid"; + info[2].name = "agg_cost"; + + info[2].eType = INTEGER; + get_matrixRows_general(sql, info, 1, rows, total_rows); +} diff --git a/src/common/orders_input.c b/src/common/orders_input.c index 93112ea9f..5c10d553c 100644 --- a/src/common/orders_input.c +++ b/src/common/orders_input.c @@ -34,7 +34,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "c_common/get_check_data.h" #ifdef PROFILE #include "c_common/time_msg.h" -#include "c_common/debug_macro.h" #endif diff --git a/src/common/vroom/breaks_input.c b/src/common/vroom/breaks_input.c new file mode 100644 index 000000000..801e9deb1 --- /dev/null +++ b/src/common/vroom/breaks_input.c @@ -0,0 +1,172 @@ +/*PGR-GNU***************************************************************** +File: breaks_input.c + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#include "c_common/vroom/breaks_input.h" + +/* +.. vrp_vroom start + +A ``SELECT`` statement that returns the following columns: + +:: + + id, vehicle_id [, service] + +==================== ========================= =========== ================================================ +Column Type Default Description +==================== ========================= =========== ================================================ +**id** ``ANY-INTEGER`` Non-negative unique identifier of the break. + (unique for the same vehicle). + +**vehicle_id** ``ANY-INTEGER`` Non-negative unique identifier of the vehicle. + +**service** ``INTEGER`` 0 The break duration, in seconds +==================== ========================= =========== ================================================ + +.. vrp_vroom end +*/ + +static +void fetch_breaks( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t *info, + Vroom_break_t *vroom_break) { + vroom_break->id = get_Idx(tuple, tupdesc, info[0], 0); + vroom_break->vehicle_id = get_Idx(tuple, tupdesc, info[1], 0); + vroom_break->service = get_Duration(tuple, tupdesc, info[2], 0); +} + + +static +void db_get_breaks( + char *breaks_sql, + Vroom_break_t **breaks, + size_t *total_breaks, + + Column_info_t *info, + const int column_count) { +#ifdef PROFILE + clock_t start_t = clock(); + PGR_DBG("%s", breaks_sql); +#endif + + const int tuple_limit = 1000000; + + size_t total_tuples; + + void *SPIplan; + SPIplan = pgr_SPI_prepare(breaks_sql); + Portal SPIportal; + SPIportal = pgr_SPI_cursor_open(SPIplan); + + bool moredata = true; + (*total_breaks) = total_tuples = 0; + + /* on the first tuple get the column numbers */ + + while (moredata == true) { + SPI_cursor_fetch(SPIportal, true, tuple_limit); + if (total_tuples == 0) { + pgr_fetch_column_info(info, column_count); + } + size_t ntuples = SPI_processed; + total_tuples += ntuples; + if (ntuples > 0) { + if ((*breaks) == NULL) + (*breaks) = (Vroom_break_t *)palloc0( + total_tuples * sizeof(Vroom_break_t)); + else + (*breaks) = (Vroom_break_t *)repalloc( + (*breaks), + total_tuples * sizeof(Vroom_break_t)); + + if ((*breaks) == NULL) { + elog(ERROR, "Out of memory"); + } + + size_t t; + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = SPI_tuptable->tupdesc; + for (t = 0; t < ntuples; t++) { + HeapTuple tuple = tuptable->vals[t]; + fetch_breaks(&tuple, &tupdesc, info, + &(*breaks)[total_tuples - ntuples + t]); + } + SPI_freetuptable(tuptable); + } else { + moredata = false; + } + } + + SPI_cursor_close(SPIportal); + + if (total_tuples == 0) { + (*total_breaks) = 0; + return; + } + + (*total_breaks) = total_tuples; +#ifdef PROFILE + time_msg("reading breaks", start_t, clock()); +#endif +} + + + +/** + * @param[in] sql SQL query to execute + * @param[out] rows C Container that holds the data + * @param[out] total_rows Total rows recieved + */ +void +get_vroom_breaks( + char *sql, + Vroom_break_t **rows, + size_t *total_rows) { + int kColumnCount = 3; + Column_info_t info[kColumnCount]; + + for (int i = 0; i < kColumnCount; ++i) { + info[i].colNumber = -1; + info[i].type = 0; + info[i].strict = true; + info[i].eType = ANY_INTEGER; + } + + info[0].name = "id"; + info[1].name = "vehicle_id"; + info[2].name = "service"; + + info[2].eType = INTEGER; // service + + /* service is not mandatory */ + info[2].strict = false; + + db_get_breaks(sql, rows, total_rows, info, kColumnCount); +} diff --git a/src/common/vroom/jobs_input.c b/src/common/vroom/jobs_input.c new file mode 100644 index 000000000..332e28e00 --- /dev/null +++ b/src/common/vroom/jobs_input.c @@ -0,0 +1,229 @@ +/*PGR-GNU***************************************************************** +File: jobs_input.c + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#include "c_common/vroom/jobs_input.h" + +/* +.. vrp_vroom start + +A ``SELECT`` statement that returns the following columns: + +:: + + id, location_index + [, service, delivery, pickup, skills, priority] + + +==================== ========================= =========== ================================================ +Column Type Default Description +==================== ========================= =========== ================================================ +**id** ``ANY-INTEGER`` Non-negative unique identifier of the job. + +**location_index** ``ANY-INTEGER`` Non-negative identifier of the job location. + +**service** ``INTEGER`` 0 Job service duration, in seconds + +**delivery** ``ARRAY[ANY-INTEGER]`` Array of non-negative integers describing + multidimensional quantities for delivery such + as number of items, weight, volume etc. + + - All jobs must have the same value of + :code:`array_length(delivery, 1)` + +**pickup** ``ARRAY[ANY-INTEGER]`` Array of non-negative integers describing + multidimensional quantities for pickup such as + number of items, weight, volume etc. + + - All jobs must have the same value of + :code:`array_length(pickup, 1)` + +**skills** ``ARRAY[INTEGER]`` Array of non-negative integers defining + mandatory skills. + +**priority** ``INTEGER`` 0 Priority level of the job + + - Ranges from ``[0, 100]`` +==================== ========================= =========== ================================================ + +Where: + +:ANY-INTEGER: SMALLINT, INTEGER, BIGINT + +.. vrp_vroom end +*/ + +static +void fetch_jobs( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t *info, + Vroom_job_t *job) { + job->id = get_Idx(tuple, tupdesc, info[0], 0); + job->location_index = get_MatrixIndex(tuple, tupdesc, info[1], 0); + job->service = get_Duration(tuple, tupdesc, info[2], 0); + + /* + * The deliveries + */ + job->delivery_size = 0; + job->delivery = column_found(info[3].colNumber) ? + spi_getPositiveBigIntArr_allowEmpty(tuple, tupdesc, info[3], &job->delivery_size) + : NULL; + + /* + * The pickups + */ + job->pickup_size = 0; + job->pickup = column_found(info[4].colNumber) ? + spi_getPositiveBigIntArr_allowEmpty(tuple, tupdesc, info[4], &job->pickup_size) + : NULL; + + job->skills_size = 0; + job->skills = column_found(info[5].colNumber) ? + spi_getPositiveIntArr_allowEmpty(tuple, tupdesc, info[5], &job->skills_size) + : NULL; + + job->priority = get_Priority(tuple, tupdesc, info[6], 0); +} + + +static +void db_get_jobs( + char *jobs_sql, + Vroom_job_t **jobs, + size_t *total_jobs, + + Column_info_t *info, + const int column_count) { +#ifdef PROFILE + clock_t start_t = clock(); + PGR_DBG("%s", jobs_sql); +#endif + + const int tuple_limit = 1000000; + + size_t total_tuples; + + void *SPIplan; + SPIplan = pgr_SPI_prepare(jobs_sql); + Portal SPIportal; + SPIportal = pgr_SPI_cursor_open(SPIplan); + + bool moredata = true; + (*total_jobs) = total_tuples = 0; + + /* on the first tuple get the column numbers */ + + while (moredata == true) { + SPI_cursor_fetch(SPIportal, true, tuple_limit); + if (total_tuples == 0) { + pgr_fetch_column_info(info, column_count); + } + size_t ntuples = SPI_processed; + total_tuples += ntuples; + if (ntuples > 0) { + if ((*jobs) == NULL) + (*jobs) = (Vroom_job_t *)palloc0( + total_tuples * sizeof(Vroom_job_t)); + else + (*jobs) = (Vroom_job_t *)repalloc( + (*jobs), + total_tuples * sizeof(Vroom_job_t)); + + if ((*jobs) == NULL) { + elog(ERROR, "Out of memory"); + } + + size_t t; + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = SPI_tuptable->tupdesc; + for (t = 0; t < ntuples; t++) { + HeapTuple tuple = tuptable->vals[t]; + fetch_jobs(&tuple, &tupdesc, info, + &(*jobs)[total_tuples - ntuples + t]); + } + SPI_freetuptable(tuptable); + } else { + moredata = false; + } + } + + SPI_cursor_close(SPIportal); + + if (total_tuples == 0) { + (*total_jobs) = 0; + return; + } + + (*total_jobs) = total_tuples; +#ifdef PROFILE + time_msg("reading jobs", start_t, clock()); +#endif +} + + +/** + * @param[in] sql SQL query to execute + * @param[out] rows C Container that holds the data + * @param[out] total_rows Total rows recieved + */ +void +get_vroom_jobs( + char *sql, + Vroom_job_t **rows, + size_t *total_rows) { + int kColumnCount = 7; + Column_info_t info[kColumnCount]; + + for (int i = 0; i < kColumnCount; ++i) { + info[i].colNumber = -1; + info[i].type = 0; + info[i].strict = false; + info[i].eType = ANY_INTEGER; + } + + info[0].name = "id"; + info[1].name = "location_index"; + info[2].name = "service"; + info[3].name = "delivery"; + info[4].name = "pickup"; + info[5].name = "skills"; + info[6].name = "priority"; + + info[2].eType = INTEGER; // service + info[3].eType = ANY_INTEGER_ARRAY; // delivery + info[4].eType = ANY_INTEGER_ARRAY; // pickup + info[5].eType = INTEGER_ARRAY; // skills + info[6].eType = INTEGER; // priority + + /* Only id and location_index are mandatory */ + info[0].strict = true; + info[1].strict = true; + + db_get_jobs(sql, rows, total_rows, info, kColumnCount); +} diff --git a/src/common/vroom/shipments_input.c b/src/common/vroom/shipments_input.c new file mode 100644 index 000000000..864b4dc71 --- /dev/null +++ b/src/common/vroom/shipments_input.c @@ -0,0 +1,233 @@ +/*PGR-GNU***************************************************************** +File: shipments_input.c + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#include "c_common/vroom/shipments_input.h" + +/* +.. vrp_vroom start + +A ``SELECT`` statement that returns the following columns: + +:: + + id, p_location_index [, p_service], d_location_index [, d_service] + [, amount, skills, priority] + + +====================== ========================= =========== ================================================ +Column Type Default Description +====================== ========================= =========== ================================================ +**id** ``ANY-INTEGER`` Non-negative unique identifier of the shipment. + +**p_location_index** ``ANY-INTEGER`` Non-negative identifier of the pickup location. + +**p_service** ``INTEGER`` 0 Pickup service duration, in seconds + +**d_location_index** ``ANY-INTEGER`` Non-negative identifier of the delivery location. + +**d_service** ``INTEGER`` 0 Delivery service duration, in seconds + +**amount** ``ARRAY[ANY-INTEGER]`` Array of non-negative integers describing + multidimensional quantities such as number + of items, weight, volume etc. + + - All shipments must have the same value of + :code:`array_length(amount, 1)` + +**skills** ``ARRAY[INTEGER]`` Array of non-negative integers defining + mandatory skills. + +**priority** ``INTEGER`` 0 Priority level of the shipment. + + - Ranges from ``[0, 100]`` + +====================== ========================= =========== ================================================ + +Where: + +:ANY-INTEGER: SMALLINT, INTEGER, BIGINT + +.. vrp_vroom end +*/ + +static +void fetch_shipments( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t *info, + Vroom_shipment_t *shipment) { + shipment->id = get_Idx(tuple, tupdesc, info[0], 0); + + /* + * The pickups + */ + shipment->p_location_index = get_MatrixIndex(tuple, tupdesc, info[1], 0); + shipment->p_service = get_Duration(tuple, tupdesc, info[2], 0); + + /* + * The deliveries + */ + shipment->d_location_index = get_MatrixIndex(tuple, tupdesc, info[3], 0); + shipment->d_service = get_Duration(tuple, tupdesc, info[4], 0); + + shipment->amount_size = 0; + shipment->amount = column_found(info[5].colNumber) ? + spi_getPositiveBigIntArr_allowEmpty(tuple, tupdesc, info[5], &shipment->amount_size) + : NULL; + + shipment->skills_size = 0; + shipment->skills = column_found(info[6].colNumber) ? + spi_getPositiveIntArr_allowEmpty(tuple, tupdesc, info[6], &shipment->skills_size) + : NULL; + + shipment->priority = get_Priority(tuple, tupdesc, info[7], 0); +} + + +static +void db_get_shipments( + char *shipments_sql, + Vroom_shipment_t **shipments, + size_t *total_shipments, + + Column_info_t *info, + const int column_count) { +#ifdef PROFILE + clock_t start_t = clock(); + PGR_DBG("%s", shipments_sql); +#endif + + const int tuple_limit = 1000000; + + size_t total_tuples; + + void *SPIplan; + SPIplan = pgr_SPI_prepare(shipments_sql); + Portal SPIportal; + SPIportal = pgr_SPI_cursor_open(SPIplan); + + bool moredata = true; + (*total_shipments) = total_tuples = 0; + + /* on the first tuple get the column numbers */ + + while (moredata == true) { + SPI_cursor_fetch(SPIportal, true, tuple_limit); + if (total_tuples == 0) { + pgr_fetch_column_info(info, column_count); + } + size_t ntuples = SPI_processed; + total_tuples += ntuples; + if (ntuples > 0) { + if ((*shipments) == NULL) + (*shipments) = (Vroom_shipment_t *)palloc0( + total_tuples * sizeof(Vroom_shipment_t)); + else + (*shipments) = (Vroom_shipment_t *)repalloc( + (*shipments), + total_tuples * sizeof(Vroom_shipment_t)); + + if ((*shipments) == NULL) { + elog(ERROR, "Out of memory"); + } + + size_t t; + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = SPI_tuptable->tupdesc; + for (t = 0; t < ntuples; t++) { + HeapTuple tuple = tuptable->vals[t]; + fetch_shipments(&tuple, &tupdesc, info, + &(*shipments)[total_tuples - ntuples + t]); + } + SPI_freetuptable(tuptable); + } else { + moredata = false; + } + } + + SPI_cursor_close(SPIportal); + + if (total_tuples == 0) { + (*total_shipments) = 0; + return; + } + + (*total_shipments) = total_tuples; +#ifdef PROFILE + time_msg("reading shipments", start_t, clock()); +#endif +} + + +/** + * @param[in] sql SQL query to execute + * @param[out] rows C Container that holds the data + * @param[out] total_rows Total rows recieved + */ +void +get_vroom_shipments( + char *sql, + Vroom_shipment_t **rows, + size_t *total_rows) { + int kColumnCount = 8; + Column_info_t info[kColumnCount]; + + for (int i = 0; i < kColumnCount; ++i) { + info[i].colNumber = -1; + info[i].type = 0; + info[i].strict = false; + info[i].eType = ANY_INTEGER; + } + + info[0].name = "id"; + + /* pickup shipments */ + info[1].name = "p_location_index"; + info[2].name = "p_service"; + + /* delivery shipments */ + info[3].name = "d_location_index"; + info[4].name = "d_service"; + + info[5].name = "amount"; + info[6].name = "skills"; + info[7].name = "priority"; + + info[2].eType = INTEGER; // p_service + info[4].eType = INTEGER; // d_service + info[5].eType = ANY_INTEGER_ARRAY; // amount + info[6].eType = INTEGER_ARRAY; // skills + info[7].eType = INTEGER; // priority + + /* id and location_index of pickup and delivery are mandatory */ + info[0].strict = true; + info[1].strict = true; + info[3].strict = true; + + db_get_shipments(sql, rows, total_rows, info, kColumnCount); +} diff --git a/src/common/vroom/time_windows_input.c b/src/common/vroom/time_windows_input.c new file mode 100644 index 000000000..b45979317 --- /dev/null +++ b/src/common/vroom/time_windows_input.c @@ -0,0 +1,238 @@ +/*PGR-GNU***************************************************************** +File: time_windows_input.c + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#include "c_common/vroom/time_windows_input.h" + +/* +.. vrp_vroom start + +A ``SELECT`` statement that returns the following columns: + +:: + + id [, kind], tw_open, tw_close + +==================== ====================================== ===================================================== +Column Type Description +==================== ====================================== ===================================================== +**id** ``ANY-INTEGER`` Non-negative unique identifier of the job, + pickup/delivery shipment, or break. + +**kind** ``CHAR`` **Only required for shipments**. Value in ['p', 'd'] + indicating whether the time window is for: + + - Pickup shipment, or + - Delivery shipment. + +**tw_open** ``INTEGER`` Time window opening time. + +**tw_close** ``INTEGER`` Time window closing time. +==================== ====================================== ===================================================== + +**Note**: + +- All timing are in seconds. +- Every row must satisfy the condition: :code:`tw_open ≤ tw_close`. +- It is up to users to decide how to describe time windows: + + - **Relative values**, e.g. [0, 14400] for a 4 hours time window starting at the beginning of the planning horizon. In that case all times reported in output with the arrival column are relative to the start of the planning horizon. + - **Absolute values**, "real" timestamps. In that case all times reported in output with the arrival column can be interpreted as timestamps. + +.. vrp_vroom end +*/ + +static +void fetch_time_windows( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t *info, + Vroom_time_window_t *time_window, + bool is_shipment) { + + time_window->id = get_Idx(tuple, tupdesc, info[0], 0); + + if (is_shipment) { + char kind = get_Kind(tuple, tupdesc, info[1], ' '); + if (kind != 'p' && kind != 'd') { + ereport(ERROR, (errmsg("Invalid kind %c", kind), + errhint("Kind must be either 'p' or 'd'"))); + } + time_window->kind = kind; + time_window->start_time = get_Duration(tuple, tupdesc, info[2], 0); + time_window->end_time = get_Duration(tuple, tupdesc, info[3], 0); + } else { + time_window->start_time = get_Duration(tuple, tupdesc, info[1], 0); + time_window->end_time = get_Duration(tuple, tupdesc, info[2], 0); + } + + if (time_window->start_time > time_window->end_time) { + ereport(ERROR, + (errmsg("Invalid time window (%d, %d)", + time_window->start_time, time_window->end_time), + errhint("Time window start time %d must be " + "less than or equal to time window end time %d", + time_window->start_time, time_window->end_time))); + } +} + + +static +void db_get_time_windows( + char *time_windows_sql, + Vroom_time_window_t **time_windows, + size_t *total_time_windows, + + Column_info_t *info, + const int column_count, + bool is_shipment) { +#ifdef PROFILE + clock_t start_t = clock(); + PGR_DBG("%s", time_windows_sql); +#endif + + const int tuple_limit = 1000000; + + size_t total_tuples; + + void *SPIplan; + SPIplan = pgr_SPI_prepare(time_windows_sql); + Portal SPIportal; + SPIportal = pgr_SPI_cursor_open(SPIplan); + + bool moredata = true; + (*total_time_windows) = total_tuples = 0; + + /* on the first tuple get the column numbers */ + + while (moredata == true) { + SPI_cursor_fetch(SPIportal, true, tuple_limit); + if (total_tuples == 0) { + pgr_fetch_column_info(info, column_count); + } + size_t ntuples = SPI_processed; + total_tuples += ntuples; + if (ntuples > 0) { + if ((*time_windows) == NULL) + (*time_windows) = (Vroom_time_window_t *)palloc0( + total_tuples * sizeof(Vroom_time_window_t)); + else + (*time_windows) = (Vroom_time_window_t *)repalloc( + (*time_windows), + total_tuples * sizeof(Vroom_time_window_t)); + + if ((*time_windows) == NULL) { + elog(ERROR, "Out of memory"); + } + + size_t t; + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = SPI_tuptable->tupdesc; + for (t = 0; t < ntuples; t++) { + HeapTuple tuple = tuptable->vals[t]; + fetch_time_windows(&tuple, &tupdesc, info, + &(*time_windows)[total_tuples - ntuples + t], is_shipment); + } + SPI_freetuptable(tuptable); + } else { + moredata = false; + } + } + + SPI_cursor_close(SPIportal); + + if (total_tuples == 0) { + (*total_time_windows) = 0; + return; + } + + (*total_time_windows) = total_tuples; +#ifdef PROFILE + time_msg("reading time windows", start_t, clock()); +#endif +} + + +/** + * @param[in] sql SQL query to execute + * @param[out] rows C Container that holds the data + * @param[out] total_rows Total rows recieved + */ +void +get_vroom_time_windows( + char *sql, + Vroom_time_window_t **rows, + size_t *total_rows) { + int kColumnCount = 3; + Column_info_t info[kColumnCount]; + + for (int i = 0; i < kColumnCount; ++i) { + info[i].colNumber = -1; + info[i].type = 0; + info[i].strict = true; + info[i].eType = INTEGER; + } + + info[0].name = "id"; + info[1].name = "tw_open"; + info[2].name = "tw_close"; + + info[0].eType = ANY_INTEGER; // id + + db_get_time_windows(sql, rows, total_rows, info, kColumnCount, 0); +} + +/** + * @param[in] sql SQL query to execute + * @param[out] rows C Container that holds the data + * @param[out] total_rows Total rows recieved + */ +void +get_vroom_shipments_time_windows( + char *sql, + Vroom_time_window_t **rows, + size_t *total_rows) { + int kColumnCount = 4; + Column_info_t info[kColumnCount]; + + for (int i = 0; i < kColumnCount; ++i) { + info[i].colNumber = -1; + info[i].type = 0; + info[i].strict = true; + info[i].eType = INTEGER; + } + + info[0].name = "id"; + info[1].name = "kind"; + info[2].name = "tw_open"; + info[3].name = "tw_close"; + + info[0].eType = ANY_INTEGER; // id + info[1].eType = CHAR1; // kind + + db_get_time_windows(sql, rows, total_rows, info, kColumnCount, 1); +} diff --git a/src/common/vroom/vehicles_input.c b/src/common/vroom/vehicles_input.c new file mode 100644 index 000000000..73fd69dc5 --- /dev/null +++ b/src/common/vroom/vehicles_input.c @@ -0,0 +1,243 @@ +/*PGR-GNU***************************************************************** +File: vehicles_input.c + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#include "c_common/vroom/vehicles_input.h" + +/* +.. vrp_vroom start + +A ``SELECT`` statement that returns the following columns: + +:: + + id, start_index, end_index + [, capacity, skills, tw_open, tw_close, speed_factor] + + +====================== ================================= ================================================ +Column Type Description +====================== ================================= ================================================ +**id** ``ANY-INTEGER`` Non-negative unique identifier of the job. + +**start_index** ``ANY-INTEGER`` Non-negative identifier of the vehicle start location. + +**end_index** ``ANY-INTEGER`` Non-negative identifier of the vehicle end location. + +**capacity** ``ARRAY[ANY-INTEGER]`` Array of non-negative integers describing + multidimensional quantities such as + number of items, weight, volume etc. + + - All vehicles must have the same value of + :code:`array_length(capacity, 1)` + +**skills** ``ARRAY[INTEGER]`` Array of non-negative integers defining + mandatory skills. + +**tw_open** ``INTEGER`` Time window opening time. + +**tw_close** ``INTEGER`` Time window closing time. + +**speed_factor** ``ANY-NUMERICAL`` Vehicle travel time multiplier. +====================== ================================= ================================================ + +**Note**: + +- At least one of the ``start_index`` or ``end_index`` shall be present. +- If ``end_index`` is omitted, the resulting route will stop at the last visited task, whose choice is determined by the optimization process. +- If ``start_index`` is omitted, the resulting route will start at the first visited task, whose choice is determined by the optimization process. +- To request a round trip, specify both ``start_index`` and ``end_index`` as the same index. +- A vehicle is only allowed to serve a set of tasks if the resulting load at each route step is lower than the matching value in capacity for each metric. When using multiple components for amounts, it is recommended to put the most important/limiting metrics first. +- It is assumed that all delivery-related amounts for jobs are loaded at vehicle start, while all pickup-related amounts for jobs are brought back at vehicle end. +- :code:`tw_open ≤ tw_close` + +.. vrp_vroom end +*/ + +static +void fetch_vehicles( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t *info, + Vroom_vehicle_t *vehicle) { + vehicle->id = get_Idx(tuple, tupdesc, info[0], 0); + vehicle->start_index = get_MatrixIndex(tuple, tupdesc, info[1], -1); + vehicle->end_index = get_MatrixIndex(tuple, tupdesc, info[2], -1); + + vehicle->capacity_size = 0; + vehicle->capacity = column_found(info[3].colNumber) ? + spi_getPositiveBigIntArr_allowEmpty(tuple, tupdesc, info[3], &vehicle->capacity_size) + : NULL; + + vehicle->skills_size = 0; + vehicle->skills = column_found(info[4].colNumber) ? + spi_getPositiveIntArr_allowEmpty(tuple, tupdesc, info[4], &vehicle->skills_size) + : NULL; + + vehicle->time_window_start = get_Duration(tuple, tupdesc, info[5], 0); + vehicle->time_window_end = get_Duration(tuple, tupdesc, info[6], UINT_MAX); + + if (vehicle->time_window_start > vehicle->time_window_end) { + ereport(ERROR, + (errmsg("Invalid time window (%d, %d)", + vehicle->time_window_start, vehicle->time_window_end), + errhint("Time window start time %d must be " + "less than or equal to time window end time %d", + vehicle->time_window_start, vehicle->time_window_end))); + } + + vehicle->speed_factor = column_found(info[7].colNumber) ? + spi_getFloat8(tuple, tupdesc, info[7]) + : 1.0; +} + + +static +void db_get_vehicles( + char *vehicles_sql, + Vroom_vehicle_t **vehicles, + size_t *total_vehicles, + + Column_info_t *info, + const int column_count) { +#ifdef PROFILE + clock_t start_t = clock(); + PGR_DBG("%s", vehicles_sql); +#endif + + const int tuple_limit = 1000000; + + size_t total_tuples; + + void *SPIplan; + SPIplan = pgr_SPI_prepare(vehicles_sql); + Portal SPIportal; + SPIportal = pgr_SPI_cursor_open(SPIplan); + + bool moredata = true; + (*total_vehicles) = total_tuples = 0; + + /* on the first tuple get the column numbers */ + + while (moredata == true) { + SPI_cursor_fetch(SPIportal, true, tuple_limit); + if (total_tuples == 0) { + /* Atleast one out of start_index or end_index must be present */ + info[1].colNumber = SPI_fnumber(SPI_tuptable->tupdesc, "start_index"); + info[2].colNumber = SPI_fnumber(SPI_tuptable->tupdesc, "end_index"); + if (!column_found(info[1].colNumber) && !column_found(info[2].colNumber)) { + elog(ERROR, "At least one out of start_index or end_index must be present"); + } + pgr_fetch_column_info(info, column_count); + } + size_t ntuples = SPI_processed; + total_tuples += ntuples; + if (ntuples > 0) { + if ((*vehicles) == NULL) + (*vehicles) = (Vroom_vehicle_t *)palloc0( + total_tuples * sizeof(Vroom_vehicle_t)); + else + (*vehicles) = (Vroom_vehicle_t *)repalloc( + (*vehicles), + total_tuples * sizeof(Vroom_vehicle_t)); + + if ((*vehicles) == NULL) { + elog(ERROR, "Out of memory"); + } + + size_t t; + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = SPI_tuptable->tupdesc; + for (t = 0; t < ntuples; t++) { + HeapTuple tuple = tuptable->vals[t]; + fetch_vehicles(&tuple, &tupdesc, info, + &(*vehicles)[total_tuples - ntuples + t]); + } + SPI_freetuptable(tuptable); + } else { + moredata = false; + } + } + + SPI_cursor_close(SPIportal); + + if (total_tuples == 0) { + (*total_vehicles) = 0; + return; + } + + (*total_vehicles) = total_tuples; +#ifdef PROFILE + time_msg("reading vehicles", start_t, clock()); +#endif +} + + +/** + * @param[in] sql SQL query to execute + * @param[out] rows C Container that holds the data + * @param[out] total_rows Total rows recieved + */ +void +get_vroom_vehicles( + char *sql, + Vroom_vehicle_t **rows, + size_t *total_rows) { + int kColumnCount = 8; + Column_info_t info[kColumnCount]; + + for (int i = 0; i < kColumnCount; ++i) { + info[i].colNumber = -1; + info[i].type = 0; + info[i].strict = false; + info[i].eType = ANY_INTEGER; + } + + info[0].name = "id"; + info[1].name = "start_index"; + info[2].name = "end_index"; + info[3].name = "capacity"; + info[4].name = "skills"; + info[5].name = "tw_open"; + info[6].name = "tw_close"; + info[7].name = "speed_factor"; + + info[3].eType = ANY_INTEGER_ARRAY; // capacity + info[4].eType = INTEGER_ARRAY; // skills + info[5].eType = INTEGER; // tw_open + info[6].eType = INTEGER; // tw_close + + info[7].eType = ANY_NUMERICAL; // speed_factor + + /** + * id is mandatory. + * At least one out of start_index or end_index must be present, but that is checked later. + */ + info[0].strict = true; + + db_get_vehicles(sql, rows, total_rows, info, kColumnCount); +} diff --git a/src/cpp_common/base_matrix.cpp b/src/cpp_common/base_matrix.cpp index b1f468c35..fd2ae1d70 100644 --- a/src/cpp_common/base_matrix.cpp +++ b/src/cpp_common/base_matrix.cpp @@ -245,6 +245,74 @@ Base_Matrix::Base_Matrix( } } +/** + * @brief Constructor for VROOM matrix input + * + * @param [in] data_costs The set of costs + * @param [in] size_matrix The size of the set of costs + * @param [in] location_ids The location identifiers + * + * @pre data_costs is not empty + * @post ids has all the ids of node_ids + * @post data_costs[from_vid, to_vid] is ignored when from_vid is not in node_ids or to_vid is not in node_ids + * @post costs[from_vid, to_vid] is not has the cell cost when from_vid, to_vid are in node_ids + * @post costs[from_vid, to_vid] = inf when cell from_vid, to_vid does not exist + * @post costs[from_vid, to_vid] = 0 when from_vid = to_vid + * + */ +Base_Matrix::Base_Matrix(Matrix_cell_t *data_costs, size_t size_matrix, + const Identifiers &location_ids) { + /* + * Sets the selected nodes identifiers + */ + m_ids.insert(m_ids.begin(), location_ids.begin(), location_ids.end()); + + /* + * Create matrix + */ + m_time_matrix.resize( + m_ids.size(), + std::vector(m_ids.size(), + /* + * Set initial values to infinity + */ + (std::numeric_limits::max)())); + + Identifiers inserted; + /* + * Cycle the matrix data + */ + for (size_t i = 0; i < size_matrix; ++i) { + auto data = data_costs[i]; + /* + * skip if row is not from selected nodes + */ + if (!(has_id(data.from_vid) && has_id(data.to_vid))) continue; + + /* + * Save the information + */ + m_time_matrix[get_index(data.from_vid)][get_index(data.to_vid)] = + static_cast(data.cost); + + /* + * If the opposite direction is infinity insert the same cost + */ + if (m_time_matrix[get_index(data.to_vid)][get_index(data.from_vid)] == + (std::numeric_limits::max)()) { + m_time_matrix[get_index(data.to_vid)][get_index(data.from_vid)] = + m_time_matrix[get_index(data.from_vid)][get_index(data.to_vid)]; + } + } + + /* + * Set the diagonal values to 0 + */ + for (size_t i = 0; i < m_time_matrix.size(); ++i) { + m_time_matrix[i][i] = 0; + } +} + /* * constructor for euclidean */ @@ -274,7 +342,22 @@ Base_Matrix::Base_Matrix(const std::map, Id> & } } - +/** + * @brief Get VROOM matrix from vrprouting Base Matrix + * + * @return vroom::Matrix The vroom cost matrix + */ +vroom::Matrix +Base_Matrix::get_vroom_matrix() const { + size_t matrix_size = m_ids.size(); + vroom::Matrix vroom_matrix(matrix_size); + for (size_t i = 0; i < matrix_size; i++) { + for (size_t j = 0; j < matrix_size; j++) { + vroom_matrix[i][j] = static_cast(m_time_matrix[i][j]); + } + } + return vroom_matrix; +} /** * @returns false at the moment it finds an infinity value From e45341aab531066bd457055980b61a8ae0be207e Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:26:11 +0530 Subject: [PATCH 08/20] [vroom][include] Added vroom common files --- include/c_common/arrays_input.h | 3 + include/c_common/get_check_data.h | 40 +- include/c_common/matrixRows_input.h | 6 + include/c_common/vroom/breaks_input.h | 51 ++ include/c_common/vroom/jobs_input.h | 51 ++ include/c_common/vroom/shipments_input.h | 51 ++ include/c_common/vroom/time_windows_input.h | 59 +++ include/c_common/vroom/vehicles_input.h | 51 ++ include/cpp_common/base_matrix.h | 5 + include/cpp_common/vrp_vroom_problem.hpp | 533 ++++++++++++++++++++ 10 files changed, 848 insertions(+), 2 deletions(-) create mode 100644 include/c_common/vroom/breaks_input.h create mode 100644 include/c_common/vroom/jobs_input.h create mode 100644 include/c_common/vroom/shipments_input.h create mode 100644 include/c_common/vroom/time_windows_input.h create mode 100644 include/c_common/vroom/vehicles_input.h create mode 100644 include/cpp_common/vrp_vroom_problem.hpp diff --git a/include/c_common/arrays_input.h b/include/c_common/arrays_input.h index f5677d0e0..33db7eadc 100644 --- a/include/c_common/arrays_input.h +++ b/include/c_common/arrays_input.h @@ -37,4 +37,7 @@ int64_t* pgr_get_bigIntArray(size_t *arrlen, ArrayType *input); /** @brief Allows the input array to be empty */ int64_t* pgr_get_bigIntArray_allowEmpty(size_t *arrlen, ArrayType *input); +/** @brief Allows the input array, with non-negative elements to be empty */ +uint32_t* pgr_get_positiveIntArray_allowEmpty(size_t *arrlen, ArrayType *input); + #endif // INCLUDE_C_COMMON_ARRAYS_INPUT_H_ diff --git a/include/c_common/get_check_data.h b/include/c_common/get_check_data.h index 3625ab1ff..c8fdf224c 100644 --- a/include/c_common/get_check_data.h +++ b/include/c_common/get_check_data.h @@ -44,7 +44,6 @@ spi_getChar( HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info, - bool strict, char default_value); /** @brief Function returns the values of specified columns in array. */ @@ -63,6 +62,22 @@ spi_getBigIntArr_allowEmpty( Column_info_t info, size_t *the_size); +/** @brief Function returns the values of specified columns in array. */ +int64_t* +spi_getPositiveBigIntArr_allowEmpty( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t info, + size_t *the_size); + +/** @brief Function returns the values of specified columns in array. */ +uint32_t* +spi_getPositiveIntArr_allowEmpty( + HeapTuple *tuple, + TupleDesc *tupdesc, + Column_info_t info, + size_t *the_size); + /** @brief gets value of specified column in double type. */ double spi_getFloat8( @@ -81,7 +96,7 @@ spi_getText( /** @name timestamp related * @{ */ /** @brief Converts timestamp to timestamp without timezone */ -TTimestamp timestamp_without_timezone( TTimestamp timestamp); +TTimestamp timestamp_without_timezone(TTimestamp timestamp); /** @brief gets a timestamp value from postgres type TIMESTAMP */ TTimestamp get_TTimestamp(HeapTuple*, TupleDesc*, Column_info_t, TTimestamp); @@ -114,6 +129,27 @@ TInterval get_PositiveTInterval_plain(HeapTuple*, TupleDesc*, Column_info_t, TIn /** get Id from data */ Id get_Id(HeapTuple*, TupleDesc*, Column_info_t, Id); +/** get Idx from data */ +Idx get_Idx(HeapTuple*, TupleDesc*, Column_info_t, Idx); + +/** get StepType from data */ +StepType get_StepType(HeapTuple *, TupleDesc *, Column_info_t, StepType); + +/** get MatrixIndex from data */ +MatrixIndex get_MatrixIndex(HeapTuple*, TupleDesc*, Column_info_t, MatrixIndex); + +/** get Duration from data */ +Duration get_Duration(HeapTuple*, TupleDesc*, Column_info_t, Duration); + +/** get Kind from data */ +char get_Kind(HeapTuple*, TupleDesc*, Column_info_t, char); + +/** get Priority from data */ +Priority get_Priority(HeapTuple*, TupleDesc*, Column_info_t, Priority); + +/** get Distance from data */ +Distance get_Distance(HeapTuple*, TupleDesc*, Column_info_t, Distance); + /** get Amount from data */ Amount get_Amount(HeapTuple*, TupleDesc*, Column_info_t, Amount); diff --git a/include/c_common/matrixRows_input.h b/include/c_common/matrixRows_input.h index 5e3169981..2c3c473c0 100644 --- a/include/c_common/matrixRows_input.h +++ b/include/c_common/matrixRows_input.h @@ -42,4 +42,10 @@ void get_matrixRows_plain( Matrix_cell_t **rows, size_t *total_rows); +/** @brief Get the travel time matrix of vroom with integer types*/ +void get_matrixRows_vroom_plain( + char *sql, + Matrix_cell_t **rows, + size_t *total_rows); + #endif // INCLUDE_C_COMMON_MATRIXROWS_INPUT_H_ diff --git a/include/c_common/vroom/breaks_input.h b/include/c_common/vroom/breaks_input.h new file mode 100644 index 000000000..9ced90937 --- /dev/null +++ b/include/c_common/vroom/breaks_input.h @@ -0,0 +1,51 @@ +/*PGR-GNU***************************************************************** +File: breaks_input.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_C_COMMON_VROOM_BREAKS_INPUT_H_ +#define INCLUDE_C_COMMON_VROOM_BREAKS_INPUT_H_ +#pragma once + +#include + +#include "c_common/get_check_data.h" +#include "c_types/column_info_t.h" +#include "c_types/vroom/vroom_break_t.h" + +#ifdef PROFILE +#include "c_common/debug_macro.h" +#include "c_common/time_msg.h" +#endif + +/** @brief Reads the VROOM breaks */ +void +get_vroom_breaks( + char *breaks_sql, + Vroom_break_t **breaks, + size_t *total_breaks); + +#endif // INCLUDE_C_COMMON_VROOM_BREAKS_INPUT_H_ diff --git a/include/c_common/vroom/jobs_input.h b/include/c_common/vroom/jobs_input.h new file mode 100644 index 000000000..8cc5a51ac --- /dev/null +++ b/include/c_common/vroom/jobs_input.h @@ -0,0 +1,51 @@ +/*PGR-GNU***************************************************************** +File: jobs_input.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_C_COMMON_VROOM_JOBS_INPUT_H_ +#define INCLUDE_C_COMMON_VROOM_JOBS_INPUT_H_ +#pragma once + +#include + +#include "c_common/get_check_data.h" +#include "c_types/column_info_t.h" +#include "c_types/vroom/vroom_job_t.h" + +#ifdef PROFILE +#include "c_common/debug_macro.h" +#include "c_common/time_msg.h" +#endif + +/** @brief Reads the VROOM jobs */ +void +get_vroom_jobs( + char *jobs_sql, + Vroom_job_t **jobs, + size_t *total_jobs); + +#endif // INCLUDE_C_COMMON_VROOM_JOBS_INPUT_H_ diff --git a/include/c_common/vroom/shipments_input.h b/include/c_common/vroom/shipments_input.h new file mode 100644 index 000000000..22bc7fa06 --- /dev/null +++ b/include/c_common/vroom/shipments_input.h @@ -0,0 +1,51 @@ +/*PGR-GNU***************************************************************** +File: shipments_input.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_C_COMMON_VROOM_SHIPMENTS_INPUT_H_ +#define INCLUDE_C_COMMON_VROOM_SHIPMENTS_INPUT_H_ +#pragma once + +#include + +#include "c_common/get_check_data.h" +#include "c_types/column_info_t.h" +#include "c_types/vroom/vroom_shipment_t.h" + +#ifdef PROFILE +#include "c_common/debug_macro.h" +#include "c_common/time_msg.h" +#endif + +/** @brief Reads the VROOM shipments */ +void +get_vroom_shipments( + char *shipments_sql, + Vroom_shipment_t **shipments, + size_t *total_shipments); + +#endif // INCLUDE_C_COMMON_VROOM_SHIPMENTS_INPUT_H_ diff --git a/include/c_common/vroom/time_windows_input.h b/include/c_common/vroom/time_windows_input.h new file mode 100644 index 000000000..a252a0d43 --- /dev/null +++ b/include/c_common/vroom/time_windows_input.h @@ -0,0 +1,59 @@ +/*PGR-GNU***************************************************************** +File: time_windows_input.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_C_COMMON_VROOM_TIME_WINDOWS_INPUT_H_ +#define INCLUDE_C_COMMON_VROOM_TIME_WINDOWS_INPUT_H_ +#pragma once + +#include +#include + +#include "c_common/get_check_data.h" +#include "c_types/column_info_t.h" +#include "c_types/vroom/vroom_time_window_t.h" + +#ifdef PROFILE +#include "c_common/debug_macro.h" +#include "c_common/time_msg.h" +#endif + +/** @brief Reads the VROOM time windows */ +void +get_vroom_time_windows( + char *time_windows_sql, + Vroom_time_window_t **time_windows, + size_t *total_time_windows); + +/** @brief Reads the VROOM shipments time windows */ +void +get_vroom_shipments_time_windows( + char *time_windows_sql, + Vroom_time_window_t **time_windows, + size_t *total_time_windows); + +#endif // INCLUDE_C_COMMON_VROOM_TIME_WINDOWS_INPUT_H_ diff --git a/include/c_common/vroom/vehicles_input.h b/include/c_common/vroom/vehicles_input.h new file mode 100644 index 000000000..298f2a7c5 --- /dev/null +++ b/include/c_common/vroom/vehicles_input.h @@ -0,0 +1,51 @@ +/*PGR-GNU***************************************************************** +File: vehicles_input.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_C_COMMON_VROOM_VEHICLES_INPUT_H_ +#define INCLUDE_C_COMMON_VROOM_VEHICLES_INPUT_H_ +#pragma once + +#include + +#include "c_common/get_check_data.h" +#include "c_types/column_info_t.h" +#include "c_types/vroom/vroom_vehicle_t.h" + +#ifdef PROFILE +#include "c_common/debug_macro.h" +#include "c_common/time_msg.h" +#endif + +/** @brief Reads the VROOM vehicles */ +void +get_vroom_vehicles( + char *vehicles_sql, + Vroom_vehicle_t **vehicles, + size_t *total_vehicles); + +#endif // INCLUDE_C_COMMON_VROOM_VEHICLES_INPUT_H_ diff --git a/include/cpp_common/base_matrix.h b/include/cpp_common/base_matrix.h index 0d47ece23..16be2d7cf 100644 --- a/include/cpp_common/base_matrix.h +++ b/include/cpp_common/base_matrix.h @@ -38,6 +38,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "c_types/typedefs.h" #include "cpp_common/identifiers.hpp" +#include "structures/generic/matrix.h" + typedef struct Matrix_cell_t Matrix_cell_t; namespace vrprouting { @@ -62,6 +64,7 @@ class Base_Matrix { Base_Matrix() = default; /** @brief Constructs a matrix for only specific identifiers */ Base_Matrix(Matrix_cell_t *, size_t, const Identifiers&, Multiplier); + Base_Matrix(Matrix_cell_t *, size_t, const Identifiers &); explicit Base_Matrix(const std::map, Id> &, Multiplier); /** @name status of the matrix @@ -70,6 +73,8 @@ class Base_Matrix { /** @brief does the matrix values not given by the user? */ bool has_no_infinity() const; + vroom::Matrix get_vroom_matrix() const; + /** @brief does the matrix obeys the triangle inequality? */ bool obeys_triangle_inequality() const; size_t fix_triangle_inequality(size_t depth = 0); diff --git a/include/cpp_common/vrp_vroom_problem.hpp b/include/cpp_common/vrp_vroom_problem.hpp new file mode 100644 index 000000000..be9309bb1 --- /dev/null +++ b/include/cpp_common/vrp_vroom_problem.hpp @@ -0,0 +1,533 @@ +/*PGR-GNU***************************************************************** +File: vrp_vroom_problem.hpp + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_CPP_COMMON_VRP_VROOM_PROBLEM_HPP_ +#define INCLUDE_CPP_COMMON_VRP_VROOM_PROBLEM_HPP_ +#pragma once + +#include +#include +#include +#include +#include + +#include "c_types/vroom/vroom_job_t.h" +#include "c_types/vroom/vroom_rt.h" +#include "c_types/vroom/vroom_break_t.h" +#include "c_types/vroom/vroom_shipment_t.h" +#include "c_types/vroom/vroom_time_window_t.h" +#include "c_types/vroom/vroom_vehicle_t.h" +#include "c_types/matrix_cell_t.h" +#include "cpp_common/pgr_messages.h" +#include "cpp_common/base_matrix.h" + +#include "structures/vroom/input/input.h" +#include "structures/vroom/job.h" +#include "structures/vroom/vehicle.h" + +namespace vrprouting { + +class Vrp_vroom_problem : public vrprouting::Pgr_messages { + public: + std::vector jobs() const { return m_jobs; } + std::vector> shipments() const { return m_shipments; } + std::vector vehicles() const { return m_vehicles; } + vrprouting::base::Base_Matrix matrix() const { return m_matrix; } + + /** + * @name vroom time window wrapper + */ + ///@{ + /** + * @brief Gets the vroom time window from the C-style struct + * + * @param[in] time_window The C-style time window struct + * + * @return The vroom time window. + */ + vroom::TimeWindow + get_vroom_time_window(const Vroom_time_window_t &time_window) const { + return + vroom::TimeWindow(time_window.start_time, + time_window.end_time); + } + + vroom::TimeWindow + get_vroom_time_window(Duration start_time, Duration end_time) const { + return vroom::TimeWindow(start_time, end_time); + } + + std::vector + get_vroom_time_windows( + const std::vector &time_windows) const { + std::vector < vroom::TimeWindow > tws; + for (auto time_window : time_windows) { + tws.push_back(get_vroom_time_window(time_window)); + } + if (tws.size()) { + return tws; + } else { + return std::vector(1, vroom::TimeWindow()); + } + } + ///@} + + + /** + * @name vroom amounts wrapper + */ + ///@{ + /** + * @brief Gets the vroom amounts from C-style array + * + * @param[in] amounts The amounts array (pickup or delivery) + * + * @return The vroom amounts. + */ + vroom::Amount + get_vroom_amounts(const std::vector &amounts) const { + vroom::Amount amt; + if (amounts.size()) { + for (auto amount : amounts) { + amt.push_back(amount); + } + } else { + const unsigned int amount_size = + m_vehicles.size() ? static_cast(m_vehicles[0].capacity.size()) : 0; + // Default to zero amount with provided size. + amt = vroom::Amount(amount_size); + for (size_t i = 0; i < amounts.size(); i++) { + amt[i] = amounts[i]; + } + } + return amt; + } + + vroom::Amount + get_vroom_amounts(const Amount *amounts, size_t count) const { + return get_vroom_amounts(std::vector (amounts, amounts + count)); + } + ///@} + + + /** + * @name vroom skills wrapper + */ + ///@{ + /** + * @brief Gets the vroom skills. + * + * @param[in] skills The skills array + * @param[in] count The size of skills array + * + * @return The vroom skills. + */ + vroom::Skills + get_vroom_skills(const Skill *skills, size_t count) const { + return std::unordered_set (skills, skills + count); + } + ///@} + + + /** + * @name vroom jobs wrapper + */ + ///@{ + /** + * @brief Gets the vroom jobs. + * + * @param[in] job The job C-style struct + * @param[in] job_tws The job time windows + * + * @return The vroom job. + */ + vroom::Job + get_vroom_job(const Vroom_job_t &job, + const std::vector &job_tws) const { + vroom::Amount delivery = + get_vroom_amounts(job.delivery, job.delivery_size); + vroom::Amount pickup = + get_vroom_amounts(job.pickup, job.pickup_size); + vroom::Skills skills = + get_vroom_skills(job.skills, job.skills_size); + std::vector time_windows = + get_vroom_time_windows(job_tws); + vroom::Index location_index = + static_cast(m_matrix.get_index(job.location_index)); + return vroom::Job(job.id, location_index, job.service, delivery, pickup, + skills, job.priority, time_windows); + } + + void problem_add_job(const Vroom_job_t &job, + const std::vector &job_tws) { + m_jobs.push_back(get_vroom_job(job, job_tws)); + } + + void add_jobs(const std::vector &jobs, + const std::vector &jobs_tws) { + std::map> job_tws_map; + for (auto job_tw : jobs_tws) { + Idx id = job_tw.id; + if (job_tws_map.find(id) == job_tws_map.end()) { + job_tws_map[id] = std::vector(); + } + job_tws_map[id].push_back(job_tw); + } + for (auto job : jobs) { + problem_add_job(job, job_tws_map[job.id]); + } + } + + void add_jobs(const Vroom_job_t *jobs, size_t count, + const Vroom_time_window_t *jobs_tws, size_t total_jobs_tws) { + add_jobs( + std::vector(jobs, jobs + count), + std::vector(jobs_tws, jobs_tws + total_jobs_tws)); + } + ///@} + + + /** + * @name vroom shipments wrapper + */ + ///@{ + /** + * @brief Gets the vroom shipments. + * + * @param[in] shipment The shipment C-style struct + * @param[in] pickup_tws The pickup time windows + * @param[in] delivery_tws The delivery time windows + * + * @return The vroom shipment. + */ + std::pair get_vroom_shipment( + const Vroom_shipment_t &shipment, + const std::vector &pickup_tws, + const std::vector &delivery_tws) const { + vroom::Amount amount = + get_vroom_amounts(shipment.amount, shipment.amount_size); + vroom::Skills skills = + get_vroom_skills(shipment.skills, shipment.skills_size); + std::vector p_time_windows = + get_vroom_time_windows(pickup_tws); + std::vector d_time_windows = + get_vroom_time_windows(delivery_tws); + vroom::Index p_location_index = static_cast( + m_matrix.get_index(shipment.p_location_index)); + vroom::Index d_location_index = static_cast( + m_matrix.get_index(shipment.d_location_index)); + vroom::Job pickup = vroom::Job(shipment.id, vroom::JOB_TYPE::PICKUP, + p_location_index, shipment.p_service, amount, + skills, shipment.priority, p_time_windows); + vroom::Job delivery = vroom::Job( + shipment.id, vroom::JOB_TYPE::DELIVERY, d_location_index, + shipment.d_service, amount, skills, shipment.priority, d_time_windows); + return std::make_pair(pickup, delivery); + } + + void problem_add_shipment( + const Vroom_shipment_t &shipment, + const std::vector &pickup_tws, + const std::vector &delivery_tws) { + m_shipments.push_back( + get_vroom_shipment(shipment, pickup_tws, delivery_tws)); + } + + void add_shipments(const std::vector &shipments, + const std::vector &shipments_tws) { + std::map> pickup_tws_map; + std::map> delivery_tws_map; + for (auto shipment_tw : shipments_tws) { + Idx id = shipment_tw.id; + if (shipment_tw.kind == 'p') { + if (pickup_tws_map.find(id) == pickup_tws_map.end()) { + pickup_tws_map[id] = std::vector(); + } + pickup_tws_map[id].push_back(shipment_tw); + } else if (shipment_tw.kind == 'd') { + if (delivery_tws_map.find(id) == delivery_tws_map.end()) { + delivery_tws_map[id] = std::vector(); + } + delivery_tws_map[id].push_back(shipment_tw); + } + } + for (auto shipment : shipments) { + problem_add_shipment(shipment, pickup_tws_map[shipment.id], + delivery_tws_map[shipment.id]); + } + } + + void add_shipments(const Vroom_shipment_t *shipments, size_t count, + const Vroom_time_window_t *shipment_tws, size_t total_shipment_tws) { + add_shipments( + std::vector(shipments, shipments + count), + std::vector(shipment_tws, shipment_tws + total_shipment_tws)); + } + ///@} + + + /** + * @name vroom breaks wrapper + */ + ///@{ + /** + * @brief Gets the vehicle breaks from C-style breaks struct + * + * @param[in] v_break The vehicle break struct + * + * @return The vroom vehicle break. + */ + vroom::Break + get_vroom_break( + const Vroom_break_t &v_break, + const std::vector &break_tws) const { + std::vector tws = get_vroom_time_windows(break_tws); + return vroom::Break(v_break.id, tws, v_break.service); + } + + std::vector < vroom::Break > + get_vroom_breaks( + const std::vector &breaks, + const std::vector &breaks_tws) const { + std::map> breaks_tws_map; + for (auto break_tw : breaks_tws) { + Idx id = break_tw.id; + if (breaks_tws_map.find(id) == breaks_tws_map.end()) { + breaks_tws_map[id] = std::vector(); + } + breaks_tws_map[id].push_back(break_tw); + } + std::vector < vroom::Break > v_breaks; + for (auto v_break : breaks) { + v_breaks.push_back(get_vroom_break(v_break, breaks_tws_map[v_break.id])); + } + return v_breaks; + } + ///@} + + + /** + * @name vroom vehicles wrapper + */ + ///@{ + /** + * @brief Gets the vroom vehicles. + * + * @param[in] vehicle The vehicle C-style struct + * @param[in] breaks_tws The breaks time windows + * + * @return The vroom vehicle. + */ + vroom::Vehicle get_vroom_vehicle( + const Vroom_vehicle_t &vehicle, + const std::vector &breaks, + const std::vector &breaks_tws) const { + vroom::Amount capacity = + get_vroom_amounts(vehicle.capacity, vehicle.capacity_size); + vroom::Skills skills = + get_vroom_skills(vehicle.skills, vehicle.skills_size); + vroom::TimeWindow time_window = + get_vroom_time_window(vehicle.time_window_start, + vehicle.time_window_end); + std::vector v_breaks = get_vroom_breaks(breaks, breaks_tws); + + std::optional start_index; + std::optional end_index; + // Set the value of start or end index only if they are present + if (vehicle.start_index != -1) { + start_index = static_cast(m_matrix.get_index(vehicle.start_index)); + } + if (vehicle.end_index != -1) { + end_index = static_cast(m_matrix.get_index(vehicle.end_index)); + } + return vroom::Vehicle(vehicle.id, start_index, end_index, + vroom::DEFAULT_PROFILE, capacity, skills, time_window, + v_breaks, "", vehicle.speed_factor); + } + + void problem_add_vehicle( + const Vroom_vehicle_t &vehicle, + const std::vector &breaks, + const std::vector &breaks_tws) { + m_vehicles.push_back(get_vroom_vehicle(vehicle, breaks, breaks_tws)); + } + + void add_vehicles(const std::vector &vehicles, + const std::vector &breaks, + const std::vector &breaks_tws) { + std::map> breaks_tws_map; + for (auto break_tw : breaks_tws) { + Idx id = break_tw.id; + if (breaks_tws_map.find(id) == breaks_tws_map.end()) { + breaks_tws_map[id] = std::vector(); + } + breaks_tws_map[id].push_back(break_tw); + } + + std::map> v_breaks_map; + for (auto v_break : breaks) { + Idx v_id = v_break.vehicle_id; + if (v_breaks_map.find(v_id) == v_breaks_map.end()) { + v_breaks_map[v_id] = std::vector(); + } + v_breaks_map[v_id].push_back(v_break); + } + + for (auto vehicle : vehicles) { + std::vector v_breaks = v_breaks_map[vehicle.id]; + std::vector v_breaks_tws; + for (auto v_break : v_breaks) { + std::vector tws = breaks_tws_map[v_break.id]; + v_breaks_tws.insert(v_breaks_tws.end(), tws.begin(), tws.end()); + } + problem_add_vehicle(vehicle, v_breaks, v_breaks_tws); + } + } + + void add_vehicles(const Vroom_vehicle_t *vehicles, size_t count, + const Vroom_break_t *breaks, size_t total_breaks, + const Vroom_time_window_t *breaks_tws, size_t total_breaks_tws) { + add_vehicles(std::vector(vehicles, vehicles + count), + std::vector(breaks, breaks + total_breaks), + std::vector(breaks_tws, breaks_tws + total_breaks_tws)); + } + ///@} + + + void add_matrix(vrprouting::base::Base_Matrix time_matrix) { + m_matrix = time_matrix; + } + + void get_amount(vroom::Amount vroom_amount, Amount **amount) { + size_t amount_size = vroom_amount.size(); + for (size_t i = 0; i < amount_size; i++) { + *((*amount) + i) = vroom_amount[i]; + } + } + + std::vector < Vroom_rt > get_results(vroom::Solution solution) { + std::vector < Vroom_rt > results; + std::vector routes = solution.routes; + Idx vehicle_seq = 1; + for (auto route : routes) { + Idx step_seq = 1; + for (auto step : route.steps) { + int32_t step_type = 0; + Id task_id = static_cast (step.id); + switch (step.step_type) { + case vroom::STEP_TYPE::START: + step_type = 1; + task_id = -1; + break; + case vroom::STEP_TYPE::END: + step_type = 6; + task_id = -1; + break; + case vroom::STEP_TYPE::BREAK: + step_type = 5; + break; + case vroom::STEP_TYPE::JOB: + switch (step.job_type) { + case vroom::JOB_TYPE::SINGLE: + step_type = 2; + break; + case vroom::JOB_TYPE::PICKUP: + step_type = 3; + break; + case vroom::JOB_TYPE::DELIVERY: + step_type = 4; + break; + } + break; + } + size_t load_size = step.load.size(); + Amount *load = reinterpret_cast(malloc(load_size * sizeof(Amount))); + get_amount(step.load, &load); + + results.push_back({ + vehicle_seq, // vehicles_seq + route.vehicle, // vehicles_id + step_seq, // step_seq + step_type, // step_type + task_id, // task_id + step.arrival, // arrival + step.duration, // duration + step.service, // service_time + step.waiting_time, // waiting_time + load, // load + load_size // load size + }); + step_seq++; + } + vehicle_seq++; + } + return results; + } + + std::vector < Vroom_rt > solve() { + std::vector results; + try { + const unsigned int amount_size = + m_vehicles.size() + ? static_cast(m_vehicles[0].capacity.size()) + : 0; + vroom::Input problem_instance(amount_size); + + for (const auto &vehicle : m_vehicles) { + problem_instance.add_vehicle(vehicle); + } + for (const auto &job : m_jobs) { + problem_instance.add_job(job); + } + for (const auto &shipment : m_shipments) { + problem_instance.add_shipment(shipment.first, shipment.second); + } + vroom::Matrix matrix = m_matrix.get_vroom_matrix(); + problem_instance.set_matrix(vroom::DEFAULT_PROFILE, std::move(matrix)); + + auto solution = problem_instance.solve(5, 4); + results = get_results(solution); + } catch (const vroom::Exception &ex) { + throw; + } catch (const std::exception &ex) { + throw; + } catch (...) { + throw; + } + return results; + } + + private: + std::vector m_jobs; + std::vector> m_shipments; + std::vector m_vehicles; + vrprouting::base::Base_Matrix m_matrix; +}; + +} // namespace vrprouting + +#endif // INCLUDE_CPP_COMMON_VRP_VROOM_PROBLEM_HPP_ From 1103ba1784d7eb8ff6c4b5f3fadd742f26b4249a Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:26:38 +0530 Subject: [PATCH 09/20] [vroom][include] Added vroom types --- include/c_types/column_info_t.h | 5 +- include/c_types/typedefs.h | 26 +++++++- include/c_types/vroom/vroom_break_t.h | 52 +++++++++++++++ include/c_types/vroom/vroom_job_t.h | 70 ++++++++++++++++++++ include/c_types/vroom/vroom_rt.h | 66 +++++++++++++++++++ include/c_types/vroom/vroom_shipment_t.h | 72 +++++++++++++++++++++ include/c_types/vroom/vroom_time_window_t.h | 53 +++++++++++++++ include/c_types/vroom/vroom_vehicle_t.h | 70 ++++++++++++++++++++ 8 files changed, 412 insertions(+), 2 deletions(-) create mode 100644 include/c_types/vroom/vroom_break_t.h create mode 100644 include/c_types/vroom/vroom_job_t.h create mode 100644 include/c_types/vroom/vroom_rt.h create mode 100644 include/c_types/vroom/vroom_shipment_t.h create mode 100644 include/c_types/vroom/vroom_time_window_t.h create mode 100644 include/c_types/vroom/vroom_vehicle_t.h diff --git a/include/c_types/column_info_t.h b/include/c_types/column_info_t.h index 7d6ca522a..571be6b42 100644 --- a/include/c_types/column_info_t.h +++ b/include/c_types/column_info_t.h @@ -30,15 +30,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. /* for int64_t */ #ifndef __cplusplus # include +# include #endif // used for getting the data typedef enum { + INTEGER, ANY_INTEGER, ANY_NUMERICAL, TEXT, CHAR1, + INTEGER_ARRAY, ANY_INTEGER_ARRAY, TIMESTAMP, INTERVAL @@ -48,7 +51,7 @@ enum { typedef struct { int colNumber; - unsigned long type; + uint64_t type; bool strict; char *name; expectType eType; diff --git a/include/c_types/typedefs.h b/include/c_types/typedefs.h index 6bf1e7c84..9a8117d2c 100644 --- a/include/c_types/typedefs.h +++ b/include/c_types/typedefs.h @@ -39,12 +39,24 @@ using Speed = double; using Multiplier = double; using Id = int64_t; using Idx = uint64_t; +using MatrixIndex = int64_t; +using Duration = uint32_t; +using Priority = uint32_t; +using Distance = uint32_t; +using Skill = uint32_t; +using StepType = int32_t; using PickDeliveryOrders_t = struct PickDeliveryOrders_t; using Vehicle_t = struct Vehicle_t; using Matrix_cell_t = struct Matrix_cell_t; using Time_multipliers_t = struct Time_multipliers_t; using Solution_rt = struct Solution_rt; using Short_vehicle_rt = struct Short_vehicle_rt; +using Vroom_job_t = struct Vroom_job_t; +using Vroom_shipment_t = struct Vroom_shipment_t; +using Vroom_vehicle_t = struct Vroom_vehicle_t; +using Vroom_break_t = struct Vroom_break_t; +using Vroom_time_window_t = struct Vroom_time_window_t; +using Vroom_rt = struct Vroom_rt; /* * Index on a container */ @@ -60,15 +72,27 @@ typedef uint32_t PAmount; typedef double Speed; typedef double Multiplier; typedef int64_t Id; +typedef uint64_t Idx; +typedef int64_t MatrixIndex; +typedef uint32_t Duration; +typedef uint32_t Priority; +typedef uint32_t Distance; +typedef uint32_t Skill; +typedef int32_t StepType; typedef struct PickDeliveryOrders_t PickDeliveryOrders_t; typedef struct Vehicle_t Vehicle_t; typedef struct Matrix_cell_t Matrix_cell_t; typedef struct Time_multipliers_t Time_multipliers_t; typedef struct Solution_rt Solution_rt; typedef struct Short_vehicle_rt Short_vehicle_rt; +typedef struct Vroom_job_t Vroom_job_t; +typedef struct Vroom_shipment_t Vroom_shipment_t; +typedef struct Vroom_vehicle_t Vroom_vehicle_t; +typedef struct Vroom_break_t Vroom_break_t; +typedef struct Vroom_time_window_t Vroom_time_window_t; +typedef struct Vroom_rt Vroom_rt; #endif - /*************************************************************************/ #endif // INCLUDE_C_TYPES_TYPEDEFS_H_ diff --git a/include/c_types/vroom/vroom_break_t.h b/include/c_types/vroom/vroom_break_t.h new file mode 100644 index 000000000..4246837ea --- /dev/null +++ b/include/c_types/vroom/vroom_break_t.h @@ -0,0 +1,52 @@ +/*PGR-GNU***************************************************************** +File: vroom_break_t.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ +/*! @file */ + +#ifndef INCLUDE_C_TYPES_VROOM_VROOM_BREAK_T_H_ +#define INCLUDE_C_TYPES_VROOM_VROOM_BREAK_T_H_ +#pragma once + +#include "c_types/typedefs.h" + +/** @brief Vehicle's break attributes + +@note C/C++/postgreSQL connecting structure for input +name | description +:----- | :------- +id | Identifier of break +vehicle_id | Identifier of vehicle +service | Duration of break +*/ +struct Vroom_break_t { + Idx id; /** Identifier of break */ + Idx vehicle_id; /** Identifier of vehicle */ + Duration service; /** Duration of break */ +}; + + +#endif // INCLUDE_C_TYPES_VROOM_VROOM_BREAK_T_H_ diff --git a/include/c_types/vroom/vroom_job_t.h b/include/c_types/vroom/vroom_job_t.h new file mode 100644 index 000000000..76e3af6b5 --- /dev/null +++ b/include/c_types/vroom/vroom_job_t.h @@ -0,0 +1,70 @@ +/*PGR-GNU***************************************************************** +File: vroom_job_t.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ +/*! @file */ + +#ifndef INCLUDE_C_TYPES_VROOM_VROOM_JOB_T_H_ +#define INCLUDE_C_TYPES_VROOM_VROOM_JOB_T_H_ +#pragma once + +#include "c_types/typedefs.h" + +/** @brief Job's attributes + +@note C/C++/postgreSQL connecting structure for input +name | description +:----- | :------- +id | The job's identifier +location_index | Location index of job in matrix +service | Job service duration +delivery | Quantities for delivery +delivery_size | Number of delivery quantities +pickup | Quantities for pickup +pickup_size | Number of pickup quantities +skills | Mandatory skills +skills_size | Number of mandatory skills +priority | Priority level of job +*/ +struct Vroom_job_t { + Idx id; /** The job's identifier */ + MatrixIndex location_index; /** Location index of job in matrix */ + + Duration service; /** Job service duration */ + + Amount *delivery; /** Quantities for delivery */ + size_t delivery_size; /** Number of delivery quantities */ + + Amount *pickup; /** Quantities for pickup */ + size_t pickup_size; /** Number of pickup quantities */ + + Skill *skills; /** Mandatory skills */ + size_t skills_size; /** Number of mandatory skills */ + + Priority priority; /** Priority level of job */ +}; + +#endif // INCLUDE_C_TYPES_VROOM_VROOM_JOB_T_H_ diff --git a/include/c_types/vroom/vroom_rt.h b/include/c_types/vroom/vroom_rt.h new file mode 100644 index 000000000..d5961fa55 --- /dev/null +++ b/include/c_types/vroom/vroom_rt.h @@ -0,0 +1,66 @@ +/*PGR-GNU***************************************************************** +File: vroom_rt.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ +/*! @file */ + +#ifndef INCLUDE_C_TYPES_VROOM_VROOM_RT_H_ +#define INCLUDE_C_TYPES_VROOM_VROOM_RT_H_ +#pragma once + +#include "c_types/typedefs.h" + +/** @brief Solution's attributes + +@note C/C++/postgreSQL connecting structure for input +name | description +:----- | :------- +vehicle_seq | Sequence for ordering a single vehicle +vehicle_id | The vehicle's identifier +step_seq | Step sequence of the vehicle +step_type | Step sequence of the vehicle +task_id | The task's identifier +arrival_time | Estimated time of arrival +travel_time | Cumulated travel time upon arrival +service_time | Service time at this step +waiting_time | Waiting time upon arrival at this step +load | Vehicle load after step completion +*/ +struct Vroom_rt { + Idx vehicle_seq; /** Sequence for ordering a single vehicle */ + Idx vehicle_id; /** The vehicle's identifier */ + Idx step_seq; /** Step sequence of the vehicle */ + StepType step_type; /** Type of the step */ + Id task_id; /** The task's identifier */ + Duration arrival_time; /** Estimated time of arrival */ + Duration travel_time; /** Cumulated travel time upon arrival */ + Duration service_time; /** Service time at this step */ + Duration waiting_time; /** Waiting time upon arrival at this step */ + Amount *load; /** Vehicle's load after step completion array */ + size_t load_size; /** Vehicle's load array size */ +}; + +#endif // INCLUDE_C_TYPES_VROOM_VROOM_RT_H_ diff --git a/include/c_types/vroom/vroom_shipment_t.h b/include/c_types/vroom/vroom_shipment_t.h new file mode 100644 index 000000000..ed61b60c4 --- /dev/null +++ b/include/c_types/vroom/vroom_shipment_t.h @@ -0,0 +1,72 @@ +/*PGR-GNU***************************************************************** +File: vroom_shipment_t.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ +/*! @file */ + +#ifndef INCLUDE_C_TYPES_VROOM_VROOM_SHIPMENT_T_H_ +#define INCLUDE_C_TYPES_VROOM_VROOM_SHIPMENT_T_H_ +#pragma once + +#include "c_types/typedefs.h" + +/** @brief Vehicles's attributes + +@note C/C++/postgreSQL connecting structure for input +name | description +:----- | :------- +id | Shipment identifier +p_location_index | Pickup location index in matrix +p_service | Pickup service time +d_location_index | Delivery location index in matrix +d_service | Delivery service time +amount | Quantities for shipment +amount_size | Number of quantities +skills | Mandatory skills +skills_size | Number of skills +priority | Priority level of shipment +*/ +struct Vroom_shipment_t { + Idx id; /** Shipment identifier */ + + /** pickup shipment */ + MatrixIndex p_location_index; /** Pickup location index in matrix */ + Duration p_service; /** Pickup service time */ + + /** delivery shipment */ + MatrixIndex d_location_index; /** Delivery location index in matrix */ + Duration d_service; /** Delivery service time */ + + Amount *amount; /** Quantities for shipment */ + size_t amount_size; /** Number of quantities */ + + Skill *skills; /** Mandatory skills */ + size_t skills_size; /** Number of skills */ + + Priority priority; /** Priority level of shipment */ +}; + +#endif // INCLUDE_C_TYPES_VROOM_VROOM_SHIPMENT_T_H_ diff --git a/include/c_types/vroom/vroom_time_window_t.h b/include/c_types/vroom/vroom_time_window_t.h new file mode 100644 index 000000000..99e7dd86b --- /dev/null +++ b/include/c_types/vroom/vroom_time_window_t.h @@ -0,0 +1,53 @@ +/*PGR-GNU***************************************************************** +File: vroom_time_window_t.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ +/*! @file */ + +#ifndef INCLUDE_C_TYPES_VROOM_VROOM_TIME_WINDOW_T_H_ +#define INCLUDE_C_TYPES_VROOM_VROOM_TIME_WINDOW_T_H_ +#pragma once + +#include "c_types/typedefs.h" + +/** @brief Time window's attributes + +@note C/C++/postgreSQL connecting structure for input +name | description +:----- | :------- +id | Identifier of the job/shipment/break +kind | Whether the shipment is a pickup ('p') or a delivery ('d') +start_time | Time window start time +end_time | Time window end time +*/ +struct Vroom_time_window_t { + Idx id; + char kind; + Duration start_time; + Duration end_time; +}; + +#endif // INCLUDE_C_TYPES_VROOM_VROOM_TIME_WINDOW_T_H_ diff --git a/include/c_types/vroom/vroom_vehicle_t.h b/include/c_types/vroom/vroom_vehicle_t.h new file mode 100644 index 000000000..4231297e3 --- /dev/null +++ b/include/c_types/vroom/vroom_vehicle_t.h @@ -0,0 +1,70 @@ +/*PGR-GNU***************************************************************** +File: vroom_vehicle_t.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ +/*! @file */ + +#ifndef INCLUDE_C_TYPES_VROOM_VROOM_VEHICLE_T_H_ +#define INCLUDE_C_TYPES_VROOM_VROOM_VEHICLE_T_H_ +#pragma once + +#include "c_types/typedefs.h" + +/** @brief Vehicles's attributes + +@note C/C++/postgreSQL connecting structure for input +name | description +:----- | :------- +id | The vehicle's identifier +start_index | Start location index in matrix +end_index | End location index in matrix +capacity | Vehicle's capacity array +capacity_size | Vehicle's capacity array size +skills | Vehicle's skills +skills_size | Number of vehicle's skills +time_window_start | Time window start time +time_window_end | Time window end time +speed_factor | Vehicle travel time multiplier +*/ +struct Vroom_vehicle_t { + Idx id; /** The vehicle's identifier */ + MatrixIndex start_index; /** Start location index in matrix */ + MatrixIndex end_index; /** End location index in matrix */ + + Amount *capacity; /** Vehicle's capacity array */ + size_t capacity_size; /** Vehicle's capacity array size */ + + Skill *skills; /** Vehicle's skills */ + size_t skills_size; /** Number of vehicle's skills */ + + Duration time_window_start; /** Time window start time */ + Duration time_window_end; /** Time window end time */ + + double speed_factor; /** Vehicle travel time multiplier */ +}; + + +#endif // INCLUDE_C_TYPES_VROOM_VROOM_VEHICLE_T_H_ From 1933468634dcd825ded9eece74cb45a4c7863850 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:28:34 +0530 Subject: [PATCH 10/20] [vroom][include] Added vroom driver --- include/drivers/vroom/vroom_driver.h | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 include/drivers/vroom/vroom_driver.h diff --git a/include/drivers/vroom/vroom_driver.h b/include/drivers/vroom/vroom_driver.h new file mode 100644 index 000000000..83a3b8ccd --- /dev/null +++ b/include/drivers/vroom/vroom_driver.h @@ -0,0 +1,60 @@ +/*PGR-GNU***************************************************************** +File: vroom_driver.h + +Copyright (c) 2021 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2021 Ashish Kumar +Mail: ashishkr23438@gmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + ********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_DRIVERS_VROOM_VROOM_DRIVER_H_ +#define INCLUDE_DRIVERS_VROOM_VROOM_DRIVER_H_ +#pragma once + +#include "c_types/typedefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + + void do_vrp_vroom( + Vroom_job_t *jobs, size_t total_jobs, + Vroom_time_window_t *jobs_tws, size_t total_jobs_tws, + Vroom_shipment_t *shipments, size_t total_shipments, + Vroom_time_window_t *shipments_tws, size_t total_shipments_tws, + Vroom_vehicle_t *vehicles, size_t total_vehicles, + Vroom_break_t *breaks, size_t total_breaks, + Vroom_time_window_t *breaks_tws, size_t total_breaks_tws, + Matrix_cell_t *matrix_cells_arr, size_t total_cells, + + Vroom_rt **return_tuples, + size_t *return_count, + + char ** log_msg, + char ** notice_msg, + char ** err_msg); + +#ifdef __cplusplus +} +#endif + +#endif // INCLUDE_DRIVERS_VROOM_VROOM_DRIVER_H_ From 3729131defc6174c8436354718c61731ef719f18 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:27:01 +0530 Subject: [PATCH 11/20] [vroom][cmake] Updated CMakeLists to build vroom --- CMakeLists.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b5a5a806..888cd6bb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,11 +52,13 @@ set(DOXYGEN_MINIMUM_VERSION "1.7") set(SPHINX_MINIMUM_VERSION "1.8") set(POSTGRESQL_MINIMUM_VERSION "12.0") set(BOOST_MINIMUM_VERSION "1.65.0") +set(VROOM_MINIMUM_VERSION "1.10.0") message(STATUS "DOXYGEN_MINIMUM_VERSION=${DOXYGEN_MINIMUM_VERSION}") message(STATUS "SPHINX_MINIMUM_VERSION=${SPHINX_MINIMUM_VERSION}") message(STATUS "POSTGRESQL_MINIMUM_VERSION=${POSTGRESQL_MINIMUM_VERSION}") message(STATUS "BOOST_MINIMUM_VERSION=${BOOST_MINIMUM_VERSION}") +message(STATUS "VROOM_MINIMUM_VERSION=${VROOM_MINIMUM_VERSION}") # cmake 3.2 adds unwanted flags if(WIN32 AND MSVC) @@ -71,7 +73,7 @@ endif() #----------------------------------------------------------------------------- -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_STANDARD 11) #--------------------------------------------- @@ -301,6 +303,19 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") endif() +#------------------- +# Add the VROOM library and dependencies +#------------------- + +if(NOT VROOM_INSTALL_PATH) + message(FATAL_ERROR "VROOM installation path not specified. Please specify the vroom root directory in -DVROOM_INSTALL_PATH") +endif() + +message(STATUS "VROOM_INSTALL_PATH ${VROOM_INSTALL_PATH}") + +include_directories(${VROOM_INSTALL_PATH}/src) +link_libraries(${VROOM_INSTALL_PATH}/lib/libvroom.a) +link_libraries(glpk) #------------------- # add the subdirectories that have the C/C++ code From 8ecaa1d52a86dfc1e2cceac790e4d0a98365323d Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:27:58 +0530 Subject: [PATCH 12/20] [vroom][config] Updated configuration file to compile vroom --- configuration.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/configuration.conf b/configuration.conf index e824637cb..9e051b19c 100644 --- a/configuration.conf +++ b/configuration.conf @@ -27,3 +27,4 @@ viewRoute | N | Y | N simulation | N | Y | N optimizers | Y | N | N initialsol | Y | N | N +vroom | Y | Y | Y From f4c7f0d7d2d6d442fd737a95dfe355e7f887431d Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:34:02 +0530 Subject: [PATCH 13/20] [vroom][ci] Updated GitHub Actions to compile, build and test vroom --- .github/workflows/boost_version.yml | 20 ++++++++++++++++++-- .github/workflows/check-queries.yml | 21 +++++++++++++++++++-- .github/workflows/clang.yml | 21 +++++++++++++++++++-- .github/workflows/doc-check.yml | 20 +++++++++++++++++++- .github/workflows/documentation.yml | 20 +++++++++++++++++++- .github/workflows/macos.yml | 28 ++++++++++++++++++++++++++-- .github/workflows/publish-doc.yml | 19 ++++++++++++++++++- .github/workflows/release.yml | 19 ++++++++++++++++++- .github/workflows/ubuntu.yml | 21 +++++++++++++++++++-- 9 files changed, 175 insertions(+), 14 deletions(-) diff --git a/.github/workflows/boost_version.yml b/.github/workflows/boost_version.yml index d03a3e32c..62719b3f0 100644 --- a/.github/workflows/boost_version.yml +++ b/.github/workflows/boost_version.yml @@ -62,13 +62,29 @@ jobs: sudo tar --bzip2 -xf boost_1_${{ matrix.boost_minor }}_0.tar.bz2 sudo mv boost_1_${{ matrix.boost_minor }}_0/boost /usr/include/ + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV - name: Configure run: | export PATH=/usr/lib/postgresql/${PGVER}/bin:$PATH mkdir build cd build - cmake -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=Debug -DWITH_DOC=OFF .. + cmake -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=Debug -DWITH_DOC=OFF -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build run: | @@ -76,7 +92,7 @@ jobs: make -j 4 sudo make install - - name: Unapck data + - name: Unpack data run: | cd tools/testers tar -xf matrix_new_values.tar.gz diff --git a/.github/workflows/check-queries.yml b/.github/workflows/check-queries.yml index dc06e8f98..9d9bb7e1a 100644 --- a/.github/workflows/check-queries.yml +++ b/.github/workflows/check-queries.yml @@ -52,12 +52,29 @@ jobs: postgresql-${PGVER}-pgrouting \ postgresql-server-dev-${PGVER} + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure run: | export PATH=/usr/lib/postgresql/${PGVER}/bin:$PATH mkdir build cd build - cmake -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=Debug .. + cmake -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=Debug -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build run: | @@ -73,7 +90,7 @@ jobs: tools/scripts/get_signatures.sh -p ${PGPORT} git diff --exit-code --quiet sql/sigs/*.sig - - name: Unapck data + - name: Unpack data run: | cd tools/testers tar -xf matrix_new_values.tar.gz diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index f8ed46703..cc3766ad8 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -55,12 +55,29 @@ jobs: postgresql-${PGVER}-pgrouting \ postgresql-server-dev-${PGVER} + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure run: | export PATH=/usr/lib/postgresql/${PGVER}/bin:$PATH mkdir build cd build - CXX=clang++ CC=clang cmake -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=${{ matrix.release }} -DWITH_DOC=OFF .. + CXX=clang++ CC=clang cmake -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=${{ matrix.release }} -DWITH_DOC=OFF -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build run: | @@ -68,7 +85,7 @@ jobs: make -j 4 sudo make install - - name: Unapck data + - name: Unpack data run: | cd tools/testers tar -xf matrix_new_values.tar.gz diff --git a/.github/workflows/doc-check.yml b/.github/workflows/doc-check.yml index 695d179a4..1b4c99b8c 100644 --- a/.github/workflows/doc-check.yml +++ b/.github/workflows/doc-check.yml @@ -76,6 +76,23 @@ jobs: pip install -r requirements.txt pip list + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure if: env.PROCESS == 'true' run: | @@ -84,7 +101,8 @@ jobs: cd build cmake -DLINKCHECK=ON -DHTML=ON -DWITH_DOC=ON \ -DDE=ON -DES=ON -DFR=ON -DJA=ON -DIT=ON \ - -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=Release .. + -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=Release \ + -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Check Links if: env.PROCESS == 'true' diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 8249f252d..2d6368d0f 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -56,13 +56,31 @@ jobs: pip install -r requirements.txt pip list + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure link checks run: | export PATH=/usr/lib/postgresql/${PGVER}/bin:$PATH mkdir build cd build cmake -DPOSTGRESQL_VERSION=${PGVER} -DCMAKE_BUILD_TYPE=Release \ - -DWITH_DOC=ON -DES=ON .. + -DWITH_DOC=ON -DES=ON \ + -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build Documentation run: | diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index e0bf6cf69..1ce3b6007 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -9,6 +9,7 @@ on: paths-ignore: - '**.po' +# TODO: Fix the macOS build for compiling and building VROOM with vrprouting. jobs: build: name: Build @@ -22,11 +23,34 @@ jobs: run: | brew install postgis boost pgrouting + - name: Install VROOM dependencies + run: | + brew install openssl asio glpk + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Source: https://github.com/VROOM-Project/vroom/issues/378 + ln -s /usr/local/opt/openssl/include/openssl /usr/local/include + ln -s /usr/local/opt/openssl/lib/libssl.dylib /usr/local/lib/ + ln -s /usr/local/opt/openssl/lib/libcrypto.dylib /usr/local/lib/ + + # Create object file with position independent code using -fPIC flag + sed -i '' -e 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + sed -i '' -e 's/\/usr\/include\/glpk.h/\/usr\/local\/opt\/glpk\/include\/glpk.h/' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_DOC=OFF .. + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_DOC=OFF -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build run: | @@ -63,7 +87,7 @@ jobs: sudo make install cpan TAP::Parser::SourceHandler::pgTAP - - name: Unapck data + - name: Unpack data run: | cd tools/testers tar -xf matrix_new_values.tar.gz diff --git a/.github/workflows/publish-doc.yml b/.github/workflows/publish-doc.yml index a45af950d..9d75ee4f1 100644 --- a/.github/workflows/publish-doc.yml +++ b/.github/workflows/publish-doc.yml @@ -67,12 +67,29 @@ jobs: pip install sphinx-bootstrap-theme pip list + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure run: | export PATH=/usr/lib/postgresql/${PGVER}/bin:$PATH mkdir build cd build - cmake -DPOSTGRESQL_VERSION=${PGVER} -DDOC_USE_BOOTSTRAP=ON -DWITH_DOC=ON -DBUILD_DOXY=ON -DCMAKE_BUILD_TYPE=Release -DES=ON .. + cmake -DPOSTGRESQL_VERSION=${PGVER} -DDOC_USE_BOOTSTRAP=ON -DWITH_DOC=ON -DBUILD_DOXY=ON -DCMAKE_BUILD_TYPE=Release -DES=ON -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea2383dcf..8a090cbf5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,12 +75,29 @@ jobs: pip install sphinx-bootstrap-theme pip list + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure run: | export PATH=/usr/lib/postgresql/${PGVER}/bin:$PATH mkdir build cd build - cmake -DPOSTGRESQL_VERSION=${PGVER} -DDOC_USE_BOOTSTRAP=ON -DWITH_DOC=ON -DBUILD_DOXY=ON -DCMAKE_BUILD_TYPE=Release -DES=ON .. + cmake -DPOSTGRESQL_VERSION=${PGVER} -DDOC_USE_BOOTSTRAP=ON -DWITH_DOC=ON -DBUILD_DOXY=ON -DCMAKE_BUILD_TYPE=Release -DES=ON -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build run: | diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index f3d55f8e8..8c3b03d06 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -55,12 +55,29 @@ jobs: postgresql-${{ matrix.psql }}-pgrouting \ postgresql-server-dev-${{ matrix.psql }} + - name: Install VROOM dependencies + run: | + sudo apt-get install libssl-dev libasio-dev libglpk-dev + + - name: Build VROOM v1.10.0 + run: | + wget https://github.com/VROOM-Project/vroom/archive/refs/tags/v1.10.0.tar.gz + tar -zvxf v1.10.0.tar.gz + cd vroom-1.10.0/src + + # Create object file with position independent code using -fPIC flag + sed -i 's/CXXFLAGS = /CXXFLAGS = -fPIC /' makefile + + make + cd .. + echo "VROOM_INSTALL_PATH=$(pwd)" >> $GITHUB_ENV + - name: Configure run: | export PATH=/usr/lib/postgresql/${{ matrix.psql }}/bin:$PATH mkdir build cd build - cmake -DPOSTGRESQL_VERSION=${{ matrix.psql }} -DCMAKE_BUILD_TYPE=${{ matrix.release }} -DWITH_DOC=OFF .. + cmake -DPOSTGRESQL_VERSION=${{ matrix.psql }} -DCMAKE_BUILD_TYPE=${{ matrix.release }} -DWITH_DOC=OFF -DVROOM_INSTALL_PATH=${VROOM_INSTALL_PATH} .. - name: Build run: | @@ -68,7 +85,7 @@ jobs: make -j 4 sudo make install - - name: Unapck data + - name: Unpack data run: | cd tools/testers tar -xf matrix_new_values.tar.gz From 0497d345759e58214ed96128c96ff33800d15e6d Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:34:27 +0530 Subject: [PATCH 14/20] [vroom][doc] Added vroom functions documentation --- doc/conf.py.in | 12 ++- doc/general/CMakeLists.txt | 1 + doc/general/experimental.rst | 1 + doc/general/sampledata.rst | 59 +++++++++++ doc/general/vroom-category.rst | 169 +++++++++++++++++++++++++++++++ doc/vroom/CMakeLists.txt | 14 +++ doc/vroom/vrp_vroom.rst | 116 +++++++++++++++++++++ doc/vroom/vrp_vroomJobs.rst | 108 ++++++++++++++++++++ doc/vroom/vrp_vroomShipments.rst | 109 ++++++++++++++++++++ 9 files changed, 587 insertions(+), 2 deletions(-) create mode 100644 doc/general/vroom-category.rst create mode 100644 doc/vroom/CMakeLists.txt create mode 100644 doc/vroom/vrp_vroom.rst create mode 100644 doc/vroom/vrp_vroomJobs.rst create mode 100644 doc/vroom/vrp_vroomShipments.rst diff --git a/doc/conf.py.in b/doc/conf.py.in index 5c74d182e..46401c0e0 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -171,8 +171,8 @@ html_last_updated_fmt = '%b %d, %Y' # Custom sidebar templates, maps document names to template names. html_sidebars = { - # '**': ['globaltoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html'], - # 'using/windows': ['windowssidebar.html', 'searchbox.html'], + # '**': ['globaltoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html'], + # 'using/windows': ['windowssidebar.html', 'searchbox.html'], } # Additional templates that should be rendered to pages, maps page names to @@ -317,6 +317,14 @@ linkcheck_ignore = [ r"https://gis.stackexchange.com/", "https://vrp.pgrouting.org/v0/en/pgr-category.html", "https://vrp.pgrouting.org/latest/en/pgr-category.html", + "https://vrp.pgrouting.org/v0/en/vroom-category.html", + "https://vrp.pgrouting.org/latest/en/vroom-category.html", + "https://vrp.pgrouting.org/v0/en/vrp_vroom.html", + "https://vrp.pgrouting.org/latest/en/vrp_vroom.html", + "https://vrp.pgrouting.org/v0/en/vrp_vroomJobs.html", + "https://vrp.pgrouting.org/latest/en/vrp_vroomJobs.html", + "https://vrp.pgrouting.org/v0/en/vrp_vroomShipments.html", + "https://vrp.pgrouting.org/latest/en/vrp_vroomShipments.html", # (see: https://github.com/sphinx-doc/sphinx/issues/7388) r"https://github.com/pgRouting/vrprouting/", # limit only vrprouting diff --git a/doc/general/CMakeLists.txt b/doc/general/CMakeLists.txt index e542f46ef..be8954041 100644 --- a/doc/general/CMakeLists.txt +++ b/doc/general/CMakeLists.txt @@ -11,6 +11,7 @@ SET(LOCAL_FILES sampledata.rst support.rst pgr-category.rst + vroom-category.rst ) foreach (f ${LOCAL_FILES}) diff --git a/doc/general/experimental.rst b/doc/general/experimental.rst index 6ea295034..0bd4a3aee 100644 --- a/doc/general/experimental.rst +++ b/doc/general/experimental.rst @@ -51,6 +51,7 @@ Experimental Functions :maxdepth: 2 pgr-category + vroom-category .. rubric:: See Also diff --git a/doc/general/sampledata.rst b/doc/general/sampledata.rst index d3468e1d6..48e8bcb64 100644 --- a/doc/general/sampledata.rst +++ b/doc/general/sampledata.rst @@ -67,6 +67,65 @@ Orders table .. literalinclude:: ../../tools/testers/solomon_100_rc101.data.sql +VROOM Data +------------------------------------------------------------------------------- + +Jobs +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- JOBS TABLE start + :end-before: -- JOBS TABLE end + +Jobs Time Windows +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- JOBS TIME WINDOWS TABLE start + :end-before: -- JOBS TIME WINDOWS TABLE end + +Shipments +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- SHIPMENTS TABLE start + :end-before: -- SHIPMENTS TABLE end + +Shipments Time Windows +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- SHIPMENTS TIME WINDOWS TABLE start + :end-before: -- SHIPMENTS TIME WINDOWS TABLE end + +Vehicles +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- VEHICLES TABLE start + :end-before: -- VEHICLES TABLE end + +Breaks +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- BREAKS TABLE start + :end-before: -- BREAKS TABLE end + +Breaks Time Windows +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- BREAKS TIME WINDOWS TABLE start + :end-before: -- BREAKS TIME WINDOWS TABLE end + +Matrix +............................................................................... + +.. literalinclude:: ../../tools/testers/vroomdata.sql + :start-after: -- MATRIX TABLE start + :end-before: -- MATRIX TABLE end + Images ------------------------------------------------------------------------------- diff --git a/doc/general/vroom-category.rst b/doc/general/vroom-category.rst new file mode 100644 index 000000000..1008291a3 --- /dev/null +++ b/doc/general/vroom-category.rst @@ -0,0 +1,169 @@ +.. + **************************************************************************** + vrpRouting Manual + Copyright(c) vrpRouting Contributors + + This documentation is licensed under a Creative Commons Attribution-Share + Alike 3.0 License: https://creativecommons.org/licenses/by-sa/3.0/ + **************************************************************************** + +| + +* `Documentation `__ → `vrpRouting v0 `__ +* Supported Versions + `Latest `__ + (`v0 `__) + + +VROOM - Category (Experimental) +=============================================================================== + +.. include:: experimental.rst + :start-after: begin-warn-expr + :end-before: end-warn-expr + + +.. contents:: + +.. rubric:: Functions + +.. toctree:: + :maxdepth: 1 + + vrp_vroom + vrp_vroomJobs + vrp_vroomShipments + + +Synopsis +------------------------------------------------------------------------------- + +VROOM is an open-source optimization engine that aims at providing good solutions +to various real-life vehicle routing problems (VRP) within a small computing time. + +VROOM can solve several well-known types of vehicle routing problems (VRP). + +- TSP (travelling salesman problem) +- CVRP (capacitated VRP) +- VRPTW (VRP with time windows) +- MDHVRPTW (multi-depot heterogeneous vehicle VRPTW) +- PDPTW (pickup-and-delivery problem with TW) + +VROOM can also solve any mix of the above problem types. + + +Characteristics +............................................................................... + +VROOM models a Vehicle Routing Problem with ``vehicles``, ``jobs`` and ``shipments``. + +The **vehicles** denote the resources that pick and/or deliver the jobs and shipments. +They are characterised by: + +- Capacity on arbitrary number of metrics +- Skills +- Working hours +- Driver breaks +- Start and end defined on a per-vehicle basis +- Start and end can be different +- Open trip optimization (only start or only end defined) + +The **jobs** denote the single-location pickup and/or delivery tasks, and the **shipments** +denote the pickup-and-delivery tasks that should happen within the same route. +They are characterised by: + +- Delivery/pickup amounts on arbitrary number of metrics +- Service time windows +- Service duration +- Skills +- Priority + +Terminologies +............................................................................... + +- **Tasks**: Either jobs or shipments are referred to as tasks. +- **Skills**: Every task and vehicle may have some set of skills. A task can be served by only that vehicle which has all the skills of the task. +- **Priority**: Tasks may have some priority assigned, which is useful when all tasks cannot be performed due to constraints, so the tasks with low priority are left unassigned. +- **Amount (for shipment), Pickup and delivery (for job)**: They denote the multidimensional quantities such as number of items, weights, volume, etc. +- **Capacity (for vehicle)**: Every vehicle may have some capacity, denoting the multidimensional quantities. A vehicle can serve only those sets of tasks such that the total sum of the quantity does not exceed the vehicle capacity, at any point of the route. +- **Time Window**: An interval of time during which some activity can be performed, such as working hours of the vehicle, break of the vehicle, or service start time for a task. +- **Break**: Array of time windows, denoting valid slots for the break start of a vehicle. +- **Service time**: The additional time to be spent by a vehicle while serving a task. +- **Travel time**: The total time the vehicle travels during its route. +- **Waiting time**: The total time the vehicle is idle, i.e. it is neither traveling nor servicing any task. It is generally the time spent by a vehicle waiting for a task service to open. + +Inner Queries +------------------------------------------------------------------------------- + +Jobs SQL +............................................................................... + +.. include:: ../../src/common/vroom/jobs_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +Shipments SQL +............................................................................... + +.. include:: ../../src/common/vroom/shipments_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +.. inner_queries_start + +Vehicles SQL +............................................................................... + +.. include:: ../../src/common/vroom/vehicles_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +Breaks SQL +............................................................................... + +.. include:: ../../src/common/vroom/breaks_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +Time Windows SQL +............................................................................... + +.. include:: ../../src/common/vroom/time_windows_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +Time Matrix SQL +............................................................................... + +.. include:: ../../src/common/matrixRows_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +.. inner_queries_end + +Result Columns +------------------------------------------------------------------------------- + +.. result_columns_start + +.. include:: ../sql/vroom/vrp_vroom.sql + :start-after: result start + :end-before: result end + +.. result_columns_end + +See Also +------------------------------------------------------------------------------- + +.. see_also_start + +* `Wikipedia: Vehicle Routing problems `__ +* `VROOM: Vehicle Routing Open-source Optimization Machine `__ +* `VROOM API Documentation `__ + +.. see_also_end + +.. rubric:: Indices and tables + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/vroom/CMakeLists.txt b/doc/vroom/CMakeLists.txt new file mode 100644 index 000000000..d537ef8af --- /dev/null +++ b/doc/vroom/CMakeLists.txt @@ -0,0 +1,14 @@ + +SET(LOCAL_FILES + vrp_vroom.rst + vrp_vroomJobs.rst + vrp_vroomShipments.rst + ) + +foreach (f ${LOCAL_FILES}) + configure_file(${f} "${PGR_DOCUMENTATION_SOURCE_DIR}/${f}") + list(APPEND LOCAL_DOC_FILES ${PGR_DOCUMENTATION_SOURCE_DIR}/${f}) +endforeach() + +set(PROJECT_DOC_FILES ${PROJECT_DOC_FILES} ${LOCAL_DOC_FILES} PARENT_SCOPE) +set(PROJECT_IMG_FILES ${PROJECT_IMG_FILES} PARENT_SCOPE) diff --git a/doc/vroom/vrp_vroom.rst b/doc/vroom/vrp_vroom.rst new file mode 100644 index 000000000..2987ee976 --- /dev/null +++ b/doc/vroom/vrp_vroom.rst @@ -0,0 +1,116 @@ +.. + **************************************************************************** + vrpRouting Manual + Copyright(c) vrpRouting Contributors + + This documentation is licensed under a Creative Commons Attribution-Share + Alike 3.0 License: https://creativecommons.org/licenses/by-sa/3.0/ + **************************************************************************** + +| + +* `Documentation `__ → `vrpRouting v0 `__ +* Supported Versions + `Latest `__ + (`v0 `__) + + +vrp_vroom - Experimental +=============================================================================== + +``vrp_vroom`` - Vehicle Routing Problem with VROOM, involving both jobs and shipments. + +.. include:: experimental.rst + :start-after: begin-warn-expr + :end-before: end-warn-expr + +.. rubric:: Availability + +Version 0.2.0 + +* New **experimental** function + + +Description +------------------------------------------------------------------------------- + +VROOM is an open-source optimization engine that aims at providing good solutions +to various real-life vehicle routing problems (VRP) within a small computing time. +This function can be used to get the solution to a problem involving both jobs and +shipments. + +.. index:: + single: vrp_vroom -- Experimental on v0.2 + +Signature +------------------------------------------------------------------------------- + +.. include:: ../sql/vroom/vrp_vroom.sql + :start-after: signature start + :end-before: signature end + +**Example**: This example is based on the VROOM Data of the :doc:`sampledata` network: + +.. literalinclude:: doc-vrp_vroom.queries + :start-after: -- q1 + :end-before: -- q2 + +Parameters +------------------------------------------------------------------------------- + +.. include:: ../sql/vroom/vrp_vroom.sql + :start-after: parameters start + :end-before: parameters end + +Inner Queries +------------------------------------------------------------------------------- + +Jobs SQL +............................................................................... + +.. include:: ../../src/common/vroom/jobs_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +Shipments SQL +............................................................................... + +.. include:: ../../src/common/vroom/shipments_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +.. include:: vroom-category.rst + :start-after: inner_queries_start + :end-before: inner_queries_end + +Result Columns +------------------------------------------------------------------------------- + +.. include:: vroom-category.rst + :start-after: result_columns_start + :end-before: result_columns_end + +Additional Example +------------------------------------------------------------------------------- + +Problem involving 2 jobs and 1 shipment, using a single vehicle, similar to the VROOM Documentation +`Example 2 `__ with a shipment. + +.. literalinclude:: doc-vrp_vroom.queries + :start-after: -- q2 + :end-before: -- q3 + +See Also +------------------------------------------------------------------------------- + +* :doc:`vroom-category` +* The queries use the :doc:`sampledata` network. + +.. include:: vroom-category.rst + :start-after: see_also_start + :end-before: see_also_end + +.. rubric:: Indices and tables + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/vroom/vrp_vroomJobs.rst b/doc/vroom/vrp_vroomJobs.rst new file mode 100644 index 000000000..be67cf924 --- /dev/null +++ b/doc/vroom/vrp_vroomJobs.rst @@ -0,0 +1,108 @@ +.. + **************************************************************************** + vrpRouting Manual + Copyright(c) vrpRouting Contributors + + This documentation is licensed under a Creative Commons Attribution-Share + Alike 3.0 License: https://creativecommons.org/licenses/by-sa/3.0/ + **************************************************************************** + +| + +* `Documentation `__ → `vrpRouting v0 `__ +* Supported Versions + `Latest `__ + (`v0 `__) + + +vrp_vroomJobs - Experimental +=============================================================================== + +``vrp_vroomJobs`` - Vehicle Routing Problem with VROOM, involving only jobs. + +.. include:: experimental.rst + :start-after: begin-warn-expr + :end-before: end-warn-expr + +.. rubric:: Availability + +Version 0.2.0 + +* New **experimental** function + + +Description +------------------------------------------------------------------------------- + +VROOM is an open-source optimization engine that aims at providing good solutions +to various real-life vehicle routing problems (VRP) within a small computing time. +This function can be used to get the solution to a problem involving only jobs. + +.. index:: + single: vrp_vroomJobs -- Experimental on v0.2 + +Signature +------------------------------------------------------------------------------- + +.. include:: ../sql/vroom/vrp_vroomJobs.sql + :start-after: signature start + :end-before: signature end + +**Example**: This example is based on the VROOM Data of the :doc:`sampledata` network: + +.. literalinclude:: doc-vrp_vroomJobs.queries + :start-after: -- q1 + :end-before: -- q2 + +Parameters +------------------------------------------------------------------------------- + +.. include:: ../sql/vroom/vrp_vroomJobs.sql + :start-after: parameters start + :end-before: parameters end + +Inner Queries +------------------------------------------------------------------------------- + +Jobs SQL +............................................................................... + +.. include:: ../../src/common/vroom/jobs_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +.. include:: vroom-category.rst + :start-after: inner_queries_start + :end-before: inner_queries_end + +Result Columns +------------------------------------------------------------------------------- + +.. include:: vroom-category.rst + :start-after: result_columns_start + :end-before: result_columns_end + +Additional Example +------------------------------------------------------------------------------- + +Problem involving 2 jobs, using a single vehicle, corresponding to the VROOM Documentation +`Example 2 `__. + +.. literalinclude:: doc-vrp_vroomJobs.queries + :start-after: -- q2 + :end-before: -- q3 + +See Also +------------------------------------------------------------------------------- + +* :doc:`vroom-category` +* The queries use the :doc:`sampledata` network. + +.. include:: vroom-category.rst + :start-after: see_also_start + :end-before: see_also_end + +.. rubric:: Indices and tables + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/vroom/vrp_vroomShipments.rst b/doc/vroom/vrp_vroomShipments.rst new file mode 100644 index 000000000..5a504eeed --- /dev/null +++ b/doc/vroom/vrp_vroomShipments.rst @@ -0,0 +1,109 @@ +.. + **************************************************************************** + vrpRouting Manual + Copyright(c) vrpRouting Contributors + + This documentation is licensed under a Creative Commons Attribution-Share + Alike 3.0 License: https://creativecommons.org/licenses/by-sa/3.0/ + **************************************************************************** + +| + +* `Documentation `__ → `vrpRouting v0 `__ +* Supported Versions + `Latest `__ + (`v0 `__) + + +vrp_vroomShipments - Experimental +=============================================================================== + +``vrp_vroomShipments`` - Vehicle Routing Problem with VROOM, involving only shipments. + +.. include:: experimental.rst + :start-after: begin-warn-expr + :end-before: end-warn-expr + +.. rubric:: Availability + +Version 0.2.0 + +* New **experimental** function + + +Description +------------------------------------------------------------------------------- + +VROOM is an open-source optimization engine that aims at providing good solutions +to various real-life vehicle routing problems (VRP) within a small computing time. +This function can be used to get the solution to a problem involving only shipments. + +.. index:: + single: vrp_vroomShipments -- Experimental on v0.2 + +Signature +------------------------------------------------------------------------------- + +.. include:: ../sql/vroom/vrp_vroomShipments.sql + :start-after: signature start + :end-before: signature end + +**Example**: This example is based on the VROOM Data of the :doc:`sampledata` network: + +.. literalinclude:: doc-vrp_vroomShipments.queries + :start-after: -- q1 + :end-before: -- q2 + +Parameters +------------------------------------------------------------------------------- + +.. include:: ../sql/vroom/vrp_vroomShipments.sql + :start-after: parameters start + :end-before: parameters end + +Inner Queries +------------------------------------------------------------------------------- + +Shipments SQL +............................................................................... + +.. include:: ../../src/common/vroom/shipments_input.c + :start-after: vrp_vroom start + :end-before: vrp_vroom end + +.. include:: vroom-category.rst + :start-after: inner_queries_start + :end-before: inner_queries_end + +Result Columns +------------------------------------------------------------------------------- + +.. include:: vroom-category.rst + :start-after: result_columns_start + :end-before: result_columns_end + +Additional Example +------------------------------------------------------------------------------- + +Problem involving 1 shipment, using a single vehicle, similar to the VROOM Documentation +`Example 2 `__ without jobs +and with a shipment. + +.. literalinclude:: doc-vrp_vroomShipments.queries + :start-after: -- q2 + :end-before: -- q3 + +See Also +------------------------------------------------------------------------------- + +* :doc:`vroom-category` +* The queries use the :doc:`sampledata` network. + +.. include:: vroom-category.rst + :start-after: see_also_start + :end-before: see_also_end + +.. rubric:: Indices and tables + +* :ref:`genindex` +* :ref:`search` From bac4a03f31cc9688efa84faab62e47a43677b951 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:34:40 +0530 Subject: [PATCH 15/20] [vroom][docqueries] Added vroom function docqueries --- docqueries/vroom/CMakeLists.txt | 13 +++ docqueries/vroom/doc-vrp_vroom.result | 91 +++++++++++++++++++ docqueries/vroom/doc-vrp_vroom.test.sql | 44 +++++++++ docqueries/vroom/doc-vrp_vroomJobs.result | 65 +++++++++++++ docqueries/vroom/doc-vrp_vroomJobs.test.sql | 36 ++++++++ .../vroom/doc-vrp_vroomShipments.result | 70 ++++++++++++++ .../vroom/doc-vrp_vroomShipments.test.sql | 36 ++++++++ docqueries/vroom/test.conf | 21 +++++ 8 files changed, 376 insertions(+) create mode 100644 docqueries/vroom/CMakeLists.txt create mode 100644 docqueries/vroom/doc-vrp_vroom.result create mode 100644 docqueries/vroom/doc-vrp_vroom.test.sql create mode 100644 docqueries/vroom/doc-vrp_vroomJobs.result create mode 100644 docqueries/vroom/doc-vrp_vroomJobs.test.sql create mode 100644 docqueries/vroom/doc-vrp_vroomShipments.result create mode 100644 docqueries/vroom/doc-vrp_vroomShipments.test.sql create mode 100644 docqueries/vroom/test.conf diff --git a/docqueries/vroom/CMakeLists.txt b/docqueries/vroom/CMakeLists.txt new file mode 100644 index 000000000..ad8f8281f --- /dev/null +++ b/docqueries/vroom/CMakeLists.txt @@ -0,0 +1,13 @@ +# Do not use extensions +SET(LOCAL_FILES + doc-vrp_vroom + doc-vrp_vroomJobs + doc-vrp_vroomShipments + ) + +foreach (f ${LOCAL_FILES}) + configure_file("${f}.result" "${PGR_DOCUMENTATION_SOURCE_DIR}/${f}.queries") + list(APPEND LOCAL_DOC_FILES "${PGR_DOCUMENTATION_SOURCE_DIR}/${f}.queries") +endforeach() + +set(PROJECT_DOC_FILES ${PROJECT_DOC_FILES} ${LOCAL_DOC_FILES} PARENT_SCOPE) diff --git a/docqueries/vroom/doc-vrp_vroom.result b/docqueries/vroom/doc-vrp_vroom.result new file mode 100644 index 000000000..371ee2ad9 --- /dev/null +++ b/docqueries/vroom/doc-vrp_vroom.result @@ -0,0 +1,91 @@ +BEGIN; +BEGIN +SET client_min_messages TO NOTICE; +SET +-- q1 +SELECT * +FROM vrp_vroom( + 'SELECT * FROM vroom.jobs', + 'SELECT * FROM vroom.jobs_time_windows', + 'SELECT * FROM vroom.shipments', + 'SELECT * FROM vroom.shipments_time_windows', + 'SELECT * FROM vroom.vehicles', + 'SELECT * FROM vroom.breaks', + 'SELECT * FROM vroom.breaks_time_windows', + 'SELECT * FROM vroom.matrix' +); + seq | vehicle_seq | vehicle_id | step_seq | step_type | task_id | arrival | travel_time | service_time | waiting_time | load +-----+-------------+------------+----------+-----------+---------+---------+-------------+--------------+--------------+------ + 1 | 1 | 1 | 1 | 1 | -1 | 300 | 0 | 0 | 0 | {30} + 2 | 1 | 1 | 2 | 5 | 1 | 300 | 0 | 0 | 0 | {30} + 3 | 1 | 1 | 3 | 2 | 2 | 350 | 50 | 250 | 900 | {30} + 4 | 1 | 1 | 4 | 3 | 5 | 1500 | 50 | 2250 | 11850 | {40} + 5 | 1 | 1 | 5 | 3 | 3 | 15650 | 100 | 2250 | 0 | {60} + 6 | 1 | 1 | 6 | 4 | 5 | 17950 | 150 | 2250 | 225 | {50} + 7 | 1 | 1 | 7 | 4 | 3 | 20425 | 150 | 2250 | 200 | {30} + 8 | 1 | 1 | 8 | 6 | -1 | 22925 | 200 | 0 | 0 | {30} + 9 | 2 | 2 | 1 | 1 | -1 | 275 | 0 | 0 | 0 | {70} + 10 | 2 | 2 | 2 | 5 | 2 | 275 | 0 | 10 | 0 | {70} + 11 | 2 | 2 | 3 | 2 | 5 | 360 | 75 | 250 | 665 | {70} + 12 | 2 | 2 | 4 | 2 | 3 | 1325 | 125 | 250 | 1400 | {70} + 13 | 2 | 2 | 5 | 2 | 4 | 2975 | 125 | 250 | 550 | {70} + 14 | 2 | 2 | 6 | 6 | -1 | 3775 | 125 | 0 | 0 | {70} + 15 | 3 | 3 | 1 | 1 | -1 | 0 | 0 | 0 | 0 | {20} + 16 | 3 | 3 | 2 | 5 | 3 | 0 | 0 | 0 | 0 | {20} + 17 | 3 | 3 | 3 | 2 | 1 | 0 | 0 | 250 | 3625 | {20} + 18 | 3 | 3 | 4 | 3 | 4 | 3875 | 0 | 2250 | 2500 | {40} + 19 | 3 | 3 | 5 | 4 | 4 | 8700 | 75 | 2250 | 225 | {20} + 20 | 3 | 3 | 6 | 6 | -1 | 11250 | 150 | 0 | 0 | {20} + 21 | 4 | 4 | 1 | 1 | -1 | 250 | 0 | 0 | 0 | {0} + 22 | 4 | 4 | 2 | 5 | 4 | 250 | 0 | 0 | 0 | {0} + 23 | 4 | 4 | 3 | 3 | 2 | 275 | 25 | 2250 | 100 | {10} + 24 | 4 | 4 | 4 | 3 | 1 | 2650 | 50 | 2250 | 0 | {20} + 25 | 4 | 4 | 5 | 4 | 2 | 4990 | 140 | 2250 | 0 | {10} + 26 | 4 | 4 | 6 | 4 | 1 | 7351 | 251 | 2250 | 17574 | {0} + 27 | 4 | 4 | 7 | 6 | -1 | 27200 | 276 | 0 | 0 | {0} +(27 rows) + +-- q2 +SELECT * +FROM vrp_vroom( + $jobs$ + SELECT * FROM ( + VALUES (1414, 2), (1515, 3) + ) AS C(id, location_index) + $jobs$, + NULL, + $shipments$ + SELECT * FROM ( + VALUES (100, 1, 4) + ) AS C(id, p_location_index, d_location_index) + $shipments$, + NULL, + $vehicles$ + SELECT * FROM ( + VALUES (1, 1, 4) + ) AS C(id, start_index, end_index) + $vehicles$, + NULL, + NULL, + $matrix$ + SELECT * FROM ( + VALUES (1, 2, 2104), (1, 3, 197), (1, 4, 1299), + (2, 1, 2103), (2, 3, 2255), (2, 4, 3152), + (3, 1, 197), (3, 2, 2256), (3, 4, 1102), + (4, 1, 1299), (4, 2, 3153), (4, 3, 1102) + ) AS C(start_vid, end_vid, agg_cost) + $matrix$ +); + seq | vehicle_seq | vehicle_id | step_seq | step_type | task_id | arrival | travel_time | service_time | waiting_time | load +-----+-------------+------------+----------+-----------+---------+---------+-------------+--------------+--------------+------ + 1 | 1 | 1 | 1 | 1 | -1 | 0 | 0 | 0 | 0 | {} + 2 | 1 | 1 | 2 | 3 | 100 | 0 | 0 | 0 | 0 | {} + 3 | 1 | 1 | 3 | 2 | 1414 | 2104 | 2104 | 0 | 0 | {} + 4 | 1 | 1 | 4 | 2 | 1515 | 4359 | 4359 | 0 | 0 | {} + 5 | 1 | 1 | 5 | 4 | 100 | 5461 | 5461 | 0 | 0 | {} + 6 | 1 | 1 | 6 | 6 | -1 | 5461 | 5461 | 0 | 0 | {} +(6 rows) + +-- q3 +ROLLBACK; +ROLLBACK diff --git a/docqueries/vroom/doc-vrp_vroom.test.sql b/docqueries/vroom/doc-vrp_vroom.test.sql new file mode 100644 index 000000000..c0ce92438 --- /dev/null +++ b/docqueries/vroom/doc-vrp_vroom.test.sql @@ -0,0 +1,44 @@ +\echo -- q1 +SELECT * +FROM vrp_vroom( + 'SELECT * FROM vroom.jobs', + 'SELECT * FROM vroom.jobs_time_windows', + 'SELECT * FROM vroom.shipments', + 'SELECT * FROM vroom.shipments_time_windows', + 'SELECT * FROM vroom.vehicles', + 'SELECT * FROM vroom.breaks', + 'SELECT * FROM vroom.breaks_time_windows', + 'SELECT * FROM vroom.matrix' +); +\echo -- q2 +SELECT * +FROM vrp_vroom( + $jobs$ + SELECT * FROM ( + VALUES (1414, 2), (1515, 3) + ) AS C(id, location_index) + $jobs$, + NULL, + $shipments$ + SELECT * FROM ( + VALUES (100, 1, 4) + ) AS C(id, p_location_index, d_location_index) + $shipments$, + NULL, + $vehicles$ + SELECT * FROM ( + VALUES (1, 1, 4) + ) AS C(id, start_index, end_index) + $vehicles$, + NULL, + NULL, + $matrix$ + SELECT * FROM ( + VALUES (1, 2, 2104), (1, 3, 197), (1, 4, 1299), + (2, 1, 2103), (2, 3, 2255), (2, 4, 3152), + (3, 1, 197), (3, 2, 2256), (3, 4, 1102), + (4, 1, 1299), (4, 2, 3153), (4, 3, 1102) + ) AS C(start_vid, end_vid, agg_cost) + $matrix$ +); +\echo -- q3 diff --git a/docqueries/vroom/doc-vrp_vroomJobs.result b/docqueries/vroom/doc-vrp_vroomJobs.result new file mode 100644 index 000000000..db6a8f149 --- /dev/null +++ b/docqueries/vroom/doc-vrp_vroomJobs.result @@ -0,0 +1,65 @@ +BEGIN; +BEGIN +SET client_min_messages TO NOTICE; +SET +-- q1 +SELECT * +FROM vrp_vroomJobs( + 'SELECT * FROM vroom.jobs', + 'SELECT * FROM vroom.jobs_time_windows', + 'SELECT * FROM vroom.vehicles', + 'SELECT * FROM vroom.breaks', + 'SELECT * FROM vroom.breaks_time_windows', + 'SELECT * FROM vroom.matrix' +); + seq | vehicle_seq | vehicle_id | step_seq | step_type | task_id | arrival | travel_time | service_time | waiting_time | load +-----+-------------+------------+----------+-----------+---------+---------+-------------+--------------+--------------+------- + 1 | 1 | 1 | 1 | 1 | -1 | 300 | 0 | 0 | 0 | {20} + 2 | 1 | 1 | 2 | 5 | 1 | 300 | 0 | 0 | 0 | {20} + 3 | 1 | 1 | 3 | 2 | 1 | 300 | 0 | 250 | 3325 | {20} + 4 | 1 | 1 | 4 | 6 | -1 | 3875 | 0 | 0 | 0 | {20} + 5 | 2 | 2 | 1 | 1 | -1 | 275 | 0 | 0 | 0 | {100} + 6 | 2 | 2 | 2 | 5 | 2 | 275 | 0 | 10 | 0 | {100} + 7 | 2 | 2 | 3 | 2 | 2 | 335 | 50 | 250 | 915 | {100} + 8 | 2 | 2 | 4 | 2 | 5 | 1590 | 140 | 250 | 0 | {100} + 9 | 2 | 2 | 5 | 2 | 3 | 1890 | 190 | 250 | 835 | {100} + 10 | 2 | 2 | 6 | 2 | 4 | 2975 | 190 | 250 | 550 | {100} + 11 | 2 | 2 | 7 | 6 | -1 | 3775 | 190 | 0 | 0 | {100} +(11 rows) + +-- q2 +SELECT * +FROM vrp_vroomJobs( + $jobs$ + SELECT * FROM ( + VALUES (1414, 2), (1515, 3) + ) AS C(id, location_index) + $jobs$, + NULL, + $vehicles$ + SELECT * FROM ( + VALUES (1, 1, 4) + ) AS C(id, start_index, end_index) + $vehicles$, + NULL, + NULL, + $matrix$ + SELECT * FROM ( + VALUES (1, 2, 2104), (1, 3, 197), (1, 4, 1299), + (2, 1, 2103), (2, 3, 2255), (2, 4, 3152), + (3, 1, 197), (3, 2, 2256), (3, 4, 1102), + (4, 1, 1299), (4, 2, 3153), (4, 3, 1102) + ) AS C(start_vid, end_vid, agg_cost) + $matrix$ +); + seq | vehicle_seq | vehicle_id | step_seq | step_type | task_id | arrival | travel_time | service_time | waiting_time | load +-----+-------------+------------+----------+-----------+---------+---------+-------------+--------------+--------------+------ + 1 | 1 | 1 | 1 | 1 | -1 | 0 | 0 | 0 | 0 | {} + 2 | 1 | 1 | 2 | 2 | 1414 | 2104 | 2104 | 0 | 0 | {} + 3 | 1 | 1 | 3 | 2 | 1515 | 4359 | 4359 | 0 | 0 | {} + 4 | 1 | 1 | 4 | 6 | -1 | 5461 | 5461 | 0 | 0 | {} +(4 rows) + +-- q3 +ROLLBACK; +ROLLBACK diff --git a/docqueries/vroom/doc-vrp_vroomJobs.test.sql b/docqueries/vroom/doc-vrp_vroomJobs.test.sql new file mode 100644 index 000000000..c2d39c778 --- /dev/null +++ b/docqueries/vroom/doc-vrp_vroomJobs.test.sql @@ -0,0 +1,36 @@ +\echo -- q1 +SELECT * +FROM vrp_vroomJobs( + 'SELECT * FROM vroom.jobs', + 'SELECT * FROM vroom.jobs_time_windows', + 'SELECT * FROM vroom.vehicles', + 'SELECT * FROM vroom.breaks', + 'SELECT * FROM vroom.breaks_time_windows', + 'SELECT * FROM vroom.matrix' +); +\echo -- q2 +SELECT * +FROM vrp_vroomJobs( + $jobs$ + SELECT * FROM ( + VALUES (1414, 2), (1515, 3) + ) AS C(id, location_index) + $jobs$, + NULL, + $vehicles$ + SELECT * FROM ( + VALUES (1, 1, 4) + ) AS C(id, start_index, end_index) + $vehicles$, + NULL, + NULL, + $matrix$ + SELECT * FROM ( + VALUES (1, 2, 2104), (1, 3, 197), (1, 4, 1299), + (2, 1, 2103), (2, 3, 2255), (2, 4, 3152), + (3, 1, 197), (3, 2, 2256), (3, 4, 1102), + (4, 1, 1299), (4, 2, 3153), (4, 3, 1102) + ) AS C(start_vid, end_vid, agg_cost) + $matrix$ +); +\echo -- q3 diff --git a/docqueries/vroom/doc-vrp_vroomShipments.result b/docqueries/vroom/doc-vrp_vroomShipments.result new file mode 100644 index 000000000..625293f5e --- /dev/null +++ b/docqueries/vroom/doc-vrp_vroomShipments.result @@ -0,0 +1,70 @@ +BEGIN; +BEGIN +SET client_min_messages TO NOTICE; +SET +-- q1 +SELECT * +FROM vrp_vroomShipments( + 'SELECT * FROM vroom.shipments', + 'SELECT * FROM vroom.shipments_time_windows', + 'SELECT * FROM vroom.vehicles', + 'SELECT * FROM vroom.breaks', + 'SELECT * FROM vroom.breaks_time_windows', + 'SELECT * FROM vroom.matrix' +); + seq | vehicle_seq | vehicle_id | step_seq | step_type | task_id | arrival | travel_time | service_time | waiting_time | load +-----+-------------+------------+----------+-----------+---------+---------+-------------+--------------+--------------+------ + 1 | 1 | 1 | 1 | 1 | -1 | 300 | 0 | 0 | 0 | {0} + 2 | 1 | 1 | 2 | 5 | 1 | 300 | 0 | 0 | 0 | {0} + 3 | 1 | 1 | 3 | 3 | 4 | 300 | 0 | 2250 | 6075 | {20} + 4 | 1 | 1 | 4 | 4 | 4 | 8700 | 75 | 2250 | 225 | {0} + 5 | 1 | 1 | 5 | 3 | 5 | 11265 | 165 | 2250 | 2085 | {10} + 6 | 1 | 1 | 6 | 3 | 3 | 15650 | 215 | 2250 | 0 | {30} + 7 | 1 | 1 | 7 | 4 | 5 | 17950 | 265 | 2250 | 225 | {20} + 8 | 1 | 1 | 8 | 4 | 3 | 20425 | 265 | 2250 | 200 | {0} + 9 | 1 | 1 | 9 | 6 | -1 | 22925 | 315 | 0 | 0 | {0} + 10 | 2 | 4 | 1 | 1 | -1 | 250 | 0 | 0 | 0 | {0} + 11 | 2 | 4 | 2 | 5 | 4 | 250 | 0 | 0 | 0 | {0} + 12 | 2 | 4 | 3 | 3 | 2 | 275 | 25 | 2250 | 100 | {10} + 13 | 2 | 4 | 4 | 3 | 1 | 2650 | 50 | 2250 | 0 | {20} + 14 | 2 | 4 | 5 | 4 | 2 | 4990 | 140 | 2250 | 0 | {10} + 15 | 2 | 4 | 6 | 4 | 1 | 7351 | 251 | 2250 | 17574 | {0} + 16 | 2 | 4 | 7 | 6 | -1 | 27200 | 276 | 0 | 0 | {0} +(16 rows) + +-- q2 +SELECT * +FROM vrp_vroomShipments( + $shipments$ + SELECT * FROM ( + VALUES (100, 1, 4) + ) AS C(id, p_location_index, d_location_index) + $shipments$, + NULL, + $vehicles$ + SELECT * FROM ( + VALUES (1, 1, 4) + ) AS C(id, start_index, end_index) + $vehicles$, + NULL, + NULL, + $matrix$ + SELECT * FROM ( + VALUES (1, 2, 2104), (1, 3, 197), (1, 4, 1299), + (2, 1, 2103), (2, 3, 2255), (2, 4, 3152), + (3, 1, 197), (3, 2, 2256), (3, 4, 1102), + (4, 1, 1299), (4, 2, 3153), (4, 3, 1102) + ) AS C(start_vid, end_vid, agg_cost) + $matrix$ +); + seq | vehicle_seq | vehicle_id | step_seq | step_type | task_id | arrival | travel_time | service_time | waiting_time | load +-----+-------------+------------+----------+-----------+---------+---------+-------------+--------------+--------------+------ + 1 | 1 | 1 | 1 | 1 | -1 | 0 | 0 | 0 | 0 | {} + 2 | 1 | 1 | 2 | 3 | 100 | 0 | 0 | 0 | 0 | {} + 3 | 1 | 1 | 3 | 4 | 100 | 1299 | 1299 | 0 | 0 | {} + 4 | 1 | 1 | 4 | 6 | -1 | 1299 | 1299 | 0 | 0 | {} +(4 rows) + +-- q3 +ROLLBACK; +ROLLBACK diff --git a/docqueries/vroom/doc-vrp_vroomShipments.test.sql b/docqueries/vroom/doc-vrp_vroomShipments.test.sql new file mode 100644 index 000000000..71fc684a6 --- /dev/null +++ b/docqueries/vroom/doc-vrp_vroomShipments.test.sql @@ -0,0 +1,36 @@ +\echo -- q1 +SELECT * +FROM vrp_vroomShipments( + 'SELECT * FROM vroom.shipments', + 'SELECT * FROM vroom.shipments_time_windows', + 'SELECT * FROM vroom.vehicles', + 'SELECT * FROM vroom.breaks', + 'SELECT * FROM vroom.breaks_time_windows', + 'SELECT * FROM vroom.matrix' +); +\echo -- q2 +SELECT * +FROM vrp_vroomShipments( + $shipments$ + SELECT * FROM ( + VALUES (100, 1, 4) + ) AS C(id, p_location_index, d_location_index) + $shipments$, + NULL, + $vehicles$ + SELECT * FROM ( + VALUES (1, 1, 4) + ) AS C(id, start_index, end_index) + $vehicles$, + NULL, + NULL, + $matrix$ + SELECT * FROM ( + VALUES (1, 2, 2104), (1, 3, 197), (1, 4, 1299), + (2, 1, 2103), (2, 3, 2255), (2, 4, 3152), + (3, 1, 197), (3, 2, 2256), (3, 4, 1102), + (4, 1, 1299), (4, 2, 3153), (4, 3, 1102) + ) AS C(start_vid, end_vid, agg_cost) + $matrix$ +); +\echo -- q3 diff --git a/docqueries/vroom/test.conf b/docqueries/vroom/test.conf new file mode 100644 index 000000000..8cd4cabd0 --- /dev/null +++ b/docqueries/vroom/test.conf @@ -0,0 +1,21 @@ +#!/usr/bin/perl -w + +%main::tests = ( + 'any' => { + 'comment' => 'VRP with VROOM tests.', + 'data' => [ ], + 'tests' => [qw( + doc-vrp_vroom + doc-vrp_vroomJobs + doc-vrp_vroomShipments + )], + 'documentation' => [qw( + doc-vrp_vroom + doc-vrp_vroomJobs + doc-vrp_vroomShipments + )] + }, + +); + +1; From e16ce6b1e33bd3be07fa331d24526a9359e6ae69 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:35:07 +0530 Subject: [PATCH 16/20] [vroom][tools] Added vroomdata --- tools/testers/doc_queries_generator.pl | 1 + tools/testers/general_pgtap_tests.sql | 29 ++++ tools/testers/no_crash_test.sql | 16 ++- tools/testers/sampledata.sql | 2 +- tools/testers/setup_db.sql | 2 + tools/testers/vroomdata.sql | 175 +++++++++++++++++++++++++ 6 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 tools/testers/general_pgtap_tests.sql create mode 100644 tools/testers/vroomdata.sql diff --git a/tools/testers/doc_queries_generator.pl b/tools/testers/doc_queries_generator.pl index e75084211..293906708 100755 --- a/tools/testers/doc_queries_generator.pl +++ b/tools/testers/doc_queries_generator.pl @@ -244,6 +244,7 @@ sub run_test { # refresh the database each time it enters a new directory mysystem("$psql $connopts -A -t -q -f tools/testers/sampledata.sql $DBNAME >> $TMP2 2>\&1 "); + mysystem("$psql $connopts -A -t -q -f tools/testers/vroomdata.sql $DBNAME >> $TMP2 2>\&1 "); mysystem("$psql $connopts -A -t -q -f tools/testers/matrix_new_values.sql $DBNAME >> $TMP2 2>\&1 "); # process data for the tests (if any) diff --git a/tools/testers/general_pgtap_tests.sql b/tools/testers/general_pgtap_tests.sql new file mode 100644 index 000000000..16c22a244 --- /dev/null +++ b/tools/testers/general_pgtap_tests.sql @@ -0,0 +1,29 @@ +-- checks the minimum version version for C++ code +CREATE OR REPLACE FUNCTION public.min_lib_version(min_version TEXT) +RETURNS BOOLEAN AS +$BODY$ +DECLARE val BOOLEAN; +BEGIN +WITH + current_version AS (SELECT string_to_array(regexp_replace((SELECT library FROM vrp_full_version()), '.*-', '', 'g'),'.')::int[] AS version), + asked_version AS (SELECT string_to_array(min_version, '.')::int[] AS version) + SELECT (current_version.version >= asked_version.version) FROM current_version, asked_version INTO val; + RETURN val; +END; +$BODY$ +LANGUAGE plpgsql; + +-- checks the minimum version version for SQL code +CREATE OR REPLACE FUNCTION public.min_version(min_version TEXT) +RETURNS BOOLEAN AS +$BODY$ +DECLARE val BOOLEAN; +BEGIN +WITH + current_version AS (SELECT string_to_array(regexp_replace(vrp_version(), '-.*', '', 'g'),'.')::int[] AS version), + asked_version AS (SELECT string_to_array(min_version, '.')::int[] AS version) + SELECT (current_version.version >= asked_version.version) FROM current_version, asked_version INTO val; + RETURN val; +END; +$BODY$ +LANGUAGE plpgsql; diff --git a/tools/testers/no_crash_test.sql b/tools/testers/no_crash_test.sql index 1d530acab..ddc1c011c 100644 --- a/tools/testers/no_crash_test.sql +++ b/tools/testers/no_crash_test.sql @@ -1,5 +1,7 @@ -CREATE OR REPLACE FUNCTION public.no_crash_test(func TEXT, params TEXT[], subs TEXT[]) +CREATE OR REPLACE FUNCTION public.no_crash_test(func TEXT, params TEXT[], subs TEXT[], + error_messages TEXT[] DEFAULT ARRAY[]::TEXT[], + non_empty_args INTEGER[] DEFAULT ARRAY[0]::INTEGER[]) RETURNS SETOF TEXT AS $BODY$ DECLARE @@ -27,11 +29,15 @@ BEGIN -- RAISE WARNING '%', q1; - RETURN query SELECT * FROM lives_ok(q1); - IF i = 0 THEN - RETURN query SELECT * FROM isnt_empty(q1); + IF array_length(error_messages, 1) >= i AND error_messages[i] != '' THEN + RETURN query SELECT throws_ok(q1, error_messages[i]); ELSE - RETURN query SELECT * FROM is_empty(q1); + RETURN query SELECT * FROM lives_ok(q1); + IF i = ANY(non_empty_args) THEN + RETURN query SELECT * FROM isnt_empty(q1); + ELSE + RETURN query SELECT * FROM is_empty(q1); + END IF; END IF; END LOOP; diff --git a/tools/testers/sampledata.sql b/tools/testers/sampledata.sql index d94042411..bf616ef63 100644 --- a/tools/testers/sampledata.sql +++ b/tools/testers/sampledata.sql @@ -10,6 +10,7 @@ DROP TABLE IF EXISTS public.edge_table; DROP TABLE IF EXISTS public.edge_table_vertices_pgr; DROP TABLE IF EXISTS public.vehicles_1; DROP TABLE IF EXISTS public.orders_1; +DROP TABLE IF EXISTS public.edges_matrix; --EDGE TABLE CREATE start CREATE TABLE public.edge_table ( @@ -1445,4 +1446,3 @@ COPY example2.shipments (p_tw_open, p_id, d_id, amount, booking_date) FROM stdin 2019-12-13 15:15:00 3629761401900 3624961402867 1 2019-12-12 08:15:27.294694 \. - diff --git a/tools/testers/setup_db.sql b/tools/testers/setup_db.sql index 6d8116f09..21b5d6a66 100644 --- a/tools/testers/setup_db.sql +++ b/tools/testers/setup_db.sql @@ -23,5 +23,7 @@ BEGIN; \i vrppdtw_data.sql \i solomon_100_rc101.data.sql \i no_crash_test.sql + \i general_pgtap_tests.sql + \i vroomdata.sql END; diff --git a/tools/testers/vroomdata.sql b/tools/testers/vroomdata.sql new file mode 100644 index 000000000..bad55e493 --- /dev/null +++ b/tools/testers/vroomdata.sql @@ -0,0 +1,175 @@ +DROP SCHEMA IF EXISTS vroom CASCADE; +CREATE SCHEMA vroom; + +DROP TABLE IF EXISTS vroom.jobs; +DROP TABLE IF EXISTS vroom.jobs_time_windows; +DROP TABLE IF EXISTS vroom.shipments; +DROP TABLE IF EXISTS vroom.shipments_time_windows; +DROP TABLE IF EXISTS vroom.vehicles; +DROP TABLE IF EXISTS vroom.breaks; +DROP TABLE IF EXISTS vroom.breaks_time_windows; +DROP TABLE IF EXISTS vroom.matrix; + + +-- JOBS TABLE start +CREATE TABLE vroom.jobs ( + id BIGSERIAL PRIMARY KEY, + location_index BIGINT, + service INTEGER, + delivery BIGINT[], + pickup BIGINT[], + skills INTEGER[], + priority INTEGER +); + +INSERT INTO vroom.jobs ( + id, location_index, service, delivery, pickup, skills, priority) + VALUES +(1, 1, 250, ARRAY[20], ARRAY[20], ARRAY[0], 0), +(2, 2, 250, ARRAY[30], ARRAY[30], ARRAY[0], 0), +(3, 3, 250, ARRAY[10], ARRAY[10], ARRAY[0], 0), +(4, 3, 250, ARRAY[40], ARRAY[40], ARRAY[0], 0), +(5, 4, 250, ARRAY[20], ARRAY[20], ARRAY[0], 0); +-- JOBS TABLE end + + +-- JOBS TIME WINDOWS TABLE start +CREATE TABLE vroom.jobs_time_windows ( + id BIGINT REFERENCES vroom.jobs(id), + tw_open INTEGER, + tw_close INTEGER +); + +INSERT INTO vroom.jobs_time_windows ( + id, tw_open, tw_close) + VALUES +(1, 3625, 4375), +(2, 1250, 2000), +(3, 2725, 3475), +(4, 3525, 4275), +(5, 1025, 1775); +-- JOBS TIME WINDOWS TABLE end + + +-- SHIPMENTS TABLE start +CREATE TABLE vroom.shipments ( + id BIGSERIAL PRIMARY KEY, + p_location_index BIGINT, + p_service INTEGER, + d_location_index BIGINT, + d_service INTEGER, + amount BIGINT[], + skills INTEGER[], + priority INTEGER +); + +INSERT INTO vroom.shipments ( + id, p_location_index, p_service, d_location_index, d_service, + amount, skills, priority) + VALUES +(1, 3, 2250, 5, 2250, ARRAY[10], ARRAY[0], 0), +(2, 5, 2250, 6, 2250, ARRAY[10], ARRAY[0], 0), +(3, 1, 2250, 2, 2250, ARRAY[20], ARRAY[0], 0), +(4, 1, 2250, 4, 2250, ARRAY[20], ARRAY[0], 0), +(5, 2, 2250, 2, 2250, ARRAY[10], ARRAY[0], 0); +-- SHIPMENTS TABLE end + + +-- SHIPMENTS TIME WINDOWS TABLE start +CREATE TABLE vroom.shipments_time_windows ( + id BIGINT REFERENCES vroom.shipments(id), + kind CHAR(1), + tw_open INTEGER, + tw_close INTEGER +); + +INSERT INTO vroom.shipments_time_windows ( + id, kind, tw_open, tw_close) + VALUES +(1, 'p', 1625, 3650), +(1, 'd', 24925, 26700), +(2, 'p', 375, 1675), +(2, 'd', 4250, 5625), +(3, 'p', 15525, 17550), +(3, 'd', 20625, 21750), +(4, 'p', 6375, 8100), +(4, 'd', 8925, 10250), +(5, 'p', 13350, 15125), +(5, 'd', 18175, 19550); +-- SHIPMENTS TIME WINDOWS TABLE end + + +-- VEHICLES TABLE start +CREATE TABLE vroom.vehicles ( + id BIGSERIAL PRIMARY KEY, + start_index BIGINT, + end_index BIGINT, + capacity BIGINT[], + skills INTEGER[], + tw_open INTEGER, + tw_close INTEGER, + speed_factor FLOAT +); + +INSERT INTO vroom.vehicles ( + id, start_index, end_index, capacity, skills, + tw_open, tw_close, speed_factor) + VALUES +(1, 1, 1, ARRAY[200], ARRAY[0], 0, 30900, 1.0), +(2, 1, 3, ARRAY[200], ARRAY[0], 100, 30900, 1.0), +(3, 1, 1, ARRAY[200], ARRAY[0], 0, 30900, 1.0), +(4, 3, 3, ARRAY[200], ARRAY[0], 0, 30900, 1.0); +-- VEHICLES TABLE end + + +-- BREAKS TABLE start +CREATE TABLE vroom.breaks ( + id BIGINT PRIMARY KEY, + vehicle_id BIGINT REFERENCES vroom.vehicles(id), + service INTEGER +); + +INSERT INTO vroom.breaks ( + id, vehicle_id, service) + VALUES +(1, 1, 0), +(2, 2, 10), +(3, 3, 0), +(4, 4, 0); +-- BREAKS TABLE end + + +-- BREAKS TIME WINDOWS TABLE start +CREATE TABLE vroom.breaks_time_windows ( + id BIGINT REFERENCES vroom.breaks(id), + tw_open INTEGER, + tw_close INTEGER +); + +INSERT INTO vroom.breaks_time_windows ( + id, tw_open, tw_close) + VALUES +(1, 250, 300), +(2, 250, 275), +(3, 0, 0), +(4, 250, 250); +-- BREAKS TIME WINDOWS TABLE end + + +-- MATRIX TABLE start +CREATE TABLE vroom.matrix ( + start_vid BIGINT, + end_vid BIGINT, + agg_cost INTEGER +); + +INSERT INTO vroom.matrix ( + start_vid, end_vid, agg_cost) + VALUES +(1, 1, 0), (1, 2, 50), (1, 3, 90), (1, 4, 75), (1, 5, 106), (1, 6, 127), +(2, 1, 50), (2, 2, 0), (2, 3, 125), (2, 4, 90), (2, 5, 145), (2, 6, 127), +(3, 1, 90), (3, 2, 125), (3, 3, 0), (3, 4, 50), (3, 5, 25), (3, 6, 90), +(4, 1, 75), (4, 2, 90), (4, 3, 50), (4, 4, 0), (4, 5, 75), (4, 6, 55), +(5, 1, 106), (5, 2, 145), (5, 3, 25), (5, 4, 75), (5, 5, 0), (5, 6, 111), +(6, 1, 127), (6, 2, 127), (6, 3, 90), (6, 4, 55), (6, 5, 111), (6, 6, 0); +-- MATRIX TABLE end From 714323c79debbb01ac0b8d9f9093df339b10c38a Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:35:24 +0530 Subject: [PATCH 17/20] [vroom][pgtap] Added vroom pgtap tests --- pgtap/vroom/edge_cases.sql | 805 +++++++++++++++++++ pgtap/vroom/inner_query.sql | 388 +++++++++ pgtap/vroom/no_crash_test.sql | 145 ++++ pgtap/vroom/types_check.sql | 100 +++ pgtap/vroom/vroomJobs-eq-vroom.test.sql | 67 ++ pgtap/vroom/vroomShipments-eq-vroom.test.sql | 67 ++ 6 files changed, 1572 insertions(+) create mode 100644 pgtap/vroom/edge_cases.sql create mode 100644 pgtap/vroom/inner_query.sql create mode 100644 pgtap/vroom/no_crash_test.sql create mode 100644 pgtap/vroom/types_check.sql create mode 100644 pgtap/vroom/vroomJobs-eq-vroom.test.sql create mode 100644 pgtap/vroom/vroomShipments-eq-vroom.test.sql diff --git a/pgtap/vroom/edge_cases.sql b/pgtap/vroom/edge_cases.sql new file mode 100644 index 000000000..39bb24f3f --- /dev/null +++ b/pgtap/vroom/edge_cases.sql @@ -0,0 +1,805 @@ +BEGIN; +SET search_path TO 'vroom', 'public'; +SET client_min_messages TO ERROR; + +SELECT CASE WHEN min_version('0.2.0') THEN plan (38) ELSE plan(1) END; + +CREATE OR REPLACE FUNCTION edge_cases() +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + fn TEXT; + start_sql TEXT; + rest_sql TEXT; +BEGIN + + IF NOT min_version('0.2.0') THEN + RETURN QUERY + SELECT skip(1, 'Function is new on 0.2.0'); + RETURN; + END IF; + + PREPARE jobs AS SELECT * FROM jobs; + PREPARE empty_jobs AS SELECT * FROM jobs WHERE id = -1; + + PREPARE jobs_time_windows AS SELECT * FROM jobs_time_windows; + PREPARE empty_jobs_time_windows AS SELECT * FROM jobs_time_windows WHERE id = -1; + + PREPARE shipments AS SELECT * FROM shipments; + PREPARE empty_shipments AS SELECT * FROM shipments WHERE id = -1; + + PREPARE shipments_time_windows AS SELECT * FROM shipments_time_windows; + PREPARE empty_shipments_time_windows AS SELECT * FROM shipments_time_windows WHERE id = -1; + + PREPARE vehicles AS SELECT * FROM vehicles; + PREPARE empty_vehicles AS SELECT * FROM vehicles WHERE id = -1; + + PREPARE breaks AS SELECT * FROM breaks; + PREPARE empty_breaks AS SELECT * FROM breaks WHERE id = -1; + + PREPARE breaks_time_windows AS SELECT * FROM breaks_time_windows; + PREPARE empty_breaks_time_windows AS SELECT * FROM breaks_time_windows WHERE id = -1; + + PREPARE matrix AS SELECT * FROM matrix; + PREPARE empty_matrix AS SELECT * FROM matrix WHERE start_vid = -1; + + PREPARE vroom_sql AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + + + -- tests for no jobs/shipments, no vehicles, or no matrix + + PREPARE no_jobs_and_shipments AS + SELECT * FROM vrp_vroom( + 'empty_jobs', + 'jobs_time_windows', + 'empty_shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT is_empty('no_jobs_and_shipments', 'Problem with no jobs and shipments'); + + PREPARE no_vehicles AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'empty_vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT is_empty('no_vehicles', 'Problem with no vehicles'); + + PREPARE no_matrix AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'empty_matrix' + ); + RETURN QUERY + SELECT is_empty('no_matrix', 'Problem with no cost matrix'); + + + -- priority range test (jobs) + + PREPARE jobs_neg_priority AS + SELECT * FROM vrp_vroom( + 'SELECT id, location_index, service, delivery, pickup, skills, -1 AS priority FROM jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'jobs_neg_priority', + 'XX000', + 'Unexpected Negative value in column priority', + 'Problem with negative priority jobs' + ); + + PREPARE jobs_101_priority AS + SELECT * FROM vrp_vroom( + 'SELECT id, location_index, service, delivery, pickup, skills, 101 AS priority FROM jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'jobs_101_priority', + 'XX000', + 'Priority exceeds the max priority 100', + 'Problem with > 100 priority jobs' + ); + + PREPARE jobs_zero_priority AS + SELECT * FROM vrp_vroom( + 'SELECT id, location_index, service, delivery, pickup, skills, 0 AS priority FROM jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('jobs_zero_priority', 'Problem with 0 priority jobs'); + + PREPARE jobs_100_priority AS + SELECT * FROM vrp_vroom( + 'SELECT id, location_index, service, delivery, pickup, skills, 0 AS priority FROM jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('jobs_100_priority', 'Problem with 100 priority jobs'); + + + -- priority range tests (shipments) + + PREPARE shipments_neg_priority AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'SELECT id, p_location_index, p_service, d_location_index, d_service, + amount, skills, -1 AS priority FROM shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'shipments_neg_priority', + 'XX000', + 'Unexpected Negative value in column priority', + 'Problem with negative priority shipments' + ); + + PREPARE shipments_101_priority AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'SELECT id, p_location_index, p_service, d_location_index, d_service, + amount, skills, 101 AS priority FROM shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'shipments_101_priority', + 'XX000', + 'Priority exceeds the max priority 100', + 'Problem with > 100 priority shipments' + ); + + PREPARE shipments_zero_priority AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'SELECT id, p_location_index, p_service, d_location_index, d_service, + amount, skills, 0 AS priority FROM shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('shipments_zero_priority', 'Problem with 0 priority shipments'); + + PREPARE shipments_100_priority AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'SELECT id, p_location_index, p_service, d_location_index, d_service, + amount, skills, 100 AS priority FROM shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('shipments_100_priority', 'Problem with 100 priority shipments'); + + + -- Missing id on matrix test + + PREPARE missing_id_on_matrix AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'SELECT * FROM matrix WHERE start_vid != 5 AND end_vid != 5' + ); + RETURN QUERY + SELECT throws_ok( + 'missing_id_on_matrix', + 'XX000', + 'An Infinity value was found on the Matrix. Might be missing information of a node', + 'Problem with missing node 5 on the cost matrix' + ); + + PREPARE missing_same_vid_on_matrix AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'SELECT * FROM matrix WHERE start_vid != end_vid' + ); + RETURN QUERY + SELECT set_eq('missing_same_vid_on_matrix', 'vroom_sql', 'Cost between same vertex is always 0'); + + PREPARE missing_reverse_cost_on_matrix AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'SELECT * FROM matrix WHERE start_vid < end_vid' + ); + RETURN QUERY + SELECT set_eq('missing_reverse_cost_on_matrix', 'vroom_sql', 'Reverse cost is equal to the cost, if not specified'); + + + -- jobs time windows validate + + PREPARE jobs_equal_tw AS SELECT id, 3000 AS tw_open, 3000 AS tw_close FROM jobs_time_windows; + PREPARE jobs_invalid_tw AS SELECT id, 3001 AS tw_open, 3000 AS tw_close FROM jobs_time_windows; + + PREPARE jobs_equal_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_equal_tw', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('jobs_equal_tw_problem', 'Problem with jobs having equal time windows'); + + PREPARE jobs_invalid_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_invalid_tw', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'jobs_invalid_tw_problem', + 'XX000', + 'Invalid time window (3001, 3000)', + 'Problem with jobs having invalid time windows' + ); + + + -- shipments time windows validate + + PREPARE shipments_equal_tw AS SELECT id, kind, 3000 AS tw_open, 3000 AS tw_close FROM shipments_time_windows; + PREPARE shipments_invalid_tw AS SELECT id, kind, 3001 AS tw_open, 3000 AS tw_close FROM shipments_time_windows; + + PREPARE shipments_equal_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_equal_tw', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('shipments_equal_tw_problem', 'Problem with shipments having equal time windows'); + + PREPARE shipments_invalid_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_invalid_tw', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'shipments_invalid_tw_problem', + 'XX000', + 'Invalid time window (3001, 3000)', + 'Problem with shipments having invalid time windows' + ); + + + -- breaks time windows validate + + PREPARE breaks_equal_tw AS SELECT id, 3000 AS tw_open, 3000 AS tw_close FROM breaks_time_windows; + PREPARE breaks_invalid_tw AS SELECT id, 3001 AS tw_open, 3000 AS tw_close FROM breaks_time_windows; + + PREPARE breaks_equal_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_equal_tw', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('breaks_equal_tw_problem', 'Problem with breaks having equal time windows'); + + PREPARE breaks_invalid_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_invalid_tw', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'breaks_invalid_tw_problem', + 'XX000', + 'Invalid time window (3001, 3000)', + 'Problem with breaks having invalid time windows' + ); + + + -- vehicles time windows validate + + PREPARE vehicles_equal_tw AS + SELECT id, start_index, end_index, capacity, skills, 3000 AS tw_open, 3000 AS tw_close, speed_factor FROM vehicles; + PREPARE vehicles_invalid_tw AS + SELECT id, start_index, end_index, capacity, skills, 3001 AS tw_open, 3000 AS tw_close, speed_factor FROM vehicles; + + PREPARE vehicles_equal_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_equal_tw', + 'empty_breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT lives_ok('vehicles_equal_tw_problem', 'Problem with vehicles having equal time windows'); + + PREPARE vehicles_invalid_tw_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_invalid_tw', + 'empty_breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'vehicles_invalid_tw_problem', + 'XX000', + 'Invalid time window (3001, 3000)', + 'Problem with vehicles having invalid time windows' + ); + + + -- Query with jobs having only one of delivery or pickup amount should succeed + + PREPARE jobs_only_delivery AS SELECT id, location_index, service, delivery, skills, priority FROM jobs; + PREPARE jobs_only_pickup AS SELECT id, location_index, service, pickup, skills, priority FROM jobs; + PREPARE jobs_only_delivery_problem AS + SELECT * FROM vrp_vroom( + 'jobs_only_delivery', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + PREPARE jobs_only_pickup_problem AS + SELECT * FROM vrp_vroom( + 'jobs_only_pickup', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY SELECT lives_ok('jobs_only_delivery_problem', 'Problem with jobs having only delivery amount'); + RETURN QUERY SELECT lives_ok('jobs_only_pickup_problem', 'Problem with jobs having only pickup amount'); + + + -- Query with vehicles having only one of start_index or end_index should succeed + + PREPARE vehicles_only_start_index AS SELECT id, start_index, capacity, skills, tw_open, tw_close, speed_factor FROM vehicles; + PREPARE vehicles_only_end_index AS SELECT id, end_index, capacity, skills, tw_open, tw_close, speed_factor FROM vehicles; + PREPARE vehicles_only_start_index_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_only_start_index', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + PREPARE vehicles_only_end_index_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_only_end_index', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY SELECT lives_ok('vehicles_only_start_index_problem', 'Problem with vehicles having only start_index'); + RETURN QUERY SELECT lives_ok('vehicles_only_end_index_problem', 'Problem with vehicles having only end_index'); + + + -- Query with vehicles having neither start_index nor end_index must fail + + PREPARE vehicles_no_index AS SELECT id, capacity, skills, tw_open, tw_close, speed_factor FROM vehicles; + PREPARE vehicles_no_index_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_no_index', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT throws_ok( + 'vehicles_no_index_problem', + 'XX000', + 'At least one out of start_index or end_index must be present', + 'Problem with vehicles having neither start_index nor end_index' + ); + + + -- Number of quantities of delivery, pickup, amount and capacity must be the same + + PREPARE jobs_inconsistent_delivery AS + SELECT id, location_index, service, ARRAY[10, 20]::BIGINT[] AS delivery, pickup, skills, priority FROM jobs; + PREPARE jobs_inconsistent_pickup AS + SELECT id, location_index, service, delivery, ARRAY[10, 20]::BIGINT[] AS pickup, skills, priority FROM jobs; + PREPARE shipments_inconsistent_amount AS + SELECT id, p_location_index, p_service, d_location_index, d_service, ARRAY[10, 20]::BIGINT[] AS amount, skills, priority FROM shipments; + PREPARE vehicles_inconsistent_capacity AS + SELECT id, start_index, end_index, ARRAY[10, 20]::BIGINT[] AS capacity, skills, tw_open, tw_close, speed_factor FROM vehicles; + + PREPARE jobs_inconsistent_delivery_problem AS + SELECT * FROM vrp_vroom( + 'jobs_inconsistent_delivery', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + PREPARE jobs_inconsistent_pickup_problem AS + SELECT * FROM vrp_vroom( + 'jobs_inconsistent_pickup', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + PREPARE shipments_inconsistent_amount_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments_inconsistent_amount', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + PREPARE vehicles_inconsistent_capacity_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_inconsistent_capacity', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + + + RETURN QUERY + SELECT throws_ok( + 'jobs_inconsistent_delivery_problem', + 'XX000', + 'Inconsistent delivery length: 2 instead of 1.', + 'Problem with jobs having inconsistent delivery length' + ); + + RETURN QUERY + SELECT throws_ok( + 'jobs_inconsistent_pickup_problem', + 'XX000', + 'Inconsistent pickup length: 2 instead of 1.', + 'Problem with jobs having inconsistent pickup length' + ); + + RETURN QUERY + SELECT throws_ok( + 'shipments_inconsistent_amount_problem', + 'XX000', + 'Inconsistent delivery length: 2 instead of 1.', + 'Problem with shipments having inconsistent amount length' + ); + + -- Length is determined by vehicle capacity, so this error message + -- denotes that job delivery has inconsistent length + RETURN QUERY + SELECT throws_ok( + 'vehicles_inconsistent_capacity_problem', + 'XX000', + 'Inconsistent delivery length: 1 instead of 2.', + 'Problem with vehicles having inconsistent capacity length' + ); + + + -- If speed_factor and agg_cost are multiplied by same number, result should be same + + PREPARE vehicles_2x_speed AS + SELECT id, start_index, end_index, capacity, skills, tw_open, tw_close, 2 * speed_factor AS speed_factor FROM vehicles; + PREPARE matrix_2x_distance AS + SELECT start_vid, end_vid, 2 * agg_cost AS agg_cost FROM matrix; + + PREPARE vehicles_4x_speed AS + SELECT id, start_index, end_index, capacity, skills, tw_open, tw_close, 4 * speed_factor AS speed_factor FROM vehicles; + PREPARE matrix_4x_distance AS + SELECT start_vid, end_vid, 4 * agg_cost AS agg_cost FROM matrix; + + PREPARE vehicles_2x_speed_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_2x_speed', + 'breaks', + 'breaks_time_windows', + 'matrix_2x_distance' + ); + PREPARE vehicles_4x_speed_problem AS + SELECT * FROM vrp_vroom( + 'jobs', + 'jobs_time_windows', + 'shipments', + 'shipments_time_windows', + 'vehicles_4x_speed', + 'breaks', + 'breaks_time_windows', + 'matrix_4x_distance' + ); + RETURN QUERY + SELECT set_eq('vehicles_2x_speed_problem', 'vroom_sql', 'Problem with 2x vehicle speed and distance'); + RETURN QUERY + SELECT set_eq('vehicles_4x_speed_problem', 'vroom_sql', 'Problem with 4x vehicle speed and distance'); + + + -- one job/shipment tests + + -- Column Names: + -- seq, vehicle_seq, vehicle_id, step_seq, step_type, task_id, + -- arrival, travel_time, service_time, waiting_time, load + + PREPARE one_job_q1 AS + SELECT * FROM vrp_vroom( + 'SELECT * FROM jobs WHERE id = 1', + 'jobs_time_windows', + 'empty_shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT set_eq('one_job_q1', + $$ + VALUES + (1, 1, 1, 1, 1, -1, 300, 0, 0, 0, ARRAY[20]), + (2, 1, 1, 2, 5, 1, 300, 0, 0, 0, ARRAY[20]), + (3, 1, 1, 3, 2, 1, 300, 0, 250, 3325, ARRAY[20]), + (4, 1, 1, 4, 6, -1, 3875, 0, 0, 0, ARRAY[20]) + $$, + 'Problem with only one job having id 1' + ); + + PREPARE one_job_q2 AS + SELECT * FROM vrp_vroom( + 'SELECT * FROM jobs WHERE id = 5', + 'jobs_time_windows', + 'empty_shipments', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT set_eq('one_job_q2', + $$ + VALUES + (1, 1, 4, 1, 1, -1, 250, 0, 0, 0, ARRAY[20]), + (2, 1, 4, 2, 5, 4, 250, 0, 0, 0, ARRAY[20]), + (3, 1, 4, 3, 2, 5, 300, 50, 250, 725, ARRAY[20]), + (4, 1, 4, 4, 6, -1, 1325, 100, 0, 0, ARRAY[20]) + $$, + 'Problem with only one job having id 5' + ); + + PREPARE one_shipment_q1 AS + SELECT * FROM vrp_vroom( + 'empty_jobs', + 'jobs_time_windows', + 'SELECT * FROM shipments WHERE id = 1', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT set_eq('one_shipment_q1', + $$ + VALUES + (1, 1, 4, 1, 1, -1, 250, 0, 0, 0, ARRAY[0]), + (2, 1, 4, 2, 5, 4, 250, 0, 0, 0, ARRAY[0]), + (3, 1, 4, 3, 3, 1, 250, 0, 2250, 1375, ARRAY[10]), + (4, 1, 4, 4, 4, 1, 3900, 25, 2250, 21025, ARRAY[0]), + (5, 1, 4, 5, 6, -1, 27200, 50, 0, 0, ARRAY[0]) + $$, + 'Problem with only one shipment having id 1' + ); + + PREPARE one_shipment_q2 AS + SELECT * FROM vrp_vroom( + 'empty_jobs', + 'jobs_time_windows', + 'SELECT * FROM shipments WHERE id = 5', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT set_eq('one_shipment_q2', + $$ + VALUES + (1, 1, 1, 1, 1, -1, 300, 0, 0, 0, ARRAY[0]), + (2, 1, 1, 2, 5, 1, 300, 0, 0, 0, ARRAY[0]), + (3, 1, 1, 3, 3, 5, 350, 50, 2250, 13000, ARRAY[10]), + (4, 1, 1, 4, 4, 5, 15600, 50, 2250, 2575, ARRAY[0]), + (5, 1, 1, 5, 6, -1, 20475, 100, 0, 0, ARRAY[0]) + $$, + 'Problem with only one shipment having id 5' + ); + + PREPARE one_job_shipment AS + SELECT * FROM vrp_vroom( + 'SELECT * FROM jobs WHERE id = 2', + 'jobs_time_windows', + 'SELECT * FROM shipments WHERE id = 2', + 'shipments_time_windows', + 'vehicles', + 'breaks', + 'breaks_time_windows', + 'matrix' + ); + RETURN QUERY + SELECT set_eq('one_job_shipment', + $$ + VALUES + (1, 1, 1, 1, 1, -1, 300, 0, 0, 0, ARRAY[30]), + (2, 1, 1, 2, 5, 1, 300, 0, 0, 0, ARRAY[30]), + (3, 1, 1, 3, 2, 2, 350, 50, 250, 900, ARRAY[30]), + (4, 1, 1, 4, 6, -1, 1550, 100, 0, 0, ARRAY[30]), + (5, 2, 4, 1, 1, -1, 250, 0, 0, 0, ARRAY[0]), + (6, 2, 4, 2, 5, 4, 250, 0, 0, 0, ARRAY[0]), + (7, 2, 4, 3, 3, 2, 275, 25, 2250, 100, ARRAY[10]), + (8, 2, 4, 4, 4, 2, 2736, 136, 2250, 1514, ARRAY[0]), + (9, 2, 4, 5, 6, -1, 6590, 226, 0, 0, ARRAY[0]) + $$, + 'Problem with one job and one shipment having id 2' + ); + +END; +$BODY$ +LANGUAGE plpgsql; + + +SELECT edge_cases(); + +SELECT * FROM finish(); +ROLLBACK; diff --git a/pgtap/vroom/inner_query.sql b/pgtap/vroom/inner_query.sql new file mode 100644 index 000000000..a94be6995 --- /dev/null +++ b/pgtap/vroom/inner_query.sql @@ -0,0 +1,388 @@ +BEGIN; +SET search_path TO 'vroom', 'public'; + +SELECT CASE WHEN min_version('0.2.0') THEN plan (564) ELSE plan(1) END; + +/* +SELECT * FROM vrp_vroom( + $$SELECT id, location_index, service, delivery, pickup, skills, priority FROM jobs$$, + $$SELECT id, tw_open, tw_close FROM jobs_time_windows$$, + $$SELECT id, p_location_index, p_service, d_location_index, d_service, amount, skills, priority FROM shipments$$, + $$SELECT id, kind, tw_open, tw_close FROM shipments_time_windows$$, + $$SELECT id, start_index, end_index, capacity, skills, tw_open, tw_close FROM vehicles$$, + $$SELECT id, vehicle_id, service FROM breaks$$, + $$SELECT id, tw_open, tw_close FROM breaks_time_windows$$, + $$SELECT start_vid, end_vid, agg_cost FROM matrix$$ +); +*/ + +CREATE OR REPLACE FUNCTION test_value(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT, params TEXT[], parameter TEXT, accept TEXT[], reject TEXT[]) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + end_sql TEXT; + query TEXT; + p TEXT; + type_name TEXT; +BEGIN + start_sql = 'SELECT * FROM ' || fn || '(' || start_sql || '$$ SELECT '; + FOREACH p IN ARRAY params + LOOP + IF p = parameter THEN CONTINUE; + END IF; + start_sql = start_sql || p || ', '; + END LOOP; + end_sql = ' FROM ' || inner_query_table || '$$' || rest_sql; + + FOREACH type_name IN ARRAY accept + LOOP + query := start_sql || parameter || '::' || type_name || end_sql; + RETURN query SELECT lives_ok(query); + END LOOP; + + FOREACH type_name IN ARRAY reject + LOOP + query := start_sql || parameter || '::' || type_name || end_sql; + RETURN query SELECT throws_ok(query); + END LOOP; +END; +$BODY$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_anyInteger(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT, params TEXT[], parameter TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + accept TEXT[] := ARRAY['SMALLINT', 'INTEGER', 'BIGINT']; + reject TEXT[] := ARRAY['REAL', 'FLOAT8', 'NUMERIC']; +BEGIN + RETURN query SELECT test_value(fn, inner_query_table, start_sql, rest_sql, params, parameter, accept, reject); +END; +$BODY$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_Integer(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT, params TEXT[], parameter TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + accept TEXT[] := ARRAY['SMALLINT', 'INTEGER']; + reject TEXT[] := ARRAY['BIGINT', 'REAL', 'FLOAT8', 'NUMERIC']; +BEGIN + RETURN query SELECT test_value(fn, inner_query_table, start_sql, rest_sql, params, parameter, accept, reject); +END; +$BODY$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_anyArrayInteger(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT, params TEXT[], parameter TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + accept TEXT[] := ARRAY['SMALLINT[]', 'INTEGER[]', 'BIGINT[]']; + reject TEXT[] := ARRAY['REAL[]', 'FLOAT8[]', 'NUMERIC[]']; +BEGIN + RETURN query SELECT test_value(fn, inner_query_table, start_sql, rest_sql, params, parameter, accept, reject); +END; +$BODY$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_arrayInteger(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT, params TEXT[], parameter TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + accept TEXT[] := ARRAY['SMALLINT[]', 'INTEGER[]']; + reject TEXT[] := ARRAY['BIGINT[]', 'REAL[]', 'FLOAT8[]', 'NUMERIC[]']; +BEGIN + RETURN query SELECT test_value(fn, inner_query_table, start_sql, rest_sql, params, parameter, accept, reject); +END; +$BODY$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_anyNumerical(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT, params TEXT[], parameter TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + accept TEXT[] := ARRAY['SMALLINT', 'INTEGER', 'BIGINT', 'REAL', 'FLOAT8', 'NUMERIC']; + reject TEXT[] := ARRAY[]::TEXT[]; +BEGIN + RETURN query SELECT test_value(fn, inner_query_table, start_sql, rest_sql, params, parameter, accept, reject); +END; +$BODY$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_Char(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT, params TEXT[], parameter TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + accept TEXT[] := ARRAY['CHAR']; + reject TEXT[] := ARRAY['VARCHAR', 'TEXT']::TEXT[]; +BEGIN + RETURN query SELECT test_value(fn, inner_query_table, start_sql, rest_sql, params, parameter, accept, reject); +END; +$BODY$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query_jobs(fn TEXT, start_sql TEXT, rest_sql TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + inner_query_table TEXT := 'jobs'; + params TEXT[] := ARRAY['id', 'location_index', 'service', 'delivery', 'pickup', 'skills', 'priority']; +BEGIN + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'id'); + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'location_index'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'service'); + RETURN QUERY SELECT test_anyArrayInteger(fn, inner_query_table, start_sql, rest_sql, params, 'delivery'); + RETURN QUERY SELECT test_anyArrayInteger(fn, inner_query_table, start_sql, rest_sql, params, 'pickup'); + RETURN QUERY SELECT test_arrayInteger(fn, inner_query_table, start_sql, rest_sql, params, 'skills'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'priority'); +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query_shipments(fn TEXT, start_sql TEXT, rest_sql TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + inner_query_table TEXT := 'shipments'; + params TEXT[] := ARRAY['id', 'p_location_index', 'p_service', 'd_location_index', 'd_service', 'amount', 'skills', 'priority']; +BEGIN + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'id'); + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'p_location_index'); + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'd_location_index'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'p_service'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'd_service'); + RETURN QUERY SELECT test_anyArrayInteger(fn, inner_query_table, start_sql, rest_sql, params, 'amount'); + RETURN QUERY SELECT test_arrayInteger(fn, inner_query_table, start_sql, rest_sql, params, 'skills'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'priority'); +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query_vehicles(fn TEXT, start_sql TEXT, rest_sql TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + inner_query_table TEXT := 'vehicles'; + params TEXT[] := ARRAY['id', 'start_index', 'end_index', 'capacity', 'skills', 'tw_open', 'tw_close', 'speed_factor']; +BEGIN + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'id'); + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'start_index'); + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'end_index'); + RETURN QUERY SELECT test_anyArrayInteger(fn, inner_query_table, start_sql, rest_sql, params, 'capacity'); + RETURN QUERY SELECT test_arrayInteger(fn, inner_query_table, start_sql, rest_sql, params, 'skills'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'tw_open'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'tw_close'); + RETURN QUERY SELECT test_anyNumerical(fn, inner_query_table, start_sql, rest_sql, params, 'speed_factor'); +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query_matrix(fn TEXT, start_sql TEXT, rest_sql TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + inner_query_table TEXT := 'matrix'; + params TEXT[] := ARRAY['start_vid', 'end_vid', 'agg_cost']; +BEGIN + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'start_vid'); + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'end_vid'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'agg_cost'); +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query_breaks(fn TEXT, start_sql TEXT, rest_sql TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + inner_query_table TEXT := 'breaks'; + params TEXT[] := ARRAY['id', 'vehicle_id', 'service']; +BEGIN + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'id'); + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'vehicle_id'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'service'); +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query_time_windows(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + params TEXT[] := ARRAY['id', 'tw_open', 'tw_close']; +BEGIN + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'id'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'tw_open'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'tw_close'); +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query_shipments_time_windows(fn TEXT, inner_query_table TEXT, start_sql TEXT, rest_sql TEXT) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + params TEXT[] := ARRAY['id', 'kind', 'tw_open', 'tw_close']; +BEGIN + RETURN QUERY SELECT test_anyInteger(fn, inner_query_table, start_sql, rest_sql, params, 'id'); + RETURN QUERY SELECT test_Char(fn, inner_query_table, start_sql, rest_sql, params, 'kind'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'tw_open'); + RETURN QUERY SELECT test_Integer(fn, inner_query_table, start_sql, rest_sql, params, 'tw_close'); +END; +$BODY$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION inner_query() +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + fn TEXT; + start_sql TEXT; + rest_sql TEXT; + inner_query_table TEXT; +BEGIN + + IF NOT min_version('0.2.0') THEN + RETURN QUERY + SELECT skip(1, 'Function is new on 0.2.0'); + RETURN; + END IF; + + -- vrp_vroom + + fn := 'vrp_vroom'; + start_sql := ''; + rest_sql := ', $$SELECT * FROM jobs_time_windows$$, $$SELECT * FROM shipments$$, $$SELECT * FROM shipments_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_jobs(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, '; + rest_sql := ', $$SELECT * FROM shipments$$, $$SELECT * FROM shipments_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + inner_query_table := 'jobs_time_windows'; + RETURN QUERY SELECT inner_query_time_windows(fn, inner_query_table, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, '; + rest_sql := ', $$SELECT * FROM shipments_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_shipments(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, $$SELECT * FROM shipments$$, '; + rest_sql := ', $$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + inner_query_table := 'shipments_time_windows'; + RETURN QUERY SELECT inner_query_shipments_time_windows(fn, inner_query_table, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, $$SELECT * FROM shipments$$, ' || + '$$SELECT * FROM shipments_time_windows$$, '; + rest_sql := ', $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_vehicles(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, $$SELECT * FROM shipments$$, ' || + '$$SELECT * FROM shipments_time_windows$$, $$SELECT * FROM vehicles$$, '; + rest_sql := ', $$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_breaks(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, $$SELECT * FROM shipments$$, ' || + '$$SELECT * FROM shipments_time_windows$$, $$SELECT * FROM vehicles$$, ' || + '$$SELECT * FROM breaks$$, '; + rest_sql := ', $$SELECT * FROM matrix$$)'; + inner_query_table := 'breaks_time_windows'; + RETURN QUERY SELECT inner_query_time_windows(fn, inner_query_table, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, $$SELECT * FROM shipments$$, ' || + '$$SELECT * FROM shipments_time_windows$$, $$SELECT * FROM vehicles$$, ' || + '$$SELECT * FROM breaks$$, $$SELECT * FROM breaks_time_windows$$, '; + rest_sql := ')'; + RETURN QUERY SELECT inner_query_matrix(fn, start_sql, rest_sql); + + + -- vrp_vroomJobs + + fn := 'vrp_vroomJobs'; + start_sql := ''; + rest_sql := ', $$SELECT * FROM jobs_time_windows$$, $$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_jobs(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, '; + rest_sql := ', $$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + inner_query_table := 'jobs_time_windows'; + RETURN QUERY SELECT inner_query_time_windows(fn, inner_query_table, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, '; + rest_sql := ', $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_vehicles(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, '; + rest_sql := ', $$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_breaks(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, '; + rest_sql := ', $$SELECT * FROM matrix$$)'; + inner_query_table := 'breaks_time_windows'; + RETURN QUERY SELECT inner_query_time_windows(fn, inner_query_table, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM jobs$$, $$SELECT * FROM jobs_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, $$SELECT * FROM breaks_time_windows$$, '; + rest_sql := ')'; + RETURN QUERY SELECT inner_query_matrix(fn, start_sql, rest_sql); + + + -- vrp_vroomShipments + + fn := 'vrp_vroomShipments'; + start_sql := ''; + rest_sql := ', $$SELECT * FROM shipments_time_windows$$, $$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_shipments(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM shipments$$, '; + rest_sql := ', $$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, ' || + '$$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + inner_query_table := 'shipments_time_windows'; + RETURN QUERY SELECT inner_query_shipments_time_windows(fn, inner_query_table, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM shipments$$, $$SELECT * FROM shipments_time_windows$$, '; + rest_sql := ', $$SELECT * FROM breaks$$, $$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_vehicles(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM shipments$$, $$SELECT * FROM shipments_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, '; + rest_sql := ', $$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + RETURN QUERY SELECT inner_query_breaks(fn, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM shipments$$, $$SELECT * FROM shipments_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, '; + rest_sql := ', $$SELECT * FROM matrix$$)'; + inner_query_table := 'breaks_time_windows'; + RETURN QUERY SELECT inner_query_time_windows(fn, inner_query_table, start_sql, rest_sql); + + start_sql := '$$SELECT * FROM shipments$$, $$SELECT * FROM shipments_time_windows$$, ' || + '$$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$, $$SELECT * FROM breaks_time_windows$$, '; + rest_sql := ')'; + RETURN QUERY SELECT inner_query_matrix(fn, start_sql, rest_sql); +END; +$BODY$ +LANGUAGE plpgsql; + + +SELECT inner_query(); + +SELECT * FROM finish(); +ROLLBACK; diff --git a/pgtap/vroom/no_crash_test.sql b/pgtap/vroom/no_crash_test.sql new file mode 100644 index 000000000..f9e779b5a --- /dev/null +++ b/pgtap/vroom/no_crash_test.sql @@ -0,0 +1,145 @@ +BEGIN; +SET search_path TO 'vroom', 'public'; +SET client_min_messages TO ERROR; + +SELECT CASE WHEN min_version('0.2.0') THEN plan (46) ELSE plan(1) END; + +PREPARE jobs AS SELECT * FROM jobs; +PREPARE jobs_time_windows AS SELECT * FROM jobs_time_windows; +PREPARE shipments AS SELECT * FROM shipments; +PREPARE shipments_time_windows AS SELECT * FROM shipments_time_windows; +PREPARE vehicles AS SELECT * FROM vehicles; +PREPARE breaks AS SELECT * FROM breaks; +PREPARE breaks_time_windows AS SELECT * FROM breaks_time_windows; +PREPARE matrix AS SELECT * FROM matrix; + +CREATE OR REPLACE FUNCTION no_crash() +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + params TEXT[]; + subs TEXT[]; + error_messages TEXT[]; + non_empty_args INTEGER[]; +BEGIN + IF NOT min_version('0.2.0') THEN + RETURN QUERY + SELECT skip(1, 'Function is new on 0.2.0'); + RETURN; + END IF; + + RETURN QUERY + SELECT isnt_empty('jobs', 'Should be not empty to tests be meaningful'); + RETURN QUERY + SELECT isnt_empty('jobs_time_windows', 'Should be not empty to tests be meaningful'); + RETURN QUERY + SELECT isnt_empty('shipments', 'Should be not empty to tests be meaningful'); + RETURN QUERY + SELECT isnt_empty('shipments_time_windows', 'Should be not empty to tests be meaningful'); + RETURN QUERY + SELECT isnt_empty('vehicles', 'Should be not empty to tests be meaningful'); + RETURN QUERY + SELECT isnt_empty('breaks', 'Should be not empty to tests be meaningful'); + RETURN QUERY + SELECT isnt_empty('breaks_time_windows', 'Should be not empty to tests be meaningful'); + RETURN QUERY + SELECT isnt_empty('matrix', 'Should be not empty to tests be meaningful'); + + params = ARRAY[ + '$$jobs$$', + '$$jobs_time_windows$$', + '$$shipments$$', + '$$shipments_time_windows$$', + '$$vehicles$$', + '$$breaks$$', + '$$breaks_time_windows$$', + '$$matrix$$' + ]::TEXT[]; + subs = ARRAY[ + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL' + ]::TEXT[]; + error_messages = ARRAY[ + '', + '', + '', + '', + 'Vehicles SQL must not be NULL', + '', + '', + 'Matrix SQL must not be NULL' + ]::TEXT[]; + non_empty_args = ARRAY[0, 1, 2, 3, 4, 6, 7]::INTEGER[]; + + RETURN query SELECT * FROM no_crash_test('vrp_vroom', params, subs, error_messages, non_empty_args); + + params = ARRAY[ + '$$jobs$$', + '$$jobs_time_windows$$', + '$$vehicles$$', + '$$breaks$$', + '$$breaks_time_windows$$', + '$$matrix$$' + ]::TEXT[]; + subs = ARRAY[ + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL' + ]::TEXT[]; + error_messages = ARRAY[ + 'Jobs SQL must not be NULL', + '', + 'Vehicles SQL must not be NULL', + '', + '', + 'Matrix SQL must not be NULL' + ]::TEXT[]; + non_empty_args = ARRAY[0, 2, 4, 5]::INTEGER[]; + + RETURN query SELECT * FROM no_crash_test('vrp_vroomJobs', params, subs, error_messages, non_empty_args); + + params = ARRAY[ + '$$shipments$$', + '$$shipments_time_windows$$', + '$$vehicles$$', + '$$breaks$$', + '$$breaks_time_windows$$', + '$$matrix$$' + ]::TEXT[]; + subs = ARRAY[ + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL', + 'NULL' + ]::TEXT[]; + error_messages = ARRAY[ + 'Shipments SQL must not be NULL', + '', + 'Vehicles SQL must not be NULL', + '', + '', + 'Matrix SQL must not be NULL' + ]::TEXT[]; + non_empty_args = ARRAY[0, 2, 4, 5]::INTEGER[]; + + RETURN query SELECT * FROM no_crash_test('vrp_vroomShipments'::TEXT, params, subs, error_messages, non_empty_args); + +END +$BODY$ +LANGUAGE plpgsql VOLATILE; + + +SELECT * FROM no_crash(); + +ROLLBACK; diff --git a/pgtap/vroom/types_check.sql b/pgtap/vroom/types_check.sql new file mode 100644 index 000000000..336e22672 --- /dev/null +++ b/pgtap/vroom/types_check.sql @@ -0,0 +1,100 @@ +BEGIN; +SET search_path TO 'vroom', 'public'; + +SELECT CASE WHEN min_version('0.2.0') THEN plan (15) ELSE plan(1) END; + +CREATE OR REPLACE FUNCTION types_check() +RETURNS SETOF TEXT AS +$BODY$ +BEGIN + + IF NOT min_version('0.2.0') THEN + RETURN QUERY + SELECT skip(1, 'Function is new on 0.2.0'); + RETURN; + END IF; + + -- vrp_vroom + RETURN QUERY + SELECT has_function('vrp_vroom'); + RETURN QUERY + SELECT has_function('vrp_vroom', ARRAY['text', 'text', 'text', 'text', 'text', 'text', 'text', 'text']); + RETURN QUERY + SELECT function_returns('vrp_vroom', ARRAY['text', 'text', 'text', 'text', 'text', 'text', 'text', 'text'], 'setof record'); + + -- parameter names + RETURN QUERY + SELECT bag_has( + $$SELECT proargnames from pg_proc where proname = 'vrp_vroom'$$, + $$SELECT '{"","","","","","","","","seq","vehicle_seq","vehicle_id","step_seq","step_type",' + '"task_id","arrival","travel_time","service_time","waiting_time","load"}'::TEXT[]$$ + ); + + -- parameter types + RETURN QUERY + SELECT set_eq( + $$SELECT proallargtypes from pg_proc where proname = 'vrp_vroom'$$, + $$VALUES + ('{25,25,25,25,25,25,25,25,20,20,20,20,23,20,23,23,23,23,1016}'::OID[]) + $$ + ); + + + -- vrp_vroomJobs + RETURN QUERY + SELECT has_function('vrp_vroomjobs'); + RETURN QUERY + SELECT has_function('vrp_vroomjobs', ARRAY['text', 'text', 'text', 'text', 'text', 'text']); + RETURN QUERY + SELECT function_returns('vrp_vroomjobs', ARRAY['text', 'text', 'text', 'text', 'text', 'text'], 'setof record'); + + -- parameter names + RETURN QUERY + SELECT bag_has( + $$SELECT proargnames from pg_proc where proname = 'vrp_vroomjobs'$$, + $$SELECT '{"","","","","","","seq","vehicle_seq","vehicle_id","step_seq","step_type",' + '"task_id","arrival","travel_time","service_time","waiting_time","load"}'::TEXT[]$$ + ); + + -- parameter types + RETURN QUERY + SELECT set_eq( + $$SELECT proallargtypes from pg_proc where proname = 'vrp_vroomjobs'$$, + $$VALUES + ('{25,25,25,25,25,25,20,20,20,20,23,20,23,23,23,23,1016}'::OID[]) + $$ + ); + + + -- vrp_vroomShipments + RETURN QUERY + SELECT has_function('vrp_vroomshipments'); + RETURN QUERY + SELECT has_function('vrp_vroomshipments', ARRAY['text', 'text', 'text', 'text', 'text', 'text']); + RETURN QUERY + SELECT function_returns('vrp_vroomshipments', ARRAY['text', 'text', 'text', 'text', 'text', 'text'], 'setof record'); + + -- parameter names + RETURN QUERY + SELECT bag_has( + $$SELECT proargnames from pg_proc where proname = 'vrp_vroomshipments'$$, + $$SELECT '{"","","","","","","seq","vehicle_seq","vehicle_id","step_seq","step_type",' + '"task_id","arrival","travel_time","service_time","waiting_time","load"}'::TEXT[]$$ + ); + + -- parameter types + RETURN QUERY + SELECT set_eq( + $$SELECT proallargtypes from pg_proc where proname = 'vrp_vroomshipments'$$, + $$VALUES + ('{25,25,25,25,25,25,20,20,20,20,23,20,23,23,23,23,1016}'::OID[]) + $$ + ); +END; +$BODY$ +LANGUAGE plpgsql; + +SELECT types_check(); + +SELECT * FROM finish(); +ROLLBACK; diff --git a/pgtap/vroom/vroomJobs-eq-vroom.test.sql b/pgtap/vroom/vroomJobs-eq-vroom.test.sql new file mode 100644 index 000000000..9d83e2b78 --- /dev/null +++ b/pgtap/vroom/vroomJobs-eq-vroom.test.sql @@ -0,0 +1,67 @@ +BEGIN; +SET search_path TO 'vroom', 'public'; +SET client_min_messages TO ERROR; + +SELECT CASE WHEN min_version('0.2.0') THEN plan (22) ELSE plan(1) END; + +CREATE or REPLACE FUNCTION vroomJobs_eq_vroom() +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + ids BIGINT[] := ARRAY[1, 2, 3, 4, 5]; + jobs_sql TEXT; + empty_time_windows TEXT := '$$SELECT * FROM jobs_time_windows WHERE id = -1$$'; + shipments_sql TEXT := ', $$SELECT * FROM shipments WHERE id = -1$$, $$SELECT * FROM shipments_time_windows WHERE id = -1$$'; + rest_sql TEXT := ', $$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$' || + ', $$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + vroom_sql TEXT; + vroomJobs_sql TEXT; +data TEXT; +BEGIN + IF NOT min_version('0.2.0') THEN + RETURN QUERY + SELECT skip(1, 'Function is new on 0.2.0'); + RETURN; + END IF; + + -- Two jobs + FOR i in 1..array_length(ids, 1) LOOP + FOR j in (i+1)..array_length(ids, 1) LOOP + jobs_sql := '$$SELECT * FROM jobs WHERE id in (' || i || ', ' || j || ')$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomJobs_sql := 'SELECT * FROM vrp_vroomJobs(' || jobs_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomJobs_sql); + END LOOP; + END LOOP; + + -- Three jobs + FOR i in 1..array_length(ids, 1) LOOP + FOR j in (i+1)..array_length(ids, 1) LOOP + FOR k in (j+1)..array_length(ids, 1) LOOP + jobs_sql := '$$SELECT * FROM jobs WHERE id in (' || i || ', ' || j || ', ' || k || ')$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomJobs_sql := 'SELECT * FROM vrp_vroomJobs(' || jobs_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomJobs_sql); + END LOOP; + END LOOP; + END LOOP; + + -- All the five jobs + jobs_sql := '$$SELECT * FROM jobs$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomJobs_sql := 'SELECT * FROM vrp_vroomJobs(' || jobs_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomJobs_sql); + + -- No jobs + jobs_sql := '$$SELECT * FROM jobs WHERE id = -1$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomJobs_sql := 'SELECT * FROM vrp_vroomJobs(' || jobs_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomJobs_sql); +END +$BODY$ +language plpgsql; + +SELECT vroomJobs_eq_vroom(); + +SELECT * FROM finish(); +ROLLBACK; diff --git a/pgtap/vroom/vroomShipments-eq-vroom.test.sql b/pgtap/vroom/vroomShipments-eq-vroom.test.sql new file mode 100644 index 000000000..fe16d68a7 --- /dev/null +++ b/pgtap/vroom/vroomShipments-eq-vroom.test.sql @@ -0,0 +1,67 @@ +BEGIN; +SET search_path TO 'vroom', 'public'; +SET client_min_messages TO ERROR; + +SELECT CASE WHEN min_version('0.2.0') THEN plan (22) ELSE plan(1) END; + +CREATE or REPLACE FUNCTION vroomShipments_eq_vroom() +RETURNS SETOF TEXT AS +$BODY$ +DECLARE + ids BIGINT[] := ARRAY[1, 2, 3, 4, 5]; + jobs_sql TEXT := '$$SELECT * FROM jobs WHERE id = -1$$, $$SELECT * FROM jobs_time_windows WHERE id = -1$$, '; + shipments_sql TEXT; + empty_time_windows TEXT := '$$SELECT * FROM shipments_time_windows WHERE id = -1$$'; + rest_sql TEXT := ', $$SELECT * FROM vehicles$$, $$SELECT * FROM breaks$$' || + ', $$SELECT * FROM breaks_time_windows$$, $$SELECT * FROM matrix$$)'; + vroom_sql TEXT; + vroomShipments_sql TEXT; +data TEXT; +BEGIN + IF NOT min_version('0.2.0') THEN + RETURN QUERY + SELECT skip(1, 'Function is new on 0.2.0'); + RETURN; + END IF; + + -- Two shipments + FOR i in 1..array_length(ids, 1) LOOP + FOR j in (i+1)..array_length(ids, 1) LOOP + shipments_sql := '$$SELECT * FROM shipments WHERE id in (' || i || ', ' || j || ')$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomShipments_sql := 'SELECT * FROM vrp_vroomShipments(' || shipments_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomShipments_sql); + END LOOP; + END LOOP; + + -- Three shipments + FOR i in 1..array_length(ids, 1) LOOP + FOR j in (i+1)..array_length(ids, 1) LOOP + FOR k in (j+1)..array_length(ids, 1) LOOP + shipments_sql := '$$SELECT * FROM shipments WHERE id in (' || i || ', ' || j || ', ' || k || ')$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomShipments_sql := 'SELECT * FROM vrp_vroomShipments(' || shipments_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomShipments_sql); + END LOOP; + END LOOP; + END LOOP; + + -- All the five shipments + shipments_sql := '$$SELECT * FROM shipments$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomShipments_sql := 'SELECT * FROM vrp_vroomShipments(' || shipments_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomShipments_sql); + + -- No shipments + shipments_sql := '$$SELECT * FROM shipments WHERE id = -1$$, ' || empty_time_windows; + vroom_sql := 'SELECT * FROM vrp_vroom(' || jobs_sql || shipments_sql || rest_sql; + vroomShipments_sql := 'SELECT * FROM vrp_vroomShipments(' || shipments_sql || rest_sql; + RETURN query SELECT set_eq(vroom_sql, vroomShipments_sql); +END +$BODY$ +language plpgsql; + +SELECT vroomShipments_eq_vroom(); + +SELECT * FROM finish(); +ROLLBACK; From c2739122af6d7b1a79ad01c54141e9f8319689bc Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:35:38 +0530 Subject: [PATCH 18/20] [readme] Updated README to include vroom details --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fd4fd3f13..75076f4b6 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ### Branches * The *master* branch has the development of the next micro release -* The *develop* branch has the development of the next minor/mayor release +* The *develop* branch has the development of the next minor/major release For the complete list of releases go to: https://github.com/pgRouting/pgrouting/releases @@ -26,25 +26,29 @@ Status of the project can be found [here](https://github.com/pgRouting/vrproutin ## INTRODUCTION -vrpRouting extends the pgRouting/PostGIS/PostgreSQL geospatial database to provide algorithms for Vehilce Routing Problems +vrpRouting extends the pgRouting/PostGIS/PostgreSQL geospatial database to provide algorithms for Vehicle Routing Problems. +It requires VROOM as a dependency for building and computing the VRP solution. This release is compatible with VROOM version 1.10.0 -This library is under develpment an currently contains the following features: +This library is under development and currently contains the following functions: * `vrp_onedepot` * `vrp_pgr_pickdelivereuclidean` -* `vrp_pgr_pickdelive`r +* `vrp_pgr_pickdeliver` +* `vrp_vroom` +* `vrp_vroomJobs` +* `vrp_vroomShipments` ## REQUIREMENTS Building requirements -------------------- * Perl -* C and C++ compilers with C++14 standard support +* C and C++ compilers with C++17 standard support * Postgresql >= TBD * The Boost Graph Library (BGL) >= 1.65 * CMake >= 3.12 * Sphinx >= TBD - +* VROOM >= 1.10.0 User's requirements -------------------- From e3a05f46e7f644a42dd387adccc4bfb9bf21adff Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 10 Aug 2021 19:43:46 +0530 Subject: [PATCH 19/20] [doc] Update release notes --- doc/general/release_notes.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/general/release_notes.rst b/doc/general/release_notes.rst index c90d3ca57..8259f4938 100644 --- a/doc/general/release_notes.rst +++ b/doc/general/release_notes.rst @@ -25,6 +25,12 @@ To see the full list of changes check the list of `Git commits Date: Tue, 10 Aug 2021 19:44:04 +0530 Subject: [PATCH 20/20] [news] Updated NEWS for vroom category functions --- NEWS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS b/NEWS index 27c3c139a..ef239f50c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,12 @@ v0.2.0 Release Notes ******************************************************************************* +*New experimental functions* + +- vrp_vroom +- vrp_vroomJobs +- vrp_vroomShipments + v0.1.0 Release Notes *******************************************************************************