[pgrouting] 02/11: Imported Upstream version 2.1.0
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Fri Feb 5 12:05:54 UTC 2016
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository pgrouting.
commit 228b17fa7d539685bb63d7e70ad5804484523d0f
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Fri Feb 5 10:10:07 2016 +0100
Imported Upstream version 2.1.0
---
.editorconfig | 22 +
.gitignore | 2 +
.travis.yml | 32 +-
CMakeLists.txt | 245 +-
NEWS | 135 +
README.md | 49 +-
VERSION | 2 +-
Vagrantfile | 16 +-
cmake/FindPostgreSQL.cmake | 53 +-
doc/conf.py.in | 3 +-
doc/index.html.in | 11 +-
doc/index.rst | 176 +-
doc/index_man.rst | 2 +-
doc/src/changelog/2_1_0.rst | 71 +
doc/src/changelog/index.rst | 2 +
doc/src/developer/index.rst | 151 +-
doc/src/developer/sampledata.rst | 50 +-
doc/src/installation/build.rst | 119 +-
doc/src/installation/index.rst | 81 +-
doc/src/introduction/images/boost-inside.jpeg | Bin 0 -> 2089 bytes
doc/src/introduction/introduction.rst | 18 +-
.../recipes.rst => recipes/example_recipe.rst} | 21 +-
doc/src/recipes/images/parallelImage.png | Bin 0 -> 10091 bytes
doc/src/recipes/index.rst | 83 +
doc/src/recipes/parallel_handling.rst | 221 +
doc/src/recipes/test/example_recipe.result | 5 +
doc/src/recipes/test/example_recipe.test.sql | 30 +
doc/src/recipes/test/parallel_handling.result | 33 +
doc/src/recipes/test/parallel_handling.test.sql | 121 +
.../recipes/test/sampledata.data.sql} | 2 +
.../src/recipes}/test/test.conf | 12 +-
.../src/recipes/test/zzz-remove_sampledata.result | 0
.../recipes/test/zzz-remove_sampledata.test.sql} | 15 +-
doc/src/tutorial/custom_query.rst | 57 +-
doc/src/tutorial/index.rst | 6 -
doc/src/tutorial/performance.rst | 7 +
doc/src/tutorial/tutorial.rst | 12 +-
.../developers/disconnectEdgeDirected.graphmlz | Bin 0 -> 1272 bytes
.../images/developers/disconnectEdgeDirected.png | Bin 0 -> 4628 bytes
.../developers/disconnectEdgeUndirected.graphmlz | Bin 0 -> 1083 bytes
.../images/developers/disconnectEdgeUndirected.png | Bin 0 -> 4403 bytes
.../developers/disconnectVertexDirected.graphmlz | Bin 0 -> 1562 bytes
.../images/developers/disconnectVertexDirected.png | Bin 0 -> 10283 bytes
.../developers/disconnectVertexUndirected.graphmlz | Bin 0 -> 1462 bytes
.../developers/disconnectVertexUndirected.png | Bin 0 -> 9007 bytes
.../{alphashape-any.rest => alphashape-any.result} | 0
doc/test/alphashape-any.test | 24 -
doc/test/alphashape-any.test.sql | 24 +
...alyzeGraph-any.rest => analyzeGraph-any.result} | 62 +-
...yzeGraph-any.test => analyzeGraph-any.test.sql} | 0
...yzeOneway-any.rest => analyzeOneway-any.result} | 0
...eOneway-any.test => analyzeOneway-any.test.sql} | 0
...apspJohnson-any.rest => apspJohnson-any.result} | 0
...spJohnson-any.test => apspJohnson-any.test.sql} | 0
...spWarshall-any.rest => apspWarshall-any.result} | 0
...Warshall-any.test => apspWarshall-any.test.sql} | 0
doc/test/astar-any.rest | 10 -
doc/test/astar-any.result | 10 +
doc/test/{astar-any.test => astar-any.test.sql} | 0
.../{bdDijkstra-any.rest => bdDijkstra-any.result} | 0
...bdDijkstra-any.test => bdDijkstra-any.test.sql} | 0
doc/test/{bdstar-any.rest => bdstar-any.result} | 0
doc/test/{bdstar-any.test => bdstar-any.test.sql} | 0
...Topology-any.rest => createTopology-any.result} | 48 +-
...pology-any.test => createTopology-any.test.sql} | 5 +-
...teVertTab-any.rest => createVertTab-any.result} | 46 +-
...VertTab-any.test => createVertTab-any.test.sql} | 4 +-
doc/test/dijkstra-any.rest | 12 -
doc/test/dijkstra-v2.result | 12 +
.../{dijkstra-any.test => dijkstra-v2.test.sql} | 23 +-
doc/test/drivingDistance-any.rest | 9 -
doc/test/issue-353.test.sql | 8 +
.../{kdijkstra-any.rest => kdijkstra-any.result} | 0
.../{kdijkstra-any.test => kdijkstra-any.test.sql} | 0
doc/test/{ksp-any.rest => ksp-any.result} | 0
doc/test/{ksp-any.test => ksp-any.test.sql} | 0
...nodeNetwork-any.rest => nodeNetwork-any.result} | 53 +-
...deNetwork-any.test => nodeNetwork-any.test.sql} | 0
...Polygon-any.rest => pointsAsPolygon-any.result} | 0
...lygon-any.test => pointsAsPolygon-any.test.sql} | 0
doc/test/sampledata.data | 2 +
doc/test/{sampledata.rest => sampledata.result} | 4 +-
doc/test/{sampledata.test => sampledata.test.sql} | 0
doc/test/test.conf | 7 +-
doc/test/trsp-any.rest | 13 -
doc/test/trsp-any.result | 37 +
doc/test/{trsp-any.test => trsp-any.test.sql} | 25 +-
doc/test/{tsp-any.rest => tsp-any.result} | 0
doc/test/{tsp-any.test => tsp-any.test.sql} | 0
doc/test/utilities-any.rest | 1 -
doc/test/utilities-any.result | 1 +
.../{utilities-any.test => utilities-any.test.sql} | 0
src/CMakeLists.txt | 36 +-
src/apsp_johnson/sql/apsp_johnson.sql | 2 +-
src/apsp_johnson/src/CMakeLists.txt | 5 +-
src/apsp_johnson/src/apsp_johnson.c | 9 +-
src/apsp_johnson/src/apsp_johnson.h | 2 +-
.../src/apsp_johnson_boost_wrapper.cpp | 13 +-
...nson-any-00.rest => apsp_johnson-any-00.result} | 0
...on-any-00.test => apsp_johnson-any-00.test.sql} | 0
src/apsp_warshall/doc/index.rst | 2 +-
src/apsp_warshall/sql/apsp_warshall.sql | 2 +-
src/apsp_warshall/src/apsp.c | 19 +-
src/apsp_warshall/src/apsp.h | 2 +-
src/apsp_warshall/src/apsp_boost_wrapper.cpp | 15 +-
...all-any-00.rest => apsp_warshall-any-00.result} | 0
...l-any-00.test => apsp_warshall-any-00.test.sql} | 0
src/astar/doc/index.rst | 21 +-
src/astar/sql/astar.sql | 4 +-
src/astar/src/astar.c | 9 +-
src/astar/src/astar.h | 8 +-
src/astar/src/astar_boost_wrapper.cpp | 23 +-
.../test/{spas-any-00.rest => spas-any-00.result} | 0
.../{spas-any-00.test => spas-any-00.test.sql} | 0
.../test/{spas-any-01.rest => spas-any-01.result} | 0
.../{spas-any-01.test => spas-any-01.test.sql} | 0
src/bd_astar/sql/routing_bd_astar.sql | 2 +-
src/bd_astar/src/BiDirAStar.cpp | 15 +-
src/bd_astar/src/bdastar.c | 11 +-
src/bd_astar/src/bdastar.h | 2 +-
src/bd_astar/src/bdastar_core.cpp | 5 +
...bd_astar-any-01.rest => bd_astar-any-01.result} | 0
..._astar-any-01.test => bd_astar-any-01.test.sql} | 0
...bd_astar-any-02.rest => bd_astar-any-02.result} | 0
..._astar-any-02.test => bd_astar-any-02.test.sql} | 0
...bd_astar-any-03.rest => bd_astar-any-03.result} | 0
..._astar-any-03.test => bd_astar-any-03.test.sql} | 0
...bd_astar-any-04.rest => bd_astar-any-04.result} | 0
..._astar-any-04.test => bd_astar-any-04.test.sql} | 0
...bd_astar-any-05.rest => bd_astar-any-05.result} | 0
..._astar-any-05.test => bd_astar-any-05.test.sql} | 0
...bd_astar-any-06.rest => bd_astar-any-06.result} | 0
..._astar-any-06.test => bd_astar-any-06.test.sql} | 0
src/bd_dijkstra/sql/routing_bd_dijkstra.sql | 2 +-
src/bd_dijkstra/src/BiDirDijkstra.cpp | 11 +-
src/bd_dijkstra/src/bdsp.c | 9 +-
src/bd_dijkstra/src/bdsp.h | 2 +-
src/bd_dijkstra/src/bdsp_core.cpp | 5 +
...kstra-any-01.rest => bd_dijkstra-any-01.result} | 0
...tra-any-01.test => bd_dijkstra-any-01.test.sql} | 0
...kstra-any-02.rest => bd_dijkstra-any-02.result} | 0
...tra-any-02.test => bd_dijkstra-any-02.test.sql} | 0
...kstra-any-03.rest => bd_dijkstra-any-03.result} | 0
...tra-any-03.test => bd_dijkstra-any-03.test.sql} | 0
...kstra-any-04.rest => bd_dijkstra-any-04.result} | 0
...tra-any-04.test => bd_dijkstra-any-04.test.sql} | 0
...kstra-any-05.rest => bd_dijkstra-any-05.result} | 0
...tra-any-05.test => bd_dijkstra-any-05.test.sql} | 0
...kstra-any-06.rest => bd_dijkstra-any-06.result} | 0
...tra-any-06.test => bd_dijkstra-any-06.test.sql} | 0
src/common/doc/convenience/flip_edges.rst | 91 +
src/common/doc/convenience/index.rst | 44 +
src/common/doc/convenience/point_to_edgenode.rst | 83 +
src/common/doc/convenience/points_to_dmatrix.rst | 94 +
src/common/doc/convenience/points_to_vids.rst | 81 +
src/common/doc/convenience/text_to_points.rst | 81 +
src/common/doc/convenience/vids_to_dmatrix.rst | 102 +
src/common/doc/convenience/vids_to_dmatrix2.rst | 101 +
src/common/doc/functions/create_topology.rst | 7 +-
.../doc/functions/images/Fig1-originalData.png | Bin 0 -> 49125 bytes
src/common/doc/functions/images/Fig2-cost.png | Bin 0 -> 31293 bytes
.../doc/functions/images/Fig3-reverseCost.png | Bin 0 -> 33366 bytes
.../doc/functions/images/Fig4-costUndirected.png | Bin 0 -> 15432 bytes
.../images/Fig5-reverseCostUndirected.png | Bin 0 -> 15625 bytes
.../doc/functions/images/Fig6-undirected.png | Bin 0 -> 15274 bytes
src/common/doc/index.rst | 1 +
src/common/doc/utilities/end_point.rst | 5 +-
src/common/doc/utilities/get_column_name.rst | 7 +-
src/common/doc/utilities/get_table_name.rst | 5 +-
src/common/doc/utilities/index.rst | 2 -
src/common/doc/utilities/is_column_in_table.rst | 7 +-
src/common/doc/utilities/is_column_indexed.rst | 6 +-
src/common/doc/utilities/point_to_id.rst | 10 +-
src/common/doc/utilities/quote_ident.rst | 6 +-
src/common/doc/utilities/start_point.rst | 5 +-
src/common/doc/utilities/version.rst | 3 +-
src/common/doc/utilities/versionless.rst | 6 +-
src/common/sql/CMakeLists.txt | 12 +-
.../sql/{ => OBSOLETE}/pgrouting_network_check.sql | 0
src/common/sql/OBSOLETE/routing_tsp_wrappers.sql | 2 +-
src/common/sql/createIndex.sql | 111 +
src/common/sql/create_vertices_table.sql | 232 +
src/common/sql/noUnderUtilities.sql | 93 +
src/common/sql/pgr_parameter_check.sql | 111 +
src/common/sql/pgrouting-types.sql | 4 +
src/common/sql/pgrouting_analytics.sql | 617 +-
src/common/sql/pgrouting_conversion_tools.sql | 161 +
src/common/sql/pgrouting_dmatrix_tools.sql | 120 +
src/common/sql/pgrouting_legacy.sql | 8 +-
src/common/sql/pgrouting_node_network.sql | 88 +-
src/common/sql/pgrouting_topology.sql | 754 +-
src/common/sql/pgrouting_utilities.sql | 390 +-
src/common/sql/pgrouting_version.sql | 7 +
src/common/sql/utilities_pgr.sql | 341 +
src/common/src/CMakeLists.txt | 5 +
src/common/src/baseGraph.hpp | 453 +
src/common/src/basePath_SSEC.cpp | 231 +
src/common/src/basePath_SSEC.hpp | 154 +
src/common/src/pgr_assert.cpp | 33 +
src/common/src/pgr_assert.h | 85 +
src/common/src/pgr_logger.h | 65 +
src/common/src/pgr_types.h | 111 +
src/common/src/postgres_connection.c | 415 +
src/common/src/postgres_connection.h | 83 +
src/common/src/signalhandler.cpp | 60 +
src/common/src/signalhandler.h | 129 +
.../{common-any-01.rest => common-any-01.result} | 2 +-
.../{common-any-01.test => common-any-01.test.sql} | 0
src/common/test/common-any-02.data | 132 +
.../{common-any-02.rest => common-any-02.result} | 4 +-
.../{common-any-02.test => common-any-02.test.sql} | 0
.../{common-any-03.rest => common-any-03.result} | 2 +-
.../{common-any-03.test => common-any-03.test.sql} | 0
.../{common-any-04.rest => common-any-04.result} | 12 +-
.../{common-any-04.test => common-any-04.test.sql} | 0
.../{common-any-05.rest => common-any-05.result} | 2 +-
.../{common-any-05.test => common-any-05.test.sql} | 0
src/common/test/createTopology-any-01.rest | 501 -
src/common/test/createTopology-any-01.result | 66 +
src/common/test/createTopology-any-01.test | 133 -
src/common/test/createTopology-any-01.test.sql | 133 +
...y-01.rest => createVerticesTable-any-01.result} | 181 +-
...01.test => createVerticesTable-any-01.test.sql} | 7 +
src/common/test/gettablename-any-01.rest | 151 -
src/common/test/gettablename-any-01.result | 35 +
src/common/test/gettablename-any-01.test | 206 -
src/common/test/gettablename-any-01.test.sql | 83 +
.../test/incrementalCreateTopology_any_01.result | 146 +
.../test/incrementalCreateTopology_any_01.test.sql | 50 +-
src/common/test/isColumnInTable-any.result | 56 +
src/common/test/isColumnInTable-any.test.sql | 103 +
src/common/test/isColumnIndexed-any.result | 56 +
src/common/test/isColumnIndexed-any.test.sql | 103 +
src/common/test/makeTests.sh | 12 +
src/common/test/no_underscored-2x.result | 36 +
src/common/test/no_underscored-2x.test.sql | 28 +
src/common/test/pgr_checkVertTab_any_01.result | 13 +
src/common/test/pgr_checkVertTab_any_01.test.sql | 96 +
src/common/test/pgr_getColumnName_any_01.result | 32 +
src/common/test/pgr_getColumnName_any_01.test.sql | 87 +
src/common/test/pgr_getColumnType_any_01.result | 21 +
src/common/test/pgr_getColumnType_any_01.test.sql | 76 +
.../test/pgrouting_conversion_tools-any-01.result | 25 +
.../pgrouting_conversion_tools-any-01.test.sql | 23 +
.../test/pgrouting_dmatrix_tools-any-01.result | 11 +
.../test/pgrouting_dmatrix_tools-any-01.test.sql | 16 +
src/common/test/test.conf | 26 +-
...nless-any-01.rest => versionless-any-01.result} | 0
src/common/test/versionless-any-01.test | 63 -
src/common/test/versionless-any-01.test.sql | 63 +
src/common/tester/Makefile | 21 +
src/common/tester/test1.c | 16 +
src/common/tester/test2.cpp | 16 +
src/dijkstra/doc/{index.rst => dijkstra_v2.rst} | 106 +-
src/dijkstra/doc/dijkstra_v3.rst | 811 ++
src/dijkstra/doc/index.rst | 141 +-
src/dijkstra/sql/dijkstra.sql | 186 +-
src/dijkstra/src/1_to_many_dijkstra.c | 198 +
src/dijkstra/src/CMakeLists.txt | 19 +-
src/dijkstra/src/boost_wrapper.cpp | 213 -
src/dijkstra/src/dijkstra.c | 383 +-
src/dijkstra/src/dijkstra.h | 50 -
src/dijkstra/src/dijkstra_driver.cpp | 367 +
src/dijkstra/src/dijkstra_driver.h | 61 +
src/dijkstra/src/many_to_1_dijkstra.c | 188 +
src/dijkstra/src/many_to_many_dijkstra.c | 188 +
src/dijkstra/src/pgr_dijkstra.hpp | 375 +
src/dijkstra/test/1_to_many.result | 32 +
src/dijkstra/test/1_to_many.test.sql | 53 +
src/dijkstra/test/dijkstra-dir-00.result | 35 +
src/dijkstra/test/dijkstra-dir-00.test.sql | 43 +
src/dijkstra/test/dijkstra-dir-01.result | 20 +
src/dijkstra/test/dijkstra-dir-01.test.sql | 35 +
src/dijkstra/test/dijkstra-undi-00.result | 25 +
src/dijkstra/test/dijkstra-undi-00.test.sql | 43 +
src/dijkstra/test/dijkstra-undi-01.result | 20 +
src/dijkstra/test/dijkstra-undi-01.test.sql | 33 +
src/dijkstra/test/dijkstra-v2.result | 12 +
.../dijkstra/test/dijkstra-v2.test.sql | 23 +-
src/dijkstra/test/dijkstra-v3.result | 175 +
src/dijkstra/test/dijkstra-v3.test.sql | 276 +
src/dijkstra/test/dijkstra.data | 84 +
src/dijkstra/test/issue-353.result | 24 +
src/dijkstra/test/issue-353.test.sql | 8 +
src/dijkstra/test/many_to_1.result | 35 +
src/dijkstra/test/many_to_1.test.sql | 53 +
src/dijkstra/test/many_to_many.result | 54 +
src/dijkstra/test/many_to_many.test.sql | 50 +
{doc => src/dijkstra}/test/sampledata.data | 2 +
src/dijkstra/test/spd-any-00.data | 212 -
src/dijkstra/test/spd-any-00.rest | 7 -
src/dijkstra/test/spd-any-00.test | 5 -
src/dijkstra/test/spd-any-01.rest | 5 -
src/dijkstra/test/spd-any-01.test | 4 -
src/dijkstra/test/spd-any-02.rest | 5 -
src/dijkstra/test/spd-any-02.test | 5 -
src/dijkstra/test/spd-any-03.rest | 2 -
src/dijkstra/test/spd-any-03.test | 6 -
src/dijkstra/test/spd-any-04.rest | 7 -
src/dijkstra/test/spd-any-04.test | 5 -
src/dijkstra/test/test.conf | 21 +-
src/dijkstra/test/zero_one_edge_-1_rev.result | 20 +
src/dijkstra/test/zero_one_edge_-1_rev.test.sql | 80 +
src/dijkstra/test/zero_one_edge_has_rev.result | 44 +
src/dijkstra/test/zero_one_edge_has_rev.test.sql | 80 +
src/dijkstra/test/zero_one_edge_no_rev.result | 20 +
src/dijkstra/test/zero_one_edge_no_rev.test.sql | 80 +
src/dijkstra/tester/boost_wrapper.cpp | 2 +-
src/dijkstra/tester/dijkstra.h | 2 +-
src/driving_distance/CMakeLists.txt | 1 -
src/driving_distance/doc/dd_alphashape.rst | 51 +-
...ing_distance.rst => dd_driving_distance_v2.rst} | 35 +-
.../doc/dd_driving_distance_v3.rst | 475 +
src/driving_distance/doc/dd_points_as_polygon.rst | 29 +-
src/driving_distance/doc/index.rst | 42 +-
src/driving_distance/sql/routing_dd.sql | 157 +-
src/driving_distance/src/CMakeLists.txt | 20 +-
src/driving_distance/src/alpha.c | 35 +-
src/driving_distance/src/alpha.h | 6 +-
src/driving_distance/src/alpha_drivedist.cpp | 174 +-
src/driving_distance/src/boost_drivedist.cpp | 208 -
.../src/boost_interface_drivedist.cpp | 207 +
.../src/boost_interface_drivedist.h | 51 +
src/driving_distance/src/drivedist.c | 530 +-
src/driving_distance/src/drivedist.h | 37 -
.../src/many_to_dist_driving_distance.c | 191 +
.../test/drivingdistance-any-00.rest | 11 -
.../test/drivingdistance-any-00.result | 44 +
.../test/drivingdistance-any-00.test | 8 -
.../test/drivingdistance-any-00.test.sql | 22 +
.../test/drivingdistance-doc-v2.result | 4 +
.../test/drivingdistance-doc-v2.test.sql | 13 +-
.../test/drivingdistance-doc-v3.result | 173 +
.../test/drivingdistance-doc-v3.test.sql | 91 +
{doc => src/driving_distance}/test/sampledata.data | 2 +
src/driving_distance/test/test.conf | 8 +-
src/index.rst | 4 +-
src/kdijkstra/doc/index.rst | 3 +-
src/kdijkstra/sql/kdijkstra.sql | 14 +-
src/kdijkstra/src/k_targets_boost_wrapper.cpp | 21 +-
src/kdijkstra/src/k_targets_sp.c | 273 +-
src/kdijkstra/src/k_targets_sp.h | 2 +-
src/kdijkstra/test/kdijkstra-any-01.data | 73 +
...ijkstra-any-01.rest => kdijkstra-any-01.result} | 0
...kstra-any-01.test => kdijkstra-any-01.test.sql} | 0
...ijkstra-any-02.rest => kdijkstra-any-02.result} | 0
...kstra-any-02.test => kdijkstra-any-02.test.sql} | 0
...ijkstra-any-03.rest => kdijkstra-any-03.result} | 0
...kstra-any-03.test => kdijkstra-any-03.test.sql} | 0
src/kdijkstra/test/test.conf | 6 +-
src/kdijkstra/test/vidstodmatrix-any-01.result | 1 +
src/kdijkstra/test/vidstodmatrix-any-01.test.sql | 1 +
src/kdijkstra/test/vidstodmatrix-any-02.result | 1 +
src/kdijkstra/test/vidstodmatrix-any-02.test.sql | 1 +
src/ksp/devdata/issue285.data | 7 +
src/ksp/devdata/sampledata.data | 20 +
src/ksp/doc/index.rst | 133 +-
src/ksp/doc/{index.rst => ksp_v2.rst} | 80 +-
src/ksp/doc/ksp_v3.rst | 431 +
src/ksp/sql/CMakeLists.txt | 3 +-
src/ksp/sql/routing_ksp.sql | 83 +-
src/ksp/src/BaseGraph.cpp | 48 -
src/ksp/src/BaseGraph.h | 116 -
src/ksp/src/BasePath.cpp | 23 -
src/ksp/src/BasePath.h | 79 -
src/ksp/src/CMakeLists.txt | 30 +-
src/ksp/src/DijkstraShortestPathAlg.cpp | 236 -
src/ksp/src/DijkstraShortestPathAlg.h | 78 -
src/ksp/src/DynamicGraph.h | 88 -
src/ksp/src/Graph.cpp | 276 -
src/ksp/src/Graph.h | 124 -
src/ksp/src/GraphElements.h | 92 -
src/ksp/src/HeaderTest.cpp | 12 -
src/ksp/src/KSPDriver.cpp | 109 -
src/ksp/src/KSPDriver.h | 12 -
src/ksp/src/KSPGraph.cpp | 106 -
src/ksp/src/KSPGraph.h | 23 -
src/ksp/src/TGraph.h | 154 -
src/ksp/src/TPath.h | 46 -
src/ksp/src/VspGraph.h | 9 -
src/ksp/src/YenTopKShortestPathsAlg.cpp | 207 -
src/ksp/src/YenTopKShortestPathsAlg.h | 67 -
src/ksp/src/ksp.c | 480 +-
src/ksp/src/ksp.h | 97 +-
src/ksp/src/ksp_driver.cpp | 138 +
src/ksp/src/ksp_driver.h | 44 +
src/ksp/src/pgr_ksp.cpp | 129 +
src/ksp/src/pgr_ksp.hpp | 96 +
src/ksp/test/ksp-any-00.data | 79 +-
src/ksp/test/ksp-any-01.rest | 91 -
src/ksp/test/ksp-any-01.result | 214 +
src/ksp/test/ksp-any-01.test | 15 -
src/ksp/test/ksp-any-01.test.sql | 20 +
src/ksp/test/ksp-any-02.rest | 15 -
src/ksp/test/ksp-any-02.result | 214 +
src/ksp/test/ksp-any-02.test | 14 -
src/ksp/test/ksp-any-02.test.sql | 22 +
src/ksp/test/ksp-parallel-any-03.result | 26 +
src/ksp/test/ksp-parallel-any-03.test.sql | 59 +
.../ksp-any.rest => src/ksp/test/ksp-v2.result | 10 +-
.../ksp-any.test => src/ksp/test/ksp-v2.test.sql | 0
src/ksp/test/ksp-v3-1route.result | 93 +
src/ksp/test/ksp-v3-1route.test.sql | 116 +
src/ksp/test/ksp-v3.result | 154 +
src/ksp/test/ksp-v3.test.sql | 117 +
src/ksp/test/makeTests.sh | 12 +
src/ksp/test/show_data.result | 104 +
src/ksp/test/show_data.test.sql | 18 +
src/ksp/test/test.conf | 12 +-
.../CMakeLists.txt | 1 -
src/{common/src => label_graph/doc}/CMakeLists.txt | 0
src/label_graph/doc/analyze_brokengraph.rst | 176 +
src/{ksp => label_graph}/sql/CMakeLists.txt | 6 +-
src/label_graph/sql/label_graph.sql | 172 +
src/{common => label_graph}/src/CMakeLists.txt | 0
.../src => label_graph/test}/CMakeLists.txt | 0
src/label_graph/test/pgrouting_brokengraph.data | 4214 ++++++++
.../test/pgrouting_brokengraph.result} | 0
.../test/pgrouting_brokengraph.test.sql | 52 +
src/label_graph/test/test.conf | 17 +
src/linecommand/src/Makefile | 28 +
src/linecommand/src/dijkstra.cpp | 91 +
src/linecommand/src/driving.cpp | 103 +
src/linecommand/src/pgRouting.cpp | 415 +
src/shooting_star/sql/shooting_star.sql | 2 +-
src/shooting_star/src/shooting_star.c | 2 +-
src/shooting_star/src/shooting_star.h | 2 +-
.../src/shooting_star_boost_wrapper.cpp | 2 +-
.../{spss-any-00.test => spss-any-00.test.sql} | 0
.../{spss-any-01.test => spss-any-01.test.sql} | 0
src/trsp/doc/index.rst | 145 +-
src/trsp/sql/CMakeLists.txt | 4 +-
src/trsp/sql/routing_trsp.sql | 4 +-
src/trsp/sql/routing_trsp_vias.sql | 168 +
src/trsp/src/GraphDefinition.cpp | 1417 +--
src/trsp/src/GraphDefinition.h | 285 +-
src/trsp/src/trsp.c | 26 +-
src/trsp/src/trsp.h | 2 +-
src/trsp/src/trsp_core.cpp | 215 +-
src/trsp/test/test.conf | 4 +-
.../test/{trsp-any-00.rest => trsp-any-00.result} | 0
.../{trsp-any-00.test => trsp-any-00.test.sql} | 0
.../test/{trsp-any-01.rest => trsp-any-01.result} | 0
.../{trsp-any-01.test => trsp-any-01.test.sql} | 1 +
.../test/{trsp-any-02.rest => trsp-any-02.result} | 0
.../{trsp-any-02.test => trsp-any-02.test.sql} | 0
.../test/{trsp-any-03.rest => trsp-any-03.result} | 0
.../{trsp-any-03.test => trsp-any-03.test.sql} | 1 +
src/trsp/test/trsp-issue244.data | 42 +
src/trsp/test/trsp-issue244.result | 6 +
src/trsp/test/trsp-issue244.test.sql | 2 +
src/trsp/test/trsp_vias-any-04.result | 45 +
src/trsp/test/trsp_vias-any-04.test.sql | 40 +
src/tsp/sql/routing_tsp.sql | 2 +-
src/tsp/src/CMakeLists.txt | 62 +-
src/tsp/src/OBSOLETE/tsp.c | 2 +-
src/tsp/src/tsp.h | 4 +-
src/tsp/src/tsp2.c | 11 +-
src/tsp/src/tsplib.c | 7 +-
.../test/{tsp-any-00.rest => tsp-any-00.result} | 0
.../test/{tsp-any-00.test => tsp-any-00.test.sql} | 0
.../test/{tsp-any-01.rest => tsp-any-01.result} | 0
.../test/{tsp-any-01.test => tsp-any-01.test.sql} | 0
.../test/{tsp-any-03.rest => tsp-any-03.result} | 0
.../test/{tsp-any-03.test => tsp-any-03.test.sql} | 0
.../test/{tsp-any-04.rest => tsp-any-04.result} | 0
.../test/{tsp-any-04.test => tsp-any-04.test.sql} | 0
.../test/{tsp-any-05.rest => tsp-any-05.result} | 0
.../test/{tsp-any-05.test => tsp-any-05.test.sql} | 0
src/vrp_basic/CMakeLists.txt | 7 +
src/{common/src => vrp_basic/doc}/CMakeLists.txt | 0
{doc/src/changelog => src/vrp_basic/doc}/index.rst | 15 +-
src/{ksp => vrp_basic}/sql/CMakeLists.txt | 5 +-
src/vrp_basic/sql/routing_vrp.sql | 23 +
src/vrp_basic/src/CMakeLists.txt | 6 +
src/vrp_basic/src/Orders.txt | 102 +
src/vrp_basic/src/Tester.cpp | 266 +
src/vrp_basic/src/Utils.h | 108 +
src/vrp_basic/src/VRP.c | 922 ++
src/vrp_basic/src/VRP.h | 84 +
src/vrp_basic/src/VRP_Solver.cpp | 1034 ++
src/vrp_basic/src/VRP_Solver.h | 426 +
src/vrp_basic/src/VRP_core.cpp | 240 +
src/vrp_basic/src/Vehicles.txt | 21 +
src/{common/src => vrp_basic/test}/CMakeLists.txt | 0
src/vrp_basic/test/Distance.txt | 10100 ++++++++++++++++++
src/vrp_basic/test/Orders.txt | 102 +
src/vrp_basic/test/VRP-any-00.data | 10259 +++++++++++++++++++
src/vrp_basic/test/VRP-any-01.data | 114 +
.../test/VRP-any-01.result} | 0
src/vrp_basic/test/VRP-any-01.test.sql | 5 +
src/vrp_basic/test/VRP-any-02.test.sql | 4 +
src/vrp_basic/test/Vehicles.txt | 21 +
src/vrp_basic/test/solomon100-optimal.png | Bin 0 -> 131215 bytes
src/{ksp => vrp_basic}/test/test.conf | 7 +-
src/vrpdptw/test/README.vrpdptw-testdata | 33 +
src/vrpdptw/test/vrpdptw-testdata.sql.gz | Bin 0 -> 1996513 bytes
src/{driving_distance => vrppdtw}/CMakeLists.txt | 2 +-
src/{common/src => vrppdtw/doc}/CMakeLists.txt | 0
src/vrppdtw/doc/index.rst | 85 +
src/{ksp => vrppdtw}/sql/CMakeLists.txt | 5 +-
src/vrppdtw/sql/routing_vrppdtw.sql | 41 +
src/vrppdtw/src/CMakeLists.txt | 3 +
src/vrppdtw/src/Route.h | 348 +
src/vrppdtw/src/Solution.h | 185 +
src/vrppdtw/src/pdp.c | 478 +
src/vrppdtw/src/pdp.h | 191 +
src/vrppdtw/src/pdp_solver.cpp | 445 +
src/{common/src => vrppdtw/test}/CMakeLists.txt | 0
src/vrppdtw/test/pdp-any-00.data | 120 +
src/vrppdtw/test/pdp-any-01.result | 146 +
src/vrppdtw/test/pdp-any-01.test.sql | 3 +
src/vrppdtw/test/test.conf | 17 +
tools/build-extension-update-files | 276 +
tools/cpplint.py | 6321 ++++++++++++
tools/doit | 5 +-
tools/doxygen/Doxyfile | 2312 +++++
tools/doxygen/DoxygenLayout.xml | 194 +
tools/doxygen/Makefile | 5 +
tools/mk-signature-file | 156 +
tools/sigs/pgrouting--2.0.0.sig | 36 +
tools/sigs/pgrouting--2.1.0.sig | 80 +
tools/test-runner.pl | 81 +-
tools/test-update.sh | 12 +
tools/travis/pgrouting_build.sh | 1 +
tools/travis/pgrouting_install.sh | 49 +-
tools/travis/pgrouting_prepare.sh | 56 +-
tools/travis/pgrouting_test.sh | 72 +-
tools/vagrant/bootstrap.sh | 23 +-
tools/winnie/build_pgrouting.sh | 46 +-
tools/winnie/package_pgrouting.sh | 20 +-
531 files changed, 59022 insertions(+), 8621 deletions(-)
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..105589e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# top-most EditorConfig file
+root = true
+
+# Defaults if not specified later
+[*]
+indent_size = 4
+indent_style = space
+
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+# C source and header files
+[*.{c,h}]
+indent_size = 4
+indent_style = space
+
+# YAML and RST files
+[*.{rst,yml}]
+indent_size = 2
+indent_style = space
diff --git a/.gitignore b/.gitignore
index cc4cf5e..5ea4f44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,5 @@ build
issues
tools/vagrant/packaging.sh
*.mo
+.directory
+notUsed
diff --git a/.travis.yml b/.travis.yml
index 5e58664..ad11004 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,8 @@
language: c
+sudo: required
+
compiler:
- gcc
@@ -16,25 +18,35 @@ notifications:
branches:
only:
+ - master
- develop
- - feature-travis
+
+addons:
+ postgresql: "9.2"
+ postgresql: "9.3"
+ postgresql: "9.4"
services:
- #- postgresql
+ #- postgresql: 9.1
+ #- postgresql: 9.2
+ #- postgresql: 9.3
env:
matrix:
- #- POSTGRESQL_VERSION=8.4 POSTGIS_VERSION=1.5
- - POSTGRESQL_VERSION=9.0 POSTGIS_VERSION=1.5
- - POSTGRESQL_VERSION=9.1 POSTGIS_VERSION=1.5
+ - POSTGRESQL_VERSION=9.4 POSTGIS_VERSION=2.1
+ - POSTGRESQL_VERSION=9.3 POSTGIS_VERSION=2.1
+ - POSTGRESQL_VERSION=9.2 POSTGIS_VERSION=2.1
+ - POSTGRESQL_VERSION=9.1 POSTGIS_VERSION=2.1
- - POSTGRESQL_VERSION=9.1 POSTGIS_VERSION=2.0
+ - POSTGRESQL_VERSION=9.4 POSTGIS_VERSION=2.0
+ - POSTGRESQL_VERSION=9.3 POSTGIS_VERSION=2.0
- POSTGRESQL_VERSION=9.2 POSTGIS_VERSION=2.0
- #- POSTGRESQL_VERSION=9.3 POSTGIS_VERSION=2.0
+ - POSTGRESQL_VERSION=9.1 POSTGIS_VERSION=2.0
- - POSTGRESQL_VERSION=9.1 POSTGIS_VERSION=2.1
- - POSTGRESQL_VERSION=9.2 POSTGIS_VERSION=2.1
- #- POSTGRESQL_VERSION=9.3 POSTGIS_VERSION=2.1
+ ## We are NOT supporting these for pgrouting 2.1.0
+ #- POSTGRESQL_VERSION=8.4 POSTGIS_VERSION=1.5
+ #- POSTGRESQL_VERSION=9.0 POSTGIS_VERSION=1.5
+ #- POSTGRESQL_VERSION=9.1 POSTGIS_VERSION=1.5
install:
- ./tools/travis/pgrouting_install.sh $POSTGRESQL_VERSION $POSTGIS_VERSION
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ef3e9aa..57cccac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,11 +11,7 @@ project(PGROUTING)
#set(CMAKE_VERBOSE_MAKEFILE 1)
# Configure options
-#option(WITH_TSP
-# "Set ON|OFF (default=OFF) to build TSP library" OFF)
-option(WITH_DD
- "Set ON|OFF (default=ON) to build Driving distance library" ON)
option(WITH_DOC
"Set ON|OFF (default=OFF) to build Documentation library tree" OFF)
@@ -27,17 +23,21 @@ option(BUILD_HTML
"Set ON|OFF (default=ON) to build Documentation library tree as HTML" ON)
option(BUILD_MAN
- "Set ON|OFF (default=ON) to build Documentation library tree as MAN page" ON)
+ "Set ON|OFF (default=ON) to build Documentation library tree as MAN page" OFF)
+
+SET(POSTGRESQL_BIN "" CACHE STRING "Define optional path to PostgreSQL binaries an a non-standard location.")
+
#-----------------------------------------------------------------------------
# PGROUTING version number.
set(PGROUTING_VERSION_MAJOR "2")
-set(PGROUTING_VERSION_MINOR "0")
+set(PGROUTING_VERSION_MINOR "1")
set(PGROUTING_VERSION_PATCH "0")
set(PGROUTING_VERSION_STRING "${PGROUTING_VERSION_MAJOR}.${PGROUTING_VERSION_MINOR}.${PGROUTING_VERSION_PATCH}")
-set(POSTGRESQL_MINIMUM_VERSION "8.4.0")
+set(POSTGRESQL_MINIMUM_VERSION "9.1.0")
+set(POSTGIS_MINIMUM_VERSION "2.0.0")
file(STRINGS "${PGROUTING_SOURCE_DIR}/VERSION" PGROUTING_BUILD_STRING)
@@ -49,12 +49,18 @@ string(REGEX REPLACE "^(.+)-([0-9]+)-g([0-9a-f]+) (.*)$" "\\4" PGROUTING_GIT_BRA
set(PGROUTING_VERSION_REVISION_NAME "${PGROUTING_GIT_HASH} ${PGROUTING_GIT_BRANCH}")
set(PGROUTING_VERSION_REVISION_HASH "${PGROUTING_GIT_HASH}")
+message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}")
message(STATUS "PGROUTING_GIT_TAG: ${PGROUTING_GIT_TAG}")
message(STATUS "PGROUTING_GIT_BUILD: ${PGROUTING_GIT_BUILD}")
message(STATUS "PGROUTING_GIT_HASH: ${PGROUTING_GIT_HASH}")
message(STATUS "PGROUTING_GIT_BRANCH: ${PGROUTING_GIT_BRANCH}")
message(STATUS "PGROUTING_VERSION_REVISION_NAME: ${PGROUTING_VERSION_REVISION_NAME}")
+
+message(STATUS "PGROUTING_SOURCE_DIR: ${PGROUTING_SOURCE_DIR}")
+message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
+
message(STATUS "PGROUTING_VERSION_REVISION_HASH: ${PGROUTING_VERSION_REVISION_HASH}")
+message(STATUS "POSTGRESQL_BIN: ${POSTGRESQL_BIN}")
#-----------------------------------------------------------------------------
# CMAKE configuration
@@ -95,28 +101,12 @@ if(WIN32)
message(STATUS "CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}")
endif(WIN32)
-# Check if source contains .git directory
-#if(EXISTS "${PGROUTING_SOURCE_DIR}/.git")
-# # Find Git to collect version information
-# find_package(Git QUIET)
-# if(GIT_FOUND)
-# GIT_WC_INFO(${PGROUTING_SOURCE_DIR} PGROUTING)
-# set(PGROUTING_VERSION_REVISION_NAME "${PGROUTING_WC_REVISION_NAME}")
-# set(PGROUTING_VERSION_REVISION_HASH "${PGROUTING_WC_REVISION_HASH}")
-# else()
-# message(STATUS "Could NOT find GIT (optional)")
-# set(PGROUTING_VERSION_REVISION_NAME "")
-# set(PGROUTING_VERSION_REVISION_HASH "")
-# endif()
-#else()
-# message(STATUS "Source is not a GIT repository")
-# set(PGROUTING_VERSION_REVISION_NAME "")
-# set(PGROUTING_VERSION_REVISION_HASH "")
-#endif()
-
-#macro_optional_find_package(PostgreSQL)
-# POSTGRESQL_INCLUDE_DIR, where to find POSTGRESQL.h
-# POSTGRESQL_LIBRARIES, the libraries needed to use POSTGRESQL.
+
+include(FindPerl)
+if(NOT PERL_EXECUTABLE)
+ message(FATAL_ERROR " Please check your Perl installation.")
+endif(NOT PERL_EXECUTABLE)
+
find_package(PostgreSQL)
if(NOT POSTGRESQL_FOUND)
message(FATAL_ERROR " Please check your PostgreSQL installation.")
@@ -130,6 +120,11 @@ else(Boost_INCLUDE_DIRS)
message(FATAL_ERROR " Please check your Boost installation ")
endif(Boost_INCLUDE_DIRS)
+find_package(CGAL)
+if(NOT CGAL_FOUND)
+ message(FATAL_ERROR " Please check your CGAL installation, or set correct path to CGAL_INCLUDE_DIR and CGAL_LIBRARIES.")
+endif(NOT CGAL_FOUND)
+
if(NOT POSTGRESQL_VERSION_STRING)
message(FATAL_ERROR "pg_config was not found. Please check your PostgreSQL installation!")
endif(NOT POSTGRESQL_VERSION_STRING)
@@ -139,17 +134,13 @@ string(SUBSTRING "${POSTGRESQL_VERSION_STRING}" 11 -1 POSTGRESQL_VERSION)
message(STATUS "POSTGRESQL_VERSION is ${POSTGRESQL_VERSION}")
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*" "\\1\\2" PGSQL_VERSION ${POSTGRESQL_VERSION})
message(STATUS "PGSQL_VERSION is ${PGSQL_VERSION}")
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPGSQL_VERSION=${PGSQL_VERSION}")
if("${POSTGRESQL_VERSION}" VERSION_LESS "${POSTGRESQL_MINIMUM_VERSION}")
message(FATAL_ERROR " PostgreSQL ${POSTGRESQL_MINIMUM_VERSION} or greater is required.")
endif("${POSTGRESQL_VERSION}" VERSION_LESS "${POSTGRESQL_MINIMUM_VERSION}")
-if("${POSTGRESQL_VERSION}" VERSION_LESS "9.1")
- set(USE_PG_EXTENSION FALSE)
-else("${POSTGRESQL_VERSION}" VERSION_LESS "9.1")
- set(USE_PG_EXTENSION TRUE)
-endif("${POSTGRESQL_VERSION}" VERSION_LESS "9.1")
execute_process(
COMMAND ${POSTGRESQL_PG_CONFIG} --pkglibdir
@@ -170,17 +161,8 @@ execute_process(
OUTPUT_VARIABLE SHARE_DIR)
if(SHARE_DIR)
- # Always install in "contrib" directory of PostgreSQL
- set(CONTRIB_DIR "${SHARE_DIR}/contrib/pgrouting-${PGROUTING_VERSION_MAJOR}.${PGROUTING_VERSION_MINOR}")
- message(STATUS "Contrib directory for SQL files is set to ${CONTRIB_DIR}")
-
- # Install as extension if supported by the version of PostgreSQL
- if(USE_PG_EXTENSION)
- set(SHARE_DIR "${SHARE_DIR}/extension")
- message(STATUS "Extension directory for SQL files is set to ${SHARE_DIR}")
- #else(USE_PG_EXTENSION)
- # set(SHARE_DIR "/usr/share/pgrouting")
- endif(USE_PG_EXTENSION)
+ set(SHARE_DIR "${SHARE_DIR}/extension")
+ message(STATUS "Extension directory for SQL files is set to ${SHARE_DIR}")
else(SHARE_DIR)
message(FATAL_ERROR "pg_config --sharedir failed to return a value. Please check your PostgreSQL installation!")
endif(SHARE_DIR)
@@ -188,19 +170,35 @@ endif(SHARE_DIR)
# Handles documentation
add_subdirectory(doc)
+#include directories: files in alphabetical order
set(PGROUTING_INCLUDE_DIRECTORIES
- ${PGROUTING_SOURCE_DIR}/src/astar/src
- ${PGROUTING_SOURCE_DIR}/src/dijkstra/src
- ${PGROUTING_SOURCE_DIR}/src/kdijkstra/src
${PGROUTING_SOURCE_DIR}/src/apsp_johnson/src
${PGROUTING_SOURCE_DIR}/src/apsp_warshall/src
-# ${PGROUTING_SOURCE_DIR}/src/shooting_star/src
- ${PGROUTING_SOURCE_DIR}/src/tsp/src
+ ${PGROUTING_SOURCE_DIR}/src/astar/src
+ ${PGROUTING_SOURCE_DIR}/src/bd_astar/src
+ ${PGROUTING_SOURCE_DIR}/src/bd_dijkstra/src
+ ${PGROUTING_SOURCE_DIR}/src/common/src
+ ${PGROUTING_SOURCE_DIR}/src/dijkstra/src
${PGROUTING_SOURCE_DIR}/src/driving_distance/src
+ ${PGROUTING_SOURCE_DIR}/src/kdijkstra/src
+ ${PGROUTING_SOURCE_DIR}/src/ksp/src
${PGROUTING_SOURCE_DIR}/src/trsp/src
+ ${PGROUTING_SOURCE_DIR}/src/tsp/src
+ ${PGROUTING_SOURCE_DIR}/src/vrp_basic/src
+ ${PGROUTING_SOURCE_DIR}/src/vrppdtw/src
+
+# not using C/C++
+ ${PGROUTING_SOURCE_DIR}/src/label_graph/src
+
+
+#not suported but directory exists
+# ${PGROUTING_SOURCE_DIR}/src/shooting_star/src
+# ${PGROUTING_SOURCE_DIR}/src/vrpdptw/src
)
include_directories(${PGROUTING_INCLUDE_DIRECTORIES} ${POSTGRESQL_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
+
+
if(WIN32)
include_directories(${POSTGRESQL_INCLUDE_DIR}/port/win32)
endif(WIN32)
@@ -212,6 +210,8 @@ if(WIN32)
link_libraries(postgres)
endif(WIN32)
+
+#compiler directives
if(APPLE)
# support GNU(Xcode<4) and Clang(Xcode>=4)
if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
@@ -222,15 +222,17 @@ if(APPLE)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2 -g -frounding-math -Wno-deprecated")
else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2 -g -Wno-deprecated")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2 -std=c++0x -g -Wno-deprecated")
endif()
+
elseif(UNIX) # UNIX system variable include UNIX like system(i.e. APPLE and CYGWIN)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2 -g -frounding-math")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2 -g -frounding-math -Wno-deprecated")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2 -g -Wall -frounding-math")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2 -g -Wall -std=c++0x -frounding-math -Wno-deprecated")
+
elseif(WIN32)
# currently, support MinGW only
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -frounding-math")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -g -frounding-math -Wno-deprecated")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -Wall -frounding-math")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -g -std=c++0x -frounding-math -Wno-deprecated")
endif()
# List variable to collect module SQL file names
@@ -251,70 +253,58 @@ else(APPLE)
set(LIBRARY_MODE_TARGET "SHARED")
endif(APPLE)
-add_library(routing_bd
- ${LIBRARY_MODE_TARGET}
- $<TARGET_OBJECTS:bd_astar>
- $<TARGET_OBJECTS:bd_dijkstra>
- )
-install(TARGETS routing_bd DESTINATION ${LIBRARY_INSTALL_PATH})
+LINK_LIBRARIES(${CGAL_LIBRARIES} ${GMP_LIBRARIES} ${BOOST_THREAD_LIBRARIES})
-add_library(routing
+# libraries listed in alphabetical order.
+add_library(routing-2.1
${LIBRARY_MODE_TARGET}
+ $<TARGET_OBJECTS:apsp_johnson>
+ $<TARGET_OBJECTS:apsp_warshall>
$<TARGET_OBJECTS:astar>
+ $<TARGET_OBJECTS:bd_astar>
+ $<TARGET_OBJECTS:bd_dijkstra>
+ $<TARGET_OBJECTS:common>
$<TARGET_OBJECTS:dijkstra>
+ $<TARGET_OBJECTS:driving_distance>
$<TARGET_OBJECTS:kdijkstra>
- $<TARGET_OBJECTS:apsp_johnson>
- $<TARGET_OBJECTS:apsp_warshall>
-# $<TARGET_OBJECTS:shooting_star>
+ $<TARGET_OBJECTS:ksp>
$<TARGET_OBJECTS:trsp>
+ $<TARGET_OBJECTS:tsp>
+ $<TARGET_OBJECTS:vrp_basic>
+ $<TARGET_OBJECTS:vrppdtw>
+
+#not supported but directory exists
+# $<TARGET_OBJECTS:shooting_star>
)
-install(TARGETS routing DESTINATION ${LIBRARY_INSTALL_PATH})
+install(TARGETS routing-2.1 DESTINATION ${LIBRARY_INSTALL_PATH})
+
+#add_library(routing_vrp
+#add_library(routing_bd
+#add_library(routing_dd
+#add_library(routing
+
if(APPLE)
- set_target_properties(routing
- PROPERTIES
- LINK_FLAGS "-bundle_loader ${POSTGRESQL_EXECUTABLE} -bundle")
- set_target_properties(routing_bd
+ set_target_properties(routing-2.1
PROPERTIES
LINK_FLAGS "-bundle_loader ${POSTGRESQL_EXECUTABLE} -bundle")
endif(APPLE)
-#include_directories(${PGROUTING_INCLUDE_DIRECTORIES} ${POSTGRESQL_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
-#if(WIN32)
-# include_directories(${POSTGRESQL_INCLUDE_DIR}/port/win32)
-#endif(WIN32)
-#add_subdirectory(src/tsp)
-#list(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-
-if(WITH_DD)
- find_package(CGAL)
- if(NOT CGAL_FOUND)
- message(FATAL_ERROR " Please check your CGAL installation, or set correct path to CGAL_INCLUDE_DIR and CGAL_LIBRARIES.")
- endif(NOT CGAL_FOUND)
- #add_definitions(-DBOOST_ALL_NO_LIB)
- #add_definitions(-DBOOST_THREAD_USE_LIB)
- include_directories(${CGAL_INCLUDE_DIR})
- add_subdirectory(src/driving_distance)
- list(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-endif(WITH_DD)
-
-#MESSAGE("PACKAGE_SQL_FILES are ${L_PACKAGE_SQL_FILES}")
file(WRITE "${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql.in"
"-- pgRouting version '${PGROUTING_VERSION_STRING}' extension for postgresql\n")
+
file(APPEND "${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql.in"
-"-- built WITH_DD = ${WITH_DD}\n")
-if(USE_PG_EXTENSION)
- file(APPEND "${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql.in"
- "-- Complain if script is sourced in pgsql, rather than CREATE EXTENSION\n")
- #file(APPEND "${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql.in"
- # "\\echo Use \"CREATE EXTENSION pgrouting\" to load this file. \\quit")
-endif(USE_PG_EXTENSION)
+ "-- Complain if script is sourced in pgsql, rather than CREATE EXTENSION\n")
+#file(APPEND "${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql.in"
+# "\\echo Use \"CREATE EXTENSION pgrouting\" to load this file. \\quit")
+
cat("${PGROUTING_SOURCE_DIR}/src/common/sql/pgrouting-types.sql"
"${PGROUTING_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql.in")
+#cat("${PGROUTING_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql.in")
foreach(PACKAGE_SQL_FILE ${L_PACKAGE_SQL_FILES})
@@ -330,11 +320,35 @@ configure_file("${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.s
configure_file("${PGROUTING_SOURCE_DIR}/src/common/sql/pgrouting.control.in"
"${CMAKE_BINARY_DIR}/lib/pgrouting.control")
+# create the signature file for this release
+message(STATUS "Creating lib/pgrouting--${PGROUTING_VERSION_STRING}.sig")
+execute_process(
+ COMMAND ${PERL_EXECUTABLE} ${PGROUTING_SOURCE_DIR}/tools/mk-signature-file ${PGROUTING_VERSION_STRING}
+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
+ RESULT_VARIABLE SIG_RESULT
+)
+if(SIG_RESULT)
+ message(FATAL_ERROR " SIG_RESULT: ${SIG_RESULT}")
+endif(SIG_RESULT)
+
+# create the extension update scripts
+execute_process(
+ COMMAND ${PERL_EXECUTABLE} ${PGROUTING_SOURCE_DIR}/tools/build-extension-update-files ${PGROUTING_VERSION_STRING} ${PGROUTING_SOURCE_DIR}
+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
+ RESULT_VARIABLE UPDATE_RESULT
+)
+if(UPDATE_RESULT)
+ message(FATAL_ERROR " UPDATE_RESULT: ${UPDATE_RESULT}")
+endif(UPDATE_RESULT)
+
+# make a list of the files we need to install for version updates
+file(GLOB VERSION_UPDATE_FILES "${CMAKE_BINARY_DIR}/lib/pgrouting--*--*.sql")
+
# We will copy the pgrouting_legacy.sql, but not install it as part of
# the extension. TODO: we might want to also include a
# pgrouting_legacy_uninstall.sql file or add it to the extension
-configure_file("${PGROUTING_SOURCE_DIR}/src/common/sql/pgrouting_legacy.sql"
- "${CMAKE_BINARY_DIR}/lib/pgrouting_legacy.sql" COPYONLY)
+#configure_file("${PGROUTING_SOURCE_DIR}/src/common/sql/pgrouting_legacy.sql"
+# "${CMAKE_BINARY_DIR}/lib/pgrouting_legacy.sql" COPYONLY)
# this will create the commands in the makefile under the install target
if(UNIX)
@@ -343,41 +357,14 @@ else(UNIX)
file(GLOB_RECURSE LIBS_TO_INSTALL "${CMAKE_BINARY_DIR}/lib/*.dll")
endif(UNIX)
-#message(STATUS "LIBS_TO_INSTALL=${LIBS_TO_INSTALL}")
+message(STATUS "LIBS_TO_INSTALL=${LIBS_TO_INSTALL}")
install(FILES ${LIBS_TO_INSTALL} DESTINATION ${LIB_DIR})
install(FILES
"${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql"
"${CMAKE_BINARY_DIR}/lib/pgrouting.control"
- "${CMAKE_BINARY_DIR}/lib/pgrouting_legacy.sql"
+ ${VERSION_UPDATE_FILES}
+# "${CMAKE_BINARY_DIR}/lib/pgrouting_legacy.sql"
DESTINATION "${SHARE_DIR}")
-# The following probably could be done better
-# The idea is to also have a "pgrouting-x.x" directory in PostgreSQL contrib
-configure_file("${CMAKE_BINARY_DIR}/lib/pgrouting--${PGROUTING_VERSION_STRING}.sql"
- "${CMAKE_BINARY_DIR}/lib/pgrouting.sql" COPYONLY)
-
-install(FILES
- "${CMAKE_BINARY_DIR}/lib/pgrouting.sql"
- "${CMAKE_BINARY_DIR}/lib/pgrouting.control"
- "${CMAKE_BINARY_DIR}/lib/pgrouting_legacy.sql"
- DESTINATION "${CONTRIB_DIR}")
-
-# TODO: The following probably should be done better
-if(WITH_DD)
- # We will copy the routing_dd_legacy.sql, but not install it as part of
- # the extension. TODO: we might want to also include a
- # routing_dd_legacy_uninstall.sql file or add it to the extension
- configure_file("${PGROUTING_SOURCE_DIR}/src/driving_distance/sql/routing_dd_legacy.sql"
- "${CMAKE_BINARY_DIR}/lib/pgrouting_dd_legacy.sql" COPYONLY)
-
- install(FILES
- "${CMAKE_BINARY_DIR}/lib/pgrouting_dd_legacy.sql"
- DESTINATION "${SHARE_DIR}")
-
- install(FILES
- "${CMAKE_BINARY_DIR}/lib/pgrouting_dd_legacy.sql"
- DESTINATION "${CONTRIB_DIR}")
-endif(WITH_DD)
-
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e5b33f7
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,135 @@
+
+Changes for 2.1.0
+-------------------------------------------------------------------------------
+
+ - A C and C++ library for developer was created
+
+ - encapsulates postgreSQL related functions
+ - encapsulates Boost.Graph graphs
+
+ - Directed Boost.Graph
+ - Undirected Boost.graph.
+
+ - allow any-integer in the id's
+ - allow any-numerical on the cost/reverse_cost columns
+
+ - Three Functions where completly re-factored using the developers library and functionality was added.
+
+ - pgr_dijkstra
+ - pgr_ksp
+ - pgr_drivingDistance
+
+ - Improved
+ Alphashape function now can generate better polygons with holes and custom parameter
+
+ - Instead of generating many libraries:
+ - All functions are encapsulated in one library
+ - The library has a the prefix 2-1-0
+
+ - Added proposed functions to be evaluated:
+ - Proposed functions from Steve Woodbridge, (Classified as Convinience by the author.)
+ - pgr_pointToEdgeNode - convert a point geometry to a vertex_id based on closest edge.
+ - pgr_flipEdges - flip the edges in an array of geometries so the connect end to end.
+ - pgr_textToPoints - convert a string of x,y;x,y;... locations into point geometries.
+ - pgr_pointsToVids - convert an array of point geometries into vertex ids.
+ - pgr_pointsToDMatrix - Create a distance matrix from an array of points.
+ - pgr_vidsToDMatrix - Create a distance matrix from an array of vertix_id.
+ - pgr_vidsToDMatrix - Create a distance matrix from an array of vertix_id.
+
+ - Added proposed functions from GSoc Projects:
+ - pgr_vrppdtw
+
+ - Removed the 1.x legacy functions
+
+ - Some bug fixes in other functions
+
+Changes for 2.0.0
+-------------------------------------------------------------------------------
+
+* Graph Analytics - tools for detecting and fixing connection some problems in a graph
+* A collection of useful utility functions
+* Two new All Pairs Short Path algorithms (pgr_apspJohnson, pgr_apspWarshall)
+* Bi-directional Dijkstra and A-star search algorithms (pgr_bdAstar, pgr_bdDijkstra)
+* One to many nodes search (pgr_kDijkstra)
+* K alternate paths shortest path (pgr_ksp)
+* New TSP solver that simplifies the code and the build process (pgr_tsp), dropped "Gaul Library" dependency
+* Turn Restricted shortest path (pgr_trsp) that replaces Shooting Star
+* Dropped support for Shooting Star
+* Built a test infrastructure that is run before major code changes are checked in
+* Tested and fixed most all of the outstanding bugs reported against 1.x that existing in the 2.0-dev code base.
+* Improved build process for Windows
+* Automated testing on Linux and Windows platforms trigger by every commit
+* Modular library design
+* Compatibility with PostgreSQL 9.1 or newer
+* Compatibility with PostGIS 2.0 or newer
+* Installs as PostgreSQL EXTENSION
+* Return types refactored and unified
+* Support for table SCHEMA in function parameters
+* Support for ``st_`` PostGIS function prefix
+* Added ``pgr_`` prefix to functions and types
+* Better documentation: http://docs.pgrouting.org
+
+
+Changes for release 1.05
+-------------------------------------------------------------------------------
+
+* Bugfixes
+
+
+Changes for release 1.03
+-------------------------------------------------------------------------------
+
+* Much faster topology creation
+* Bugfixes
+
+
+Changes for release 1.02
+-------------------------------------------------------------------------------
+
+* Shooting* bugfixes
+* Compilation problems solved
+
+
+Changes for release 1.01
+-------------------------------------------------------------------------------
+
+* Shooting* bugfixes
+
+
+Changes for release 1.0
+-------------------------------------------------------------------------------
+
+* Core and extra functions are separated
+* Cmake build process
+* Bugfixes
+
+
+Changes for release 1.0.0b
+-------------------------------------------------------------------------------
+
+* Additional SQL file with more simple names for wrapper functions
+* Bugfixes
+
+
+Changes for release 1.0.0a
+-------------------------------------------------------------------------------
+
+* Shooting* shortest path algorithm for real road networks
+* Several SQL bugs were fixed
+
+
+Changes for release 0.9.9
+-------------------------------------------------------------------------------
+
+* PostgreSQL 8.2 support
+* Shortest path functions return empty result if they couldn’t find any path
+
+
+Changes for release 0.9.8
+-------------------------------------------------------------------------------
+
+* Renumbering scheme was added to shortest path functions
+* Directed shortest path functions were added
+* routing_postgis.sql was modified to use dijkstra in TSP search
+
+
diff --git a/README.md b/README.md
index 1b92598..fc189c3 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,14 @@
# pgRouting - Routing on PostgreSQL
+[](https://gitter.im/pgRouting/pgrouting?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
## STATUS
-The *master* branch reflects our current 2.0.0 release. iPost 2.0.0 development will happen in the *develop* branch. The 2.0 release is not backwards compatible with the 1.x releases because we have totally restructured the API and the source code to position the product for additional future growth. Once you see all the new functionality that we have added and the simplier API design we thing you will be very happy with the results.
+### Current Development is in the *develop* branch
+
+The *master* branch reflects our current 2.1.0 release.
+Post 2.1.0 development will happen in the *develop* branch.
+
## LINKS
@@ -26,6 +32,11 @@ The *master* branch reflects our current 2.0.0 release. iPost 2.0.0 development
<td><img src="https://travis-ci.org/pgRouting/pgrouting.png?branch=develop" alt="Build Status"/></td>
<td></td>
</tr>
+ <tr>
+ <td>develop_2_1_0</td>
+ <td><img src="https://travis-ci.org/pgRouting/pgrouting.png?branch=develop_2_1_0" alt="Build Status"/></td>
+ <td></td>
+ </tr>
<tr>
<td>gh-pages</td>
<td><img src="https://travis-ci.org/pgRouting/pgrouting.png?branch=gh-pages" alt="Build Status"/></td>
@@ -55,12 +66,14 @@ This library contains following features:
## REQUIREMENTS
* C and C++ compilers
-* Postgresql version >= 8.4 (9.1 or higher recommended)
-* PostGIS version >= 1.5 (2.0 or higher recommended)
-* The Boost Graph Library (BGL). Version >= [TBD]
+* Postgresql version >= 9.1
+* PostGIS version >= 2.0
+* The Boost Graph Library (BGL).
+ * Version >= 1.55 for linux
+ * Version >= 1.58 for MAC
* CMake >= 2.8.8
-* (optional, for Driving Distance) CGAL >= [TBD]
-* (optional, for Documentation) Sphinx >= [TBD]
+* CGAL >= 4.4
+* Sphinx >= 1.2
## INSTALLATION
@@ -72,25 +85,23 @@ For MinGW on Windows
mkdir build
cd build
- cmake -G"MSYS Makefiles" -DWITH_DD=ON ..
+ cmake -G"MSYS Makefiles" ..
make
make install
-Also pre-built Windows binaries can be downloaded from:
-
- http://www.postgis.net/windows_downloads
+Also pre-built Windows binaries can be downloaded from http://.postgis.net/windows_downloads
For Linux
mkdir build
cd build
- cmake -DWITH_DD=ON ..
+ cmake ..
make
sudo make install
Build with documentation (requires [Sphinx](http://sphinx-doc.org/))
- cmake -DWITH_DOC=ON -DWITH_DD=ON ..
+ cmake -DWITH_DOC=ON ..
Postgresql 9.1+
@@ -98,20 +109,6 @@ Postgresql 9.1+
psql mydatabase -c "create extension postgis"
psql mydatabase -c "create extension pgrouting"
-For older versions of postgresql
-
- createdb -T template1 template_postgis
- psql template_postgis -c "create language plpgsql"
- psql template_postgis -f /usr/share/postgresql/9.0/contrib/postgis-1.5/postgis.sql
- psql template_postgis -f /usr/share/postgresql/9.0/contrib/postgis-1.5/spatial_ref_sys.sql
- psql template_postgis -f /usr/share/postgresql/9.0/contrib/postgis_comments.sql
-
- createdb -T template_postgis template_pgrouting
- psql template_pgrouting -f /usr/share/postgresql/9.0/contrib/pgrouting-2.0/pgrouting.sql
-
- createdb -T template_pgrouting mydatabase
-
-
## USAGE
See online documentation: http://docs.pgrouting.org/dev/doc/index.html
diff --git a/VERSION b/VERSION
index 5af4754..72e643e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-pgrouting-2.0.0-0-gf26831f master
+pgrouting-2.1.0-1-gb38118a master
diff --git a/Vagrantfile b/Vagrantfile
index 64e8f40..cec0d0d 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -8,20 +8,8 @@ postgis = ENV['POSTGIS_VERSION'] || "2.0"
Vagrant.configure("2") do |config|
# Vagrant box configuration
- case pgbox
- when "pgr32"
- config.vm.box = "pgr32"
- config.vm.box_url = "http://s3.amazonaws.com/pgrouting/pgrouting-precise32.box"
-
- when "pgr64"
- config.vm.box = "pgr64"
- config.vm.box_url = "http://s3.amazonaws.com/pgrouting/pgrouting-precise64.box"
-
- when "precise32", "precise64"
- config.vm.box = pgbox
- config.vm.box_url = "http://files.vagrantup.com/%s.box" % [pgbox]
-
- end
+ config.vm.box = pgbox
+ config.vm.box_url = "http://files.vagrantup.com/%s.box" % [pgbox]
# Bootstrap script
config.vm.provision :shell, :path => "tools/vagrant/bootstrap.sh", :args => "%s %s" % [postgres, postgis]
diff --git a/cmake/FindPostgreSQL.cmake b/cmake/FindPostgreSQL.cmake
index 98082bb..9e48037 100644
--- a/cmake/FindPostgreSQL.cmake
+++ b/cmake/FindPostgreSQL.cmake
@@ -14,22 +14,59 @@
# Add the postgresql and mysql include paths here
+# A check condition to see if those variables are set
+
+#POSTGRESQL_BIN ia an optional commandline argument to specify a non-standard path to the postgresql program executables
+SET(POSTGRESQL_BIN "" CACHE STRING "Some user-specified option")
+
if(POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES AND POSTGRESQL_EXECUTABLE AND POSTGRESQL_VERSION_STRING)
set(POSTGRESQL_FOUND TRUE)
else(POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES AND POSTGRESQL_EXECUTABLE)
+ if(NOT "${POSTGRESQL_BIN}" STREQUAL "")
+ # Checking POSTGRESQL_PG_CONFIG
+ find_program(POSTGRESQL_PG_CONFIG NAMES pg_config
+ PATHS
+ ${POSTGRESQL_BIN}
+ NO_DEFAULT_PATH
+ )
+ else(NOT "${POSTGRESQL_BIN}" STREQUAL "")
+ # Checking POSTGRESQL_PG_CONFIG
+ find_program(POSTGRESQL_PG_CONFIG NAMES pg_config
+ PATHS
+ /usr/lib/postgresql/*/bin/
+ )
+ endif(NOT "${POSTGRESQL_BIN}" STREQUAL "")
+
+ message(STATUS "POSTGRESQL_PG_CONFIG is " ${POSTGRESQL_PG_CONFIG})
+
+ if(POSTGRESQL_PG_CONFIG)
+ execute_process(
+ COMMAND ${POSTGRESQL_PG_CONFIG} --bindir
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ OUTPUT_VARIABLE T_POSTGRESQL_BIN)
+ endif(POSTGRESQL_PG_CONFIG)
+
+ # Checking POSTGRESQL_EXECUTABLE in all the dir (*) - implies that
find_program(POSTGRESQL_EXECUTABLE NAMES postgres
PATHS
- /usr/lib/postgresql/*/bin/
+ ${T_POSTGRESQL_BIN}
)
message(STATUS "POSTGRESQL_EXECUTABLE is " ${POSTGRESQL_EXECUTABLE})
- find_program(POSTGRESQL_PG_CONFIG NAMES pg_config
- PATHS
- /usr/lib/postgresql/*/bin/
- )
- message(STATUS "POSTGRESQL_PG_CONFIG is " ${POSTGRESQL_PG_CONFIG})
+
+# find_program(POSTGRESQL_EXECUTABLE NAMES postgres
+# PATHS
+# /usr/lib/postgresql/*/bin/
+# )
+# message(STATUS "POSTGRESQL_EXECUTABLE is " ${POSTGRESQL_EXECUTABLE})
+
+# find_program(POSTGRESQL_PG_CONFIG NAMES pg_config
+# PATHS
+# /usr/lib/postgresql/*/bin/
+# )
+# message(STATUS "POSTGRESQL_PG_CONFIG is " ${POSTGRESQL_PG_CONFIG})
if(POSTGRESQL_PG_CONFIG)
execute_process(
@@ -38,6 +75,8 @@ else(POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES AND POSTGRESQL_EXECUTABLE)
OUTPUT_VARIABLE POSTGRESQL_VERSION_STRING)
endif(POSTGRESQL_PG_CONFIG)
+ message(STATUS "POSTGRESQL_VERSION_STRING in FindPostgreSQL.cmake is " ${POSTGRESQL_VERSION_STRING})
+
if(POSTGRESQL_PG_CONFIG)
execute_process(
COMMAND ${POSTGRESQL_PG_CONFIG} --includedir-server
@@ -47,6 +86,7 @@ else(POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES AND POSTGRESQL_EXECUTABLE)
find_path(POSTGRESQL_INCLUDE_DIR postgres.h
${T_POSTGRESQL_INCLUDE_DIR}
+
/usr/include/server
/usr/include/pgsql/server
/usr/local/include/pgsql/server
@@ -78,3 +118,4 @@ else(POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES AND POSTGRESQL_EXECUTABLE)
mark_as_advanced(POSTGRESQL_INCLUDE_DIR POSTGRESQL_LIBRARIES)
endif(POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES AND POSTGRESQL_EXECUTABLE AND POSTGRESQL_VERSION_STRING)
+
diff --git a/doc/conf.py.in b/doc/conf.py.in
index bea37f1..9400007 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -25,7 +25,8 @@ needs_sphinx = '1.1'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.todo']
+mathjax_path="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
+extensions = ['sphinx.ext.todo', 'sphinx.ext.mathjax']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['doc/templates']
diff --git a/doc/index.html.in b/doc/index.html.in
index 3862c2b..4ff3b79 100644
--- a/doc/index.html.in
+++ b/doc/index.html.in
@@ -48,17 +48,20 @@
<div class="section">
<h2>Betas and Release Candidates<a class="headerlink" title="Permalink to this headline">¶</a></h2>
<p>This documentation is for the alpha, beta and release candidate versions. Releases in this section are known to be unstable.</p>
- <!-- <div class="toctree-wrapper compound">
+ <div class="toctree-wrapper compound">
+ <!--
<ul>
<li class="toctree-l1"><a class="reference internal" href="v2.0.0-rc1/doc/index.html">pgRouting v2.0.0-rc1</a> [<a class="reference external" href="v2.0.0-rc1/pgRoutingDocumentation.pdf">PDF</a> | <a class="reference external" href="v2.0.0-rc1/pgrouting.7.gz">MAN</a>]</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="v2.0.0-beta/doc/index.html">pgRouting v2.0.0-beta</a> [PDF | MAN]</li>
</ul>
+ -->
<ul>
- <li class="toctree-l1"><a class="reference internal" href="v2.0.0-alpha/doc/index.html">pgRouting v2.0.0-alpha</a> [PDF | MAN]</li>
+ <li class="toctree-l1"><a class="reference internal" href="v2.1.0-alpha/doc/index.html">v2.1.0-alpha</a> [PDF | MAN]</li>
+ <li class="toctree-l1"><a class="reference internal" href="v2.1.0-beta/doc/index.html">v2.1.0-beta</a> [PDF | MAN]</li>
</ul>
- </div> -->
+ </div>
</div>
<div class="section">
@@ -66,7 +69,7 @@
<p>This documentation is for the unreleased version currently under development, and is frequently updated and changed.</p>
<div class="toctree-wrapper compound">
<ul>
- <li class="toctree-l1"><a class="reference internal" href="dev/en/doc/index.html">pgRouting ${PGROUTING_VERSION_STRING}</a> [<a class="reference external" href="dev/en/pgRoutingDocumentation.pdf">PDF</a> | <a class="reference external" href="dev/en/pgrouting.7.gz">MAN</a>] (${PGROUTING_VERSION_REVISION_NAME})</li>
+ <li class="toctree-l1"><a class="reference internal" href="dev/en/doc/index.html">develop ${PGROUTING_VERSION_REVISION_NAME}</a> [
</ul>
</div>
</div>
diff --git a/doc/index.rst b/doc/index.rst
index 1b908bb..b39938d 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -1,9 +1,9 @@
-..
+..
****************************************************************************
pgRouting Manual
Copyright(c) pgRouting Contributors
- This documentation is licensed under a Creative Commons Attribution-Share
+ This documentation is licensed under a Creative Commons Attribution-Share
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
@@ -46,9 +46,8 @@ Tutorial
- :ref:`analytics` for an overview of the analysis of a graph.
- :ref:`custom_query` that is used in the routing algorithms.
- :ref:`performance` to improve your performance.
- - :ref:`custom_wrapper` to colaborate with a wrapper.
- - :ref:`recipes` to colaborate with a recipe.
- :ref:`sampledata` that is used in the examples of this manual.
+ - :ref:`recipes`
@@ -57,14 +56,28 @@ Tutorial
src/tutorial/index
src/developer/sampledata
+ src/recipes/index
For a more complete introduction how to build a routing application read the `pgRouting Workshop <http://workshop.pgrouting.org>`_.
*******************************************************************************
+Version
+*******************************************************************************
+
+:ref:`pgr_version` - to get pgRouting's version information.
+
+.. toctree::
+ :hidden:
+
+ ../src/common/doc/utilities/version
+
+
+
+*******************************************************************************
Data Types
*******************************************************************************
-:ref:`data_types`
+:ref:`data_types`
- :ref:`type_cost_result` - A set of records to describe a path result with cost attribute.
- :ref:`pgr_costResult3[]<type_cost_result3>` - A set of records to describe a path result with cost attribute.
@@ -76,18 +89,27 @@ Data Types
../src/common/doc/types/index
*******************************************************************************
-Functions reference
+Topology functions
*******************************************************************************
-:ref:`topology_functions`
+:ref:`topology_functions`
- :ref:`pgr_create_topology` - to create a topology based on the geometry.
- :ref:`pgr_create_vert_table` - to reconstruct the vertices table based on the source and target information.
- :ref:`pgr_analyze_graph` - to analyze the edges and vertices of the edge table.
- :ref:`pgr_analyze_oneway` - to analyze directionality of the edges.
- :ref:`pgr_node_network` -to create nodes to a not noded edge table.
-
-:ref:`routing_functions`
+
+.. toctree::
+ :hidden:
+
+ ../src/common/doc/functions/index
+
+*******************************************************************************
+Routing functions
+*******************************************************************************
+
+:ref:`routing_functions`
- :ref:`pgr_apspJohnson <pgr_apsp_johnson>`- All Pairs Shortest Path, Johnson’s Algorithm
- :ref:`pgr_apspWarshall<pgr_apsp_warshall>` - All Pairs Shortest Path, Floyd-Warshall Algorithm
@@ -95,41 +117,110 @@ Functions reference
- :ref:`pgr_bdAstar<bd_astar>` - Bi-directional A* Shortest Path
- :ref:`pgr_bdDijkstra<bd_dijkstra>` - Bi-directional Dijkstra Shortest Path
- :ref:`pgr_dijkstra<pgr_dijkstra>` - Shortest Path Dijkstra
+ - :ref:`pgr_driving_distance<pgr_driving_distance>` - Driving Distance
- :ref:`pgr_kDijkstra<pgr_kdijkstra>` - Mutliple destination Shortest Path Dijkstra
- - :ref:`pgr_ksp<ksp>` - K-Shortest Path
- - :ref:`pgr_tsp<pgr_tsp>` - Traveling Sales Person
+ - :ref:`pgr_ksp<pgr_ksp>` - K-Shortest Path
- :ref:`pgr_trsp<trsp>` - Turn Restriction Shortest Path (TRSP)
+ - :ref:`pgr_tsp<pgr_tsp>` - Traveling Sales Person
+
+.. toctree::
+ :hidden:
-:ref:`dd_index`
+ ../src/index
- - :ref:`pgr_driving_distance` - Driving Distance
- - :ref:`pgr_alphaShape` - Alpha shape computation
- - :ref:`pgr_points_as_polygon` - Polygon around set of points
+*******************************************************************************
+Pre processing or post processing helping functions
+*******************************************************************************
+
+:ref:`pgr_driving_distance_post`
+
+ - :ref:`pgr_alphaShape` - Alpha shape computation
+ - :ref:`pgr_points_as_polygon` - Polygon around set of points
+
+*******************************************************************************
+Experimental and Proposed functions
+*******************************************************************************
+
+This section contains new experimental or proposed signatures for any of the following sections:
+ - topology functions
+ - routing functions
+ - vehicle routing functions
+ - pre / post procesing helper functions
+
+
+We are including them so that the pgRouting community can evaluate them before
+including them as an official function of pgRouting.
+
+Some of them are unsupported like the GSoC functions.
+
+
+*******************************************************************************
+Experimental functions: Proposed by Steve Woodbridge
+*******************************************************************************
+
+:ref:`convenience_functions`
+ - :ref:`pgr_point_to_edgenode` - convert a point geometry to a ``vertex_id`` based on closest edge.
+ - :ref:`pgr_flip_edges` - flip the edges in an array of geometries so the connect end to end.
+ - :ref:`pgr_text_to_points` - convert a string of ``x,y;x,y;...`` locations into point geometries.
+ - :ref:`pgr_points_to_vids` - convert an array of point geometries into vertex ids.
+ - :ref:`pgr_points_to_dmatrix` - Create a distance matrix from an array of points.
+ - :ref:`pgr_vids_to_dmatrix` - Create a distance matrix from an array of ``vertix_id``.
+ - :ref:`pgr_vids_to_dmatrix2` - Create a distance matrix from an array of ``vertix_id``.
+
+.. toctree::
+ :hidden:
+
+ ../src/common/doc/convenience/index
+
+*******************************************************************************
+Experimental functions: by GSoC
+*******************************************************************************
+
+The following functions are experimental
+ - They may lack documentation,
+ - Were created by GSoC students.
+ - they are unsupported.
+
+ - :ref:`pgr_vrp_basic` - VRP One Depot
+ - :ref:`pgr_gsocvrppdtw` - Pickup and Delivery problem
+
+.. toctree::
+ :hidden:
+
+ ../src/vrp_basic/doc/index.rst
+ ../src/vrppdtw/doc/index.rst
+
+*******************************************************************************
+Proposed functions: Proposed by Zia Mohammed
+*******************************************************************************
+
+About this proposal:
+ - Author: Zia Mohammed.
+ - Status: Needs a lot of testing. I am working on that.
+ - I did not add automated test.
+ - Temporary name: pgr_labelGraph
+ - Need: I need feedback from the community.
+
+ - :ref:`pgr_labelGraph` - Analyze / label subgraphs within a network
+
+.. toctree::
+ :hidden:
+
+ ../src/label_graph/doc/analyze_brokengraph.rst
-:ref:`developer_functions`
- - :ref:`pgr_get_column_name` - to get the name of the column as is stored in the postgres administration tables.
- - :ref:`pgr_get_table_name` - to retrieve the name of the table as is stored in the postgres administration tables.
- - :ref:`pgr_is_column_indexed` - to check if the column is indexed.
- - :ref:`pgr_is_column_in_table` - to check only for the existance of the column.
- - :ref:`pgr_point_to_id` -to insert/get the id of the inserted point in a vertices table.
- - :ref:`pgr_quote_ident` - to quotes the input text to be used as an identifier in an SQL statement string.
- - :ref:`pgr_version` - to get pgRouting's version information.
- - :ref:`pgr_versionless` - to compare two version numbers.
- - :ref:`pgr_start_point` - to get the start point of a (multi)linestring.
- - :ref:`pgr_end_point` - to get the end point of a (multi)linestring.
.. toctree::
:hidden:
- ../src/common/doc/functions/index
- ../src/index
- ../src/driving_distance/doc/index
../src/common/doc/utilities/index
+*******************************************************************************
+Discontinued Functions
+*******************************************************************************
+
.. toctree::
:maxdepth: 1
- ../src/common/doc/legacy
src/developer/discontinued
@@ -137,14 +228,35 @@ Functions reference
Developer
*******************************************************************************
+
+:ref:`developer_functions`
+
+
+.. warning:: In V3.0 This function are going to be discontinued. Use the already available underscored version instead.
+
+.. warning:: :ref:`developer_functions` documentation is going to be deleted from the pgRouting documentation in V3.0
+
+
+The following functions are used internaly the topology functions.
+ - :ref:`pgr_get_column_name` - to get the name of the column as is stored in the postgres administration tables.
+ - :ref:`pgr_get_table_name` - to retrieve the name of the table as is stored in the postgres administration tables.
+ - :ref:`pgr_is_column_indexed` - to check if the column is indexed.
+ - :ref:`pgr_is_column_in_table` - to check only for the existance of the column.
+ - :ref:`pgr_point_to_id` -to insert/get the id of the inserted point in a vertices table.
+ - :ref:`pgr_quote_ident` - to quotes the input text to be used as an identifier in an SQL statement string.
+ - :ref:`pgr_versionless` - to compare two version numbers.
+ - :ref:`pgr_start_point` - to get the start point of a (multi)linestring.
+ - :ref:`pgr_end_point` - to get the end point of a (multi)linestring.
+
.. toctree::
:maxdepth: 2
src/developer/index
-:ref:`change_log`
+:ref:`change_log`
- - :ref:`changelog_2_0`
+ - :ref:`changelog_2_1_0`
+ - :ref:`changelog_2_0`
- :ref:`changelog_1_x`
.. toctree::
diff --git a/doc/index_man.rst b/doc/index_man.rst
index d7ff9b1..fd957d0 100644
--- a/doc/index_man.rst
+++ b/doc/index_man.rst
@@ -39,7 +39,7 @@ pgRouting defines a few :ref:`custom data types <data_types>`:
:maxdepth: 1
:hidden:
- ../src/common/doc/types
+ ../src/common/doc/types/index
.. toctree::
:maxdepth: 1
diff --git a/doc/src/changelog/2_1_0.rst b/doc/src/changelog/2_1_0.rst
new file mode 100644
index 0000000..e658de7
--- /dev/null
+++ b/doc/src/changelog/2_1_0.rst
@@ -0,0 +1,71 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _changelog_2_1_0:
+
+pgRouting 2.1.0 Release Notes
+===============================================================================
+
+With the release of pgRouting 2.1.0 fixes some bugs and issues.
+
+ - To see the full list of changes check the list of `Git commits <https://github.com/pgRouting/pgrouting/commits>`_ on Github.
+ - To see the issues closed by this release see the `Git closed issues <https://github.com/pgRouting/pgrouting/issues?q=is%3Aissue+milestone%3A%22Release+2.1.0%22+is%3Aclosed>`_ on Github.
+ - For important changes see the following release notes.
+
+..
+
+
+
+Release Notes
+-------------------------------------------------------------------------------
+
+ - A C and C++ library for developer was created
+
+ - encapsulates postgreSQL related functions
+ - encapsulates Boost.Graph graphs
+
+ - Directed Boost.Graph
+ - Undirected Boost.graph.
+
+ - allow any-integer in the id's
+ - allow any-numerical on the cost/reverse_cost columns
+
+ - Three Functions where completly re-factored using the developers library and functionality was added.
+
+ - pgr_dijkstra
+ - pgr_ksp
+ - pgr_drivingDistance
+
+ - Improved
+ - Alphashape function now can generate better (multi)polygon with holes and alpha parameter.
+
+ - Instead of generating many libraries:
+ - All functions are encapsulated in one library
+ - The library has a the prefix 2-1-0
+
+ - Added proposed functions to be evaluated:
+
+ - Proposed functions from Steve Woodbridge, (Classified as Convinience by the author.)
+
+ - pgr_pointToEdgeNode - convert a point geometry to a vertex_id based on closest edge.
+ - pgr_flipEdges - flip the edges in an array of geometries so the connect end to end.
+ - pgr_textToPoints - convert a string of x,y;x,y;... locations into point geometries.
+ - pgr_pointsToVids - convert an array of point geometries into vertex ids.
+ - pgr_pointsToDMatrix - Create a distance matrix from an array of points.
+ - pgr_vidsToDMatrix - Create a distance matrix from an array of vertix_id.
+ - pgr_vidsToDMatrix - Create a distance matrix from an array of vertix_id.
+
+ - Added proposed functions from GSoc Projects:
+
+ - pgr_vrppdtw
+
+ - Removed the 1.x legacy functions
+
+ - Some bug fixes in other functions
+
diff --git a/doc/src/changelog/index.rst b/doc/src/changelog/index.rst
index 0534c0b..a2f49c8 100644
--- a/doc/src/changelog/index.rst
+++ b/doc/src/changelog/index.rst
@@ -12,12 +12,14 @@
Release Notes
===============================================================================
+ - :ref:`changelog_2_1_0`
- :ref:`changelog_2_0`
- :ref:`changelog_1_x`
.. toctree::
:hidden:
+ pgRouting 2.1 develop Notes <2_1_0>
pgRouting 2.0 Release Notes <2_0>
pgRouting 1.x Release Notes <1_x>
diff --git a/doc/src/developer/index.rst b/doc/src/developer/index.rst
index cc77c93..32a985b 100644
--- a/doc/src/developer/index.rst
+++ b/doc/src/developer/index.rst
@@ -12,73 +12,116 @@
Developer's Guide
===============================================================================
-.. note::
- All documentation should be in reStructuredText format.
- See: <http://docutils.sf.net/rst.html> for introductory docs.
Source Tree Layout
-------------------------------------------------------------------------------
-cmake/
+*cmake/*
cmake scripts used as part of our build system.
-src/
- This is the algorithm source tree. Each algorithm should be contained
- in its on sub-tree with doc, sql, src, and test sub-directories.
- This might get renamed to "algorithms" at some point.
-
-src/astar/
- This is an implementation of A* Search based on using Boost Graph
- libraries for its implementation. This is a Dijkstra shortest path
- implementation with a Euclidean Heuristic.
-
-src/common/
- At the moment this does not have an core in "src", but does have a lot
- of SQL wrapper code and topology code in the "sql" directory. *Algorithm
- specific wrappers should get move to the algorithm tree and appropriate
- tests should get added to validate the wrappers.*
-
-src/dijkstra/
- This is an implementation of Dikjstra's shortest path solution using
- Boost Graph libraries for the implementation.
-
-src/driving_distance/
- This optional package creates driving distance polygons based on
- solving a Dijkstra shortest path solution, then creating polygons
- based on equal cost distances from the start point.
- This optional package requires CGAL libraries to be installed.
-
-src/shooting_star/
- *DEPRECATED and DOES NOT WORK and IS BEING REMOVED*
- This is an edge based shortest path algorithm that supports turn
- restrictions. It is based on Boost Graph.
- Do *NOT* use this algorithm as it is broken, instead use *trsp*
- which has the same functionality and is faster and give correct results.
-
-src/trsp/
- This is a turn restricted shortest path algorithm. It has some nice
- features like you can specify the start and end points as a percentage
- along an edge. Restrictions are stored in a separate table from the
- graph edges and this make it easier to manage the data.
-
-src/tsp/
- This optional package provides the ability to compute traveling
- salesman problem solutions and compute the resulting route.
- This optional package requires GAUL libaries to be installed.
-
-tools/
+*src/*
+ This is the algorithm source tree. Each algorithm is to be contained
+ in its on sub-tree with /doc, /sql, /src, and /test sub-directories.
+
+For example:
+
+ - ``src/dijkstra`` Main direcotry for dijkstra algorithm.
+ - ``src/dijkstra/doc`` Dijkstra's documentation directory.
+ - ``src/dijkstra/src`` Dijkstra's C and/or C++ code.
+ - ``src/dijkstra/sql`` Dijkstra's sql code.
+ - ``src/dijkstra/test`` Dijkstra's tests.
+
+
+Tools
+-------------------------------------------------------------------------------
+
+*tools/*
Miscellaneous scripts and tools.
-lib/
- This is the output directory where compiled libraries and installation
- targets are staged before installation.
+pre-commit
+**********
+
+To keep version/branch/commit up to date install pelase do the following:
+
+.. code::
+
+ cp tools/pre-commit .git/hooks/pre-commit
+
+After each commit a the file **VERSION** will remain. (The hash number will be one behind)
+
+
+tester
+******
+
+The tester is executed from the top level of the tree layout:
+
+.. code::
+
+ tools/test-runner.pl --help
+
+doxygen
+*******
+
+.. warning:: :ref:`developer_functions` documentation is going to be deleted from the pgRouting documentation and included in the doxygen documentation.
+
+To use doxygen:
+
+
+.. code::
+ cd tools/doxygen/
+ make
+
+The code's documentation can be found in:
+
+
+.. code::
+
+ build/doxy/html/index.html
+
+
+cpplint
+*******
+
+We try to follow the following guidelines for C++ coding:
+
+https://google-styleguide.googlecode.com/svn/trunk/cppguide.html
+
+Sample use:
+
+.. code::
+
+ python cpplint.py ../src/dijkstra/src/dijkstra_driver.h
+ ../src/dijkstra/src/dijkstra_driver.h:34: Lines should be <= 80 characters long [whitespace/line_length] [2]
+ ../src/dijkstra/src/dijkstra_driver.h:40: Line ends in whitespace. Consider deleting these extra spaces. [whitespace/end_of_line] [4]
+ Done processing ../src/dijkstra/src/dijkstra_driver.h
+ Total errors found: 2
+
+
+- Maybe line 34 is a very complicated calculation so you can just ignore the message
+- Delete whitespace at end of line is easy fix.
+- Use your judgement!!!
+
+Some files like ``postgres.h`` are system dependant so don't include the directory.
+
+
+Other tools
+***********
+
+Tools like:
+ - doit
+ - winnie
+ - publish_doc.sh
+
+are very specific for the deployment of new versions, so please ask first!
Documentation Layout
-------------------------------------------------------------------------------
-*As noted above all documentation should be done using reStructuredText
-formated files.*
+.. note::
+ All documentation should be in reStructuredText format.
+ See: <http://docutils.sf.net/rst.html> for introductory docs.
+
Documentation is distributed into the source tree. This top level "doc"
directory is intended for high level documentation cover subjects like:
diff --git a/doc/src/developer/sampledata.rst b/doc/src/developer/sampledata.rst
index 9874d53..9712313 100644
--- a/doc/src/developer/sampledata.rst
+++ b/doc/src/developer/sampledata.rst
@@ -1,9 +1,9 @@
-..
+..
****************************************************************************
pgRouting Manual
Copyright(c) pgRouting Contributors
- This documentation is licensed under a Creative Commons Attribution-Share
+ This documentation is licensed under a Creative Commons Attribution-Share
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
@@ -64,7 +64,7 @@ To be able to execute the sample queries, run the following SQL commands to crea
dir = CASE WHEN (cost>0 and reverse_cost>0) THEN 'B' -- both ways
WHEN (cost>0 and reverse_cost<0) THEN 'FT' -- direction of the LINESSTRING
WHEN (cost<0 and reverse_cost>0) THEN 'TF' -- reverse direction of the LINESTRING
- ELSE '' END; -- unknown
+ ELSE '' END; -- unknown
Before you test a routing function use this query to fill the source and target columns.
@@ -86,10 +86,48 @@ This table is used in some of our examples
.. code-block:: sql
- INSERT INTO vertex_table VALUES
+ INSERT INTO vertex_table VALUES
(1,2,0), (2,2,1), (3,3,1), (4,4,1), (5,0,2), (6,1,2), (7,2,2),
(8,3,2), (9,4,2), (10,2,3), (11,3,3), (12,4,3), (13,2,4);
-.. rubric:: The network created in *edge_table*
-.. image:: ../../../src/common/doc/functions/images/before_node_net.png
+.. rubric:: Network for queries marked as ``directed`` and ``cost`` and ``reverse_cost`` columns are used:
+
+.. _fig1:
+
+.. figure:: ../../../src/common/doc/functions/images/Fig1-originalData.png
+
+ *Graph 1: Directed, with cost and reverse cost*
+
+Blue colored lines with line arrows, represent the ``cost`` of the edge table.
+Green colored lines with filled arrows, represent the ``reverse_cost`` of the edge table.
+
+
+.. rubric:: Network for queries marked as ``undirected`` and ``cost`` and ``reverse_cost`` columns are used:
+
+.. _fig2:
+
+.. figure:: ../../../src/common/doc/functions/images/Fig6-undirected.png
+
+ *Graph 2: Undirected, with cost and reverse cost*
+
+
+.. rubric:: Network for queries marked as ``directed`` and only ``cost`` column is used:
+
+.. _fig3:
+
+
+.. figure:: ../../../src/common/doc/functions/images/Fig2-cost.png
+
+ *Graph 3: Directed, with cost*
+
+
+.. rubric:: Network for queries marked as ``undirected`` and only ``cost`` column is used:
+
+.. _fig4:
+
+.. figure:: ../../../src/common/doc/functions/images/Fig4-costUndirected.png
+
+ *Graph 4: Undirected, with cost*
+
+
diff --git a/doc/src/installation/build.rst b/doc/src/installation/build.rst
index a491e3e..5027668 100644
--- a/doc/src/installation/build.rst
+++ b/doc/src/installation/build.rst
@@ -9,103 +9,108 @@
.. _build:
+###########
Build Guide
+###########
+
+Dependencies
===============================================================================
To be able to compile pgRouting make sure that the following dependencies are met:
-* C and C++ compilers
-* Postgresql version >= 8.4 (>= 9.1 recommended)
-* PostGIS version >= 1.5 (>= 2.0 recommended)
-* The Boost Graph Library (BGL). Version >= [TBD]
+* C and C++0x compilers
+* Postgresql version >= 9.1
+* PostGIS version >= 2.0
+* The Boost Graph Library (BGL). Version >= 1.55
* CMake >= 2.8.8
-* (optional, for Driving Distance) CGAL >= [TBD]
+* CGAL >= 4.2
* (optional, for Documentation) Sphinx >= 1.1
* (optional, for Documentation as PDF) Latex >= [TBD]
-The cmake system has variables the can be configured via the command line options by setting them with -D<varable>=<value>. You can get a listing of these via:
+Configuration
+===============================================================================
-.. code-block:: bash
+PgRouting uses the `cmake` system to do the configuration.
- mkdir build
- cd build
- cmake -L ..
+The following instructions start from *path/to/pgrouting/*
-Currently these are:
+Ccreate the build directory
- Boost_DIR:PATH=Boost_DIR-NOTFOUND
- CMAKE_BUILD_TYPE:STRING=
- CMAKE_INSTALL_PREFIX:PATH=/usr/local
- POSTGRESQL_EXECUTABLE:FILEPATH=/usr/lib/postgresql/9.2/bin/postgres
- POSTGRESQL_PG_CONFIG:FILEPATH=/usr/bin/pg_config
- WITH_DD:BOOL=ON
- WITH_DOC:BOOL=OFF
- BUILD_HTML:BOOL=ON
- BUILD_LATEX:BOOL=OFF
- BUILD_MAN:BOOL=ON
+.. code-block:: bash
-These also show the current or default values based on our development system. So your values my be different. In general the ones that are of most interest are:
+ $ mkdir build
- WITH_DD:BOOL=ON -- Turn on/off building driving distance code.
- WITH_DOC:BOOL=OFF -- Turn on/off building the documentation
- BUILD_HTML:BOOL=ON -- If WITH_DOC=ON, turn on/off building HTML
- BUILD_LATEX:BOOL=OFF -- If WITH_DOC=ON, turn on/off building PDF
- BUILD_MAN:BOOL=ON -- If WITH_DOC=ON, turn on/off building MAN pages
-To change any of these add ``-D<variable>=<value>`` to the cmake lines below. For example to turn on documentation, your cmake command might look like:
+To configure:
.. code-block:: bash
- cmake -DWITH_DOC=ON .. # Turn on the doc with default settings
- cmake -DWITH_DOC=ON -DBUILD_LATEX .. # Turn on doc and pdf
-
-If you turn on the documentation, you also need to add the ``doc`` target to the make command.
+ $ cd build
+ $ cmake -L ..
-.. code-block:: bash
+Configurable variables
+----------------------
- make # build the code but not the doc
- make doc # build only the doc
- make all doc # build both the code and the doc
+The documentation configurable variables are:
+:WITH_DOC: BOOL=OFF -- Turn on/off building the documentation
+:BUILD_HTML: BOOL=ON -- If WITH_DOC=ON, turn on/off building HTML
+:BUILD_LATEX: BOOL=OFF -- If WITH_DOC=ON, turn on/off building PDF
+:BUILD_MAN: BOOL=OFF -- If WITH_DOC=ON, turn on/off building MAN pages
-For MinGW on Windows
-********************************************************************************
+Configuring with documentation
.. code-block:: bash
- mkdir build
- cd build
- cmake -G"MSYS Makefiles" ..
- make
- make install
+ $ cmake -DWITH_DOC=ON ..
+.. note:: Most of the effort of the documentation has being on the html files.
-For Linux
-********************************************************************************
+
+Building
+===============================================================================
+
+Using ``make`` to build the code and the docuemtnation
+
+The following instructions start from *path/to/pgrouting/build*
.. code-block:: bash
- mkdir build
- cd build
- cmake ..
- make
- sudo make install
+ $ make # build the code but not the documentation
+ $ make doc # build only the documentation
+ $ make all doc # build both the code and the documentation
+Installation and reinstallation
+===============================================================================
-With Documentation
-********************************************************************************
+We have tested on several plataforms, For installing or reinstalling all the steps are needed.
-Build with documentation (requires `Sphinx <http://sphinx-doc.org/>`_):
+.. warning:: The sql signatures are configured and build in the ``cmake`` command.
+
+For MinGW on Windows
+----------------------------------------------------------------
.. code-block:: bash
- cmake -DWITH_DOC=ON ..
- make all doc
+ $ mkdir build
+ $ cd build
+ $ cmake -G"MSYS Makefiles" ..
+ $ make
+ $ make install
-Rebuild modified documentation only:
+For Linux
+----------------------------------------------------------------
+
+The following instructions start from *path/to/pgrouting*
.. code-block:: bash
- sphinx-build -b html -c build/doc/_build -d build/doc/_doctrees . build/html
+ $ mkdir build
+ $ cd build
+ $ cmake ..
+ $ make
+ $ sudo make install
+
+
diff --git a/doc/src/installation/index.rst b/doc/src/installation/index.rst
index 651d977..3a5cb4c 100644
--- a/doc/src/installation/index.rst
+++ b/doc/src/installation/index.rst
@@ -1,9 +1,9 @@
-..
+..
****************************************************************************
pgRouting Manual
Copyright(c) pgRouting Contributors
- This documentation is licensed under a Creative Commons Attribution-Share
+ This documentation is licensed under a Creative Commons Attribution-Share
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
@@ -12,15 +12,29 @@
Installation
===============================================================================
+This is a basic guide to download and install pgRouting.
+
+.. note:: additional notes can be found in `Installation Notes`_
+
+.. _Installation Notes: https://github.com/pgRouting/pgrouting/wiki/Notes-on-Download%2C-Installation-and-building-pgRouting
+
+Download
+--------
+
Binary packages are provided for the current version on the following platforms:
Windows
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Winnie Bot Experimental Builds:
+Winnie Bot Builds:
-* `PostgreSQL 9.2 32-bit, 64-bit <http://winnie.postgis.net/download/windows/pg92/buildbot/>`_
+* `Winnie PostgreSQL 9.2-9.5 32-bit/64-bit <http://postgis.net/windows_downloads>`_
+
+Production Builds:
+
+* Production builds are part of the Spatial Extensions/PostGIS Bundle available via Application StackBuilder
+* `Can also get PostGIS Bundle from <http://download.osgeo.org/postgis/windows/>`_
Ubuntu/Debian
@@ -49,6 +63,17 @@ RHEL/CentOS/Fedora
* Fedora RPM's: https://admin.fedoraproject.org/pkgdb/acls/name/pgRouting
+FreeBSD
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+pgRouting can be installed via ports:
+
+.. code-block:: bash
+
+ cd /usr/ports/databases/pgRouting
+ make install clean
+
+
OS X
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -64,29 +89,11 @@ OS X
Source Package
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-======================== ======================= ====================
-Git 2.0.0-rc1 release `v2.0.0-rc1.tar.gz`_ `v2.0.0-rc1.zip`_
-Git 2.0.0-beta release `v2.0.0-beta.tar.gz`_ `v2.0.0-beta.zip`_
-Git 2.0.0-alpha release `v2.0.0-alpha.tar.gz`_ `v2.0.0-alpha.zip`_
-Git master branch `master.tar.gz`_ `master.zip`_
-Git develop branch `develop.tar.gz`_ `develop.zip`_
-======================== ======================= ====================
-
-.. _v2.0.0-rc1.tar.gz: https://github.com/pgRouting/pgrouting/archive/v2.0.0-rc1.tar.gz
-.. _v2.0.0-rc1.zip: https://github.com/pgRouting/pgrouting/archive/v2.0.0-rc1.zip
+You can find all the pgRouting Releases:
-.. _v2.0.0-beta.tar.gz: https://github.com/pgRouting/pgrouting/archive/v2.0.0-beta.tar.gz
-.. _v2.0.0-beta.zip: https://github.com/pgRouting/pgrouting/archive/v2.0.0-beta.zip
-
-.. _v2.0.0-alpha.tar.gz: https://github.com/pgRouting/pgrouting/archive/v2.0.0-alpha.tar.gz
-.. _v2.0.0-alpha.zip: https://github.com/pgRouting/pgrouting/archive/v2.0.0-alpha.zip
-
-.. _master.tar.gz: https://github.com/pgRouting/pgrouting/archive/master.tar.gz
-.. _master.zip: https://github.com/pgRouting/pgrouting/archive/master.zip
-
-.. _develop.tar.gz: https://github.com/pgRouting/pgrouting/archive/develop.tar.gz
-.. _develop.zip: https://github.com/pgRouting/pgrouting/archive/develop.zip
+https://github.com/pgRouting/pgrouting/releases
+See :ref:`build` to build the binaries from the source.
Using Git
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -99,9 +106,31 @@ Git protocol (read-only):
HTTPS protocol (read-only):
+
.. code-block:: bash
git clone https://github.com/pgRouting/pgrouting.git
+See :ref:`build` to build the binaries from the source.
+
+Installing in the database
+--------------------------
+
+pgRouting is an extension.
+
+.. code-block:: sql
+
+ CREATE EXTENSION postgis;
+ CREATE EXTENSION pgrouting;
+
+
+Upgrading the database
+----------------------
+
+To upgrade pgRouting to version 2.1.0 use the following command:
+
+.. code-block:: sql
+
+ ALTER EXTENSION pgrouting UPDATE TO "2.1.0";
+
-See :ref:`build` for notes on compiling from source.
diff --git a/doc/src/introduction/images/boost-inside.jpeg b/doc/src/introduction/images/boost-inside.jpeg
new file mode 100644
index 0000000..985cb36
Binary files /dev/null and b/doc/src/introduction/images/boost-inside.jpeg differ
diff --git a/doc/src/introduction/introduction.rst b/doc/src/introduction/introduction.rst
index c271b20..56e4e1a 100644
--- a/doc/src/introduction/introduction.rst
+++ b/doc/src/introduction/introduction.rst
@@ -55,9 +55,25 @@ Corporate Sponsors (in alphabetical order)
These are corporate entities that have contributed developer time, hosting, or direct monetary funding to the pgRouting project:
- Camptocamp, CSIS (University of Tokyo), Georepublic, Google Summer of Code, iMaptools, Orkney, Paragon Corporation
+ - Camptocamp
+ - CSIS (University of Tokyo)
+ - Georepublic
+ - Google Summer of Code
+ - iMaptools
+ - Orkney
+ - Paragon Corporation
+Inside
+------
+
+.. _boost-inside:
+
+.. figure:: ./images/boost-inside.jpeg
+ :target: http://www.boost.org/libs/graph
+
+ Boost Graph Inside
+
More Information
-------------------------------------------------------------------------------
diff --git a/doc/src/tutorial/recipes.rst b/doc/src/recipes/example_recipe.rst
similarity index 56%
rename from doc/src/tutorial/recipes.rst
rename to doc/src/recipes/example_recipe.rst
index 537dd95..a7bca43 100644
--- a/doc/src/tutorial/recipes.rst
+++ b/doc/src/recipes/example_recipe.rst
@@ -7,30 +7,18 @@
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
-.. _recipes:
-
-Use's Recipes contributions
-===============================================================================
-
-.. rubric:: How to contribute.
-
-Use an issue tracker (see :ref:`support`) with a title containing: *Proposing a Recipe: Myrecipename*. The body will contain:
-
- - author: Required
- - mail: if you are subscribed to the developers list this is not necessary
- - date: Date posted
- - comments and code: using reStructuredText format
-
-Any contact with the author will be done using the developers mailing list. The pgRouting team will evaluate the recipe and will be included it in this section when approved.
+.. _example_recipe:
Comparing topology of a unnoded network with a noded network
-------------------------------------------------------------
-
:Author: pgRouting team.
+:Licence: Open Source
This recipe uses the :ref:`sampledata` network.
+The purpose of this recipe is to compare a not nodded network with a nodded network.
+
.. code-block:: sql
SELECT pgr_createTopology('edge_table', 0.001);
@@ -39,4 +27,3 @@ This recipe uses the :ref:`sampledata` network.
SELECT pgr_createTopology('edge_table_noded', 0.001);
SELECT pgr_analyzegraph('edge_table_noded', 0.001);
-*No more contributions*
diff --git a/doc/src/recipes/images/parallelImage.png b/doc/src/recipes/images/parallelImage.png
new file mode 100644
index 0000000..7469c29
Binary files /dev/null and b/doc/src/recipes/images/parallelImage.png differ
diff --git a/doc/src/recipes/index.rst b/doc/src/recipes/index.rst
new file mode 100644
index 0000000..44a3c1f
--- /dev/null
+++ b/doc/src/recipes/index.rst
@@ -0,0 +1,83 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _recipes:
+
+User's Recipes List
+===============================================================================
+
+
+.. toctree::
+
+ ./example_recipe.rst
+ ./parallel_handling.rst
+
+
+*No more contributions*
+
+
+How to contribute.
+==================
+
+.. rubric:: To add a recipie or a wrapper
+
+The first steps are:
+
+ - Fork the repository
+ - Create a branch for your recipe or wrapper
+ - Create your recipe file
+
+.. code::
+
+ cd doc/src/recipes/
+ vi myrecipe.rst
+ git add myrecipe.rst
+ # include the recipe in this file
+ vi index.rst
+
+.. rubric:: To create the test file of your recipe
+
+.. code::
+
+ cd test
+ cp myrecipe.rst myrecipe.sql.test
+
+ # make your test based on your recipe
+ vi myrecipe.sql.test
+ git add myrecipe.sql.test
+
+ # create your test results file
+ touch myrecipe.result
+ git add myrecipe.result
+
+ # add your test to the file
+ vi test.conf
+
+Leave only the SQL code on ``myrecipe.sql.test`` by deleting lines or by commenting lines.
+
+
+.. rubric:: To get the results of your recipe
+
+From the root directory execute:
+
+.. code::
+
+ tools/test-runner.pl -alg recipes -ignorenotice
+
+Copy the results of your recipe and paste them in the file ``myrecipe.result``, and remove the "> " from the file.
+
+.. rubric:: make a pull request.
+
+.. code::
+
+ git commit -a -m 'myrecipe is for this and that'
+ git push
+
+From your fork in github make a pull request over develop
+
diff --git a/doc/src/recipes/parallel_handling.rst b/doc/src/recipes/parallel_handling.rst
new file mode 100644
index 0000000..f20ddb3
--- /dev/null
+++ b/doc/src/recipes/parallel_handling.rst
@@ -0,0 +1,221 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _parallel_handling:
+
+Handling parallels after getting a path (pgr_ksp focus)
+-------------------------------------------------------
+
+:Author: pgRouting team.
+:Licence: Open Source
+
+
+.. rubric:: The graph
+
+
+.. image:: ./images/parallelImage.png
+
+
+.. rubric:: Data
+
+.. code-block:: sql
+
+ drop table if exists parallel;
+ CREATE TABLE parallel (
+ id serial,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ the_geom geometry
+ );
+
+ INSERT INTO parallel (x1,y1,x2,y2)
+ VALUES (1,0,1,1),(1,1,1,3),(1,1,1,3),(1,1,1,3),(1,3,1,4),(1,1,-1,1),(-1,1,-1,3),(-1,3,1,3);
+ UPDATE parallel SET the_geom = ST_makeline(ST_point(x1,y1),ST_point(x2,y2));
+ UPDATE parallel SET the_geom = ST_makeline(ARRAY[ST_point(1,1),ST_point(0,2),ST_point(1,3)]) WHERE id = 3;
+ UPDATE parallel SET the_geom = ST_makeline(ARRAY[ST_point(1,1),ST_point(2,1),ST_point(2,3),ST_point(1,3)])
+ WHERE id = 4;
+ UPDATE parallel SET cost = ST_length(the_geom), reverse_cost = ST_length(the_geom);
+ SELECT pgr_createTopology('parallel',0.001);
+
+.. rubric:: pgr_ksp results
+
+We ignore the costs because we want all the parallels
+
+.. code-block:: sql
+
+ SELECT seq, path_id AS route, node, edge INTO routes
+ from pgr_ksp('select id, source, target, cost, reverse_cost from parallel',
+ 1, 4, 3);
+
+ select route, node, edge from routes;
+ route | node | edge
+ -------+------+------
+ 1 | 1 | 1
+ 1 | 2 | 2
+ 1 | 3 | 5
+ 1 | 4 | -1
+ 2 | 1 | 1
+ 2 | 2 | 6
+ 2 | 5 | 7
+ 2 | 6 | 8
+ 2 | 3 | 5
+ 2 | 4 | -1
+ (10 rows)
+
+
+.. rubric:: We need an aggregate function:
+
+.. code-block:: sql
+
+ CREATE AGGREGATE array_accum (anyelement)
+ (
+ sfunc = array_append,
+ stype = anyarray,
+ initcond = '{}'
+ );
+
+
+.. rubric:: Now lets generate a table with the parallel edges.
+
+.. code-block:: sql
+
+ select distinct seq,route,source,target, array_accum(id) as edges into paths
+ from (select seq, route, source, target
+ from parallel, routes where id = edge) as r
+ join parallel using (source, target)
+ group by seq,route,source,target order by seq;
+
+ select route, source, targets, edges from paths;
+ route | source | target | edges
+ -------+--------+--------+---------
+ 1 | 1 | 2 | {1}
+ 2 | 1 | 2 | {1}
+ 2 | 2 | 5 | {6}
+ 1 | 2 | 3 | {2,3,4}
+ 2 | 5 | 6 | {7}
+ 1 | 3 | 4 | {5}
+ 2 | 6 | 3 | {8}
+ 2 | 3 | 4 | {5}
+ (8 rows)
+
+
+.. rubric:: Some more aggregate functions
+
+To generate a table with all the combinations for parallel routes, we need some more aggregates
+
+.. code-block:: sql
+
+ create or replace function multiply( integer, integer )
+ returns integer as
+ $$
+ select $1 * $2;
+ $$
+ language sql stable;
+
+ create aggregate prod(integer)
+ (
+ sfunc = multiply,
+ stype = integer,
+ initcond = 1
+ );
+
+.. rubric:: And a function that "Expands" the table
+
+
+
+.. code-block:: sql
+
+ CREATE OR REPLACE function expand_parallel_edge_paths(tab text)
+ returns TABLE (
+ seq INTEGER,
+ route INTEGER,
+ source INTEGER, target INTEGER, -- this ones are not really needed
+ edge INTEGER ) AS
+ $body$
+ DECLARE
+ nroutes INTEGER;
+ newroutes INTEGER;
+ rec record;
+ seq2 INTEGER := 1;
+ rnum INTEGER := 0;
+
+ BEGIN -- get the number of distinct routes
+ execute 'select count(DISTINCT route) from ' || tab INTO nroutes;
+ FOR i IN 0..nroutes-1
+ LOOP
+ -- compute the number of new routes this route will expand into
+ -- this is the product of the lengths of the edges array for each route
+ execute 'select prod(array_length(edges, 1))-1 from '
+ || quote_ident(tab) || ' where route=' || i INTO newroutes;
+ -- now we generate the number of new routes for this route
+ -- by repeatedly listing the route and swapping out the parallel edges
+ FOR j IN 0..newroutes
+ LOOP
+ -- query the specific route
+ FOR rec IN execute 'select * from ' || quote_ident(tab) ||' where route=' || i
+ || ' order by seq'
+ LOOP
+ seq := seq2;
+ route := rnum;
+ source := rec.source;
+ target := rec.target;
+ -- using module arithmetic iterate through the various edge choices
+ edge := rec.edges[(j % (array_length(rec.edges, 1)))+1];
+ -- return a new record
+ RETURN next;
+ seq2 := seq2 + 1; -- increment the record count
+ END LOOP;
+ seq := seq2;
+ route := rnum;
+ source := rec.target;
+ target := -1;
+ edge := -1;
+ RETURN next; -- Insert the ending record of the route
+ seq2 := seq2 + 1;
+
+ rnum := rnum + 1; -- increment the route count
+ END LOOP;
+ END LOOP;
+ END;
+ $body$
+ language plpgsql volatile strict cost 100 rows 100;
+
+.. rubric:: Test it
+
+.. code-block:: sql
+
+ select * from expand_parallel_edge_paths( 'paths' );
+ seq | route | source | target | edge
+ -----+-------+--------+--------+------
+ 1 | 0 | 1 | 2 | 1
+ 2 | 0 | 2 | 3 | 2
+ 3 | 0 | 3 | 4 | 5
+ 4 | 0 | 4 | -1 | -1
+ 5 | 1 | 1 | 2 | 1
+ 6 | 1 | 2 | 3 | 3
+ 7 | 1 | 3 | 4 | 5
+ 8 | 1 | 4 | -1 | -1
+ 9 | 2 | 1 | 2 | 1
+ 10 | 2 | 2 | 3 | 4
+ 11 | 2 | 3 | 4 | 5
+ 12 | 2 | 4 | -1 | -1
+ 13 | 3 | 1 | 2 | 1
+ 14 | 3 | 2 | 5 | 6
+ 15 | 3 | 5 | 6 | 7
+ 16 | 3 | 6 | 3 | 8
+ 17 | 3 | 3 | 4 | 5
+ 18 | 3 | 4 | -1 | -1
+ (18 rows)
+
diff --git a/doc/src/recipes/test/example_recipe.result b/doc/src/recipes/test/example_recipe.result
new file mode 100644
index 0000000..21da4d2
--- /dev/null
+++ b/doc/src/recipes/test/example_recipe.result
@@ -0,0 +1,5 @@
+OK
+OK
+OK
+OK
+OK
diff --git a/doc/src/recipes/test/example_recipe.test.sql b/doc/src/recipes/test/example_recipe.test.sql
new file mode 100644
index 0000000..2e9b913
--- /dev/null
+++ b/doc/src/recipes/test/example_recipe.test.sql
@@ -0,0 +1,30 @@
+/*..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+*/
+--.. _example_recipe:
+
+--Comparing topology of a unnoded network with a noded network
+-------------------------------------------------------------
+
+--:Author: pgRouting team.
+--:Licence: Open Source
+
+--This recipe uses the :ref:`sampledata` network.
+
+--The purpose of this recipe is to compare a not nodded network with a nodded network.
+
+--.. code-block:: sql
+set client_min_messages = warning;
+
+ SELECT pgr_createTopology('edge_table', 0.001);
+ SELECT pgr_analyzegraph('edge_table', 0.001);
+ SELECT pgr_nodeNetwork('edge_table', 0.001);
+ SELECT pgr_createTopology('edge_table_noded', 0.001);
+ SELECT pgr_analyzegraph('edge_table_noded', 0.001);
+
diff --git a/doc/src/recipes/test/parallel_handling.result b/doc/src/recipes/test/parallel_handling.result
new file mode 100644
index 0000000..4a815b0
--- /dev/null
+++ b/doc/src/recipes/test/parallel_handling.result
@@ -0,0 +1,33 @@
+NOTICE: table "parallel" does not exist, skipping
+NOTICE: PROCESSING:
+NOTICE: pgr_createTopology('parallel',0.001,'the_geom','id','source','target','true')
+NOTICE: Performing checks, please wait .....
+NOTICE: Creating Topology, Please wait...
+NOTICE: -------------> TOPOLOGY CREATED FOR 8 edges
+NOTICE: Rows with NULL geometry or NULL id: 0
+NOTICE: Vertices table for table public.parallel is: public.parallel_vertices_pgr
+NOTICE: ----------------------------------------------
+OK
+1|1|1
+1|2|2
+1|3|5
+1|4|-1
+2|1|1
+2|2|6
+2|5|7
+2|6|8
+2|3|5
+2|4|-1
+1|0||-1|-1
+2|1|1|2|1
+3|1|2|3|2
+4|1|3|4|5
+5|1|4|-1|-1
+6|2|1|2|1
+7|2|2|3|3
+8|2|3|4|5
+9|2|4|-1|-1
+10|3|1|2|1
+11|3|2|3|4
+12|3|3|4|5
+13|3|4|-1|-1
diff --git a/doc/src/recipes/test/parallel_handling.test.sql b/doc/src/recipes/test/parallel_handling.test.sql
new file mode 100644
index 0000000..4ad16a0
--- /dev/null
+++ b/doc/src/recipes/test/parallel_handling.test.sql
@@ -0,0 +1,121 @@
+ drop table if exists parallel;
+ CREATE TABLE parallel (
+ id serial,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ the_geom geometry
+ );
+
+ INSERT INTO parallel (x1,y1,x2,y2)
+ VALUES (1,0,1,1),(1,1,1,3),(1,1,1,3),(1,1,1,3),(1,3,1,4),(1,1,-1,1),(-1,1,-1,3),(-1,3,1,3);
+ UPDATE parallel SET the_geom = ST_makeline(ST_point(x1,y1),ST_point(x2,y2));
+ UPDATE parallel SET the_geom = ST_makeline(ARRAY[ST_point(1,1),ST_point(0,2),ST_point(1,3)]) WHERE id = 3;
+ UPDATE parallel SET the_geom = ST_makeline(ARRAY[ST_point(1,1),ST_point(2,1),ST_point(2,3),ST_point(1,3)])
+ WHERE id = 4;
+ UPDATE parallel SET cost = ST_length(the_geom), reverse_cost = ST_length(the_geom);
+ SELECT pgr_createTopology('parallel',0.001);
+
+
+ select seq, path_id as route, node, edge into routes
+ from pgr_ksp('select id, source, target, cost, reverse_cost from parallel',
+ 1, 4, 3);
+
+ select route, node, edge from routes;
+
+ CREATE AGGREGATE array_accum (anyelement)
+ (
+ sfunc = array_append,
+ stype = anyarray,
+ initcond = '{}'
+ );
+
+
+
+ select distinct seq,route,source,target, array_accum(id) as edges into paths
+ from (select seq, route, source, target
+ from parallel, routes where id = edge) as r
+ join parallel using (source, target)
+ group by seq,route,source,target order by seq;
+
+ -- select route, source, target, edges from paths;
+
+ create or replace function multiply( integer, integer )
+ returns integer as
+ $$
+ select $1 * $2;
+ $$
+ language sql stable;
+
+ create aggregate prod(integer)
+ (
+ sfunc = multiply,
+ stype = integer,
+ initcond = 1
+ );
+
+
+
+ CREATE OR REPLACE function expand_parallel_edge_paths(tab text)
+ returns TABLE (
+ seq INTEGER,
+ route INTEGER,
+ source INTEGER, target INTEGER, -- this ones are not really needed
+ edge INTEGER ) AS
+ $body$
+ DECLARE
+ nroutes INTEGER;
+ newroutes INTEGER;
+ rec record;
+ seq2 INTEGER := 1;
+ rnum INTEGER := 0;
+
+ BEGIN -- get the number of distinct routes
+ execute 'select count(DISTINCT route) from ' || tab INTO nroutes;
+ FOR i IN 0..nroutes-1
+ LOOP
+ -- compute the number of new routes this route will expand into
+ -- this is the product of the lengths of the edges array for each route
+ execute 'select prod(array_length(edges, 1))-1 from '
+ || quote_ident(tab) || ' where route=' || i INTO newroutes;
+ -- now we generate the number of new routes for this route
+ -- by repeatedly listing the route and swapping out the parallel edges
+ FOR j IN 0..newroutes
+ LOOP
+ -- query the specific route
+ FOR rec IN execute 'select * from ' || quote_ident(tab) ||' where route=' || i
+ || ' order by seq'
+ LOOP
+ seq := seq2;
+ route := rnum;
+ source := rec.source;
+ target := rec.target;
+ -- using module arithmetic iterate through the various edge choices
+ edge := rec.edges[(j % (array_length(rec.edges, 1)))+1];
+ -- return a new record
+ RETURN next;
+ seq2 := seq2 + 1; -- increment the record count
+ END LOOP;
+ seq := seq2;
+ route := rnum;
+ source := rec.target;
+ target := -1;
+ edge := -1;
+ RETURN next; -- Insert the ending record of the route
+ seq2 := seq2 + 1;
+
+ rnum := rnum + 1; -- increment the route count
+ END LOOP;
+ END LOOP;
+ END;
+ $body$
+ language plpgsql volatile strict cost 100 rows 100;
+
+
+
+ select * from expand_parallel_edge_paths( 'paths' );
diff --git a/doc/test/sampledata.data b/doc/src/recipes/test/sampledata.data.sql
similarity index 97%
copy from doc/test/sampledata.data
copy to doc/src/recipes/test/sampledata.data.sql
index a5e899c..db6f2cb 100644
--- a/doc/test/sampledata.data
+++ b/doc/src/recipes/test/sampledata.data.sql
@@ -4,6 +4,7 @@
-- SAMPLE DATA
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
+drop table if exists edge_table;
CREATE TABLE edge_table (
id serial,
@@ -46,6 +47,7 @@ UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
select pgr_createTopology('edge_table',0.001);
+drop table if exists vertex_table;
CREATE TABLE vertex_table (
id serial,
x double precision,
diff --git a/src/driving_distance/test/test.conf b/doc/src/recipes/test/test.conf
similarity index 50%
copy from src/driving_distance/test/test.conf
copy to doc/src/recipes/test/test.conf
index c988afc..a030d77 100644
--- a/src/driving_distance/test/test.conf
+++ b/doc/src/recipes/test/test.conf
@@ -2,10 +2,16 @@
%main::tests = (
'any' => {
- 'comment' => 'Driving Distance test for any versions.',
- 'data' => ['drivingdistance-any-00.data'],
- 'tests' => [qw(drivingdistance-any-00)]
+ 'comment' => 'Recipes test for any versions.',
+ 'data' => ['sampledata.data.sql'],
+ 'tests' => [qw(
+parallel_handling
+example_recipe
+zzz-remove_sampledata
+)]
},
+
+# 'data' => ['sampledata.data.sql'],
# 'vpg-vpgis' => {}, # for version specific tests
# '8-1' => {}, # for pg 8.x and postgis 1.x
# '9.2-2.1' => {}, # for pg 9.2 and postgis 2.1
diff --git a/src/common/src/CMakeLists.txt b/doc/src/recipes/test/zzz-remove_sampledata.result
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to doc/src/recipes/test/zzz-remove_sampledata.result
diff --git a/doc/test/dijkstra-any.test b/doc/src/recipes/test/zzz-remove_sampledata.test.sql
similarity index 54%
copy from doc/test/dijkstra-any.test
copy to doc/src/recipes/test/zzz-remove_sampledata.test.sql
index 1593f19..d6335c6 100644
--- a/doc/test/dijkstra-any.test
+++ b/doc/src/recipes/test/zzz-remove_sampledata.test.sql
@@ -1,15 +1,8 @@
+
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
--- PGR_dijkstra
+-- REMOVE SAMPLE DATA
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
-
-SELECT seq, id1 AS node, id2 AS edge, cost
- FROM pgr_dijkstra(
- 'SELECT id, source, target, cost FROM edge_table order by id',
- 7, 12, false, false);
-
-SELECT seq, id1 AS node, id2 AS edge, cost
- FROM pgr_dijkstra(
- 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
- 7, 12, true, true);
+drop table if exists edge_table;
+drop table if exists vertex_table;
diff --git a/doc/src/tutorial/custom_query.rst b/doc/src/tutorial/custom_query.rst
index 2ad32d5..1a2502e 100644
--- a/doc/src/tutorial/custom_query.rst
+++ b/doc/src/tutorial/custom_query.rst
@@ -9,10 +9,61 @@
.. _custom_query:
-Custom Query
+Dictionary of columns & Custom Query
===============================================================================
-.. Routing Algorithms:
+:path: a sequence of vertices/edges from A to B.
+:route: a sequence of paths.
+
+Description of the edges_sql query
+-------------------------------------------------------------------------------
+
+:edges_sql: an SQL query, which should return a set of rows with the following columns:
+
+ :id: ``ANY-INTEGER`` identifier of the edge.
+ :source: ``ANY-INTEGER`` identifier of the first end point vertex of the edge.
+ :target: ``ANY-INTEGER`` identifier of the second end pont vertex of the edge.
+ :cost: ``ANY-NUMERICAL`` weight of the edge `(source, target)`, if negative: edge `(source, target)` does not exist, therefore it's not part of the graph.
+ :reverse_cost: ``ANY-NUMERICAL`` (optional) weight of the edge `(target, source)`, if negative: edge `(target, source)` does not exist, therefore it's not part of the graph.
+
+Where:
+
+:ANY-INTEGER: smallint, int, bigint
+:ANY-NUMERICAL: smallint, int, bigint, real, float
+
+
+Description of the parameters of the signatures
+-------------------------------------------------------------------------------
+
+:edges_sql: ``TEXT`` SQL query as decribed above.
+:start_vid: ``BIGINT`` identifier of the starting vertex of the path.
+:start_vids: ``array[ANY-INTEGER]`` array of identifiers of starting vertices.
+:end_vid: ``BIGINT`` identifier of the ending vertex of the path.
+:end_vids: ``array[ANY-INTEGER]`` array of identifiers of ending vertices.
+:directed: ``boolean`` (optional). When ``false`` the graph is considered as Undirected. Default is ``true`` which considers the graph as Directed.
+
+
+Description of the return values
+-------------------------------------------------------------------------------
+
+Returns set of ``(seq [, start_vid] [, end_vid] , node, edge, cost, agg_cost)``
+
+:seq: ``INTEGER`` is a sequential value starting from **1**.
+:route_seq: ``INTEGER`` relative position in the route. Has value **1** for the begining of a route.
+:route_id: ``INTEGER`` id of the route.
+:path_seq: ``INTEGER`` relative position in the path. Has value **1** for the begining of a path.
+:path_id: ``INTEGER`` id of the path.
+:start_vid: ``BIGINT`` id of the starting vertex. Used when multiple starting vetrices are in the query.
+:end_vid: ``BIGINT`` id of the ending vertex. Used when multiple ending vertices are in the query.
+:node: ``BIGINT`` id of the node in the path from start_vid to end_v.
+:edge: ``BIGINT`` id of the edge used to go from ``node`` to the next node in the path sequence. ``-1`` for the last node of the path.
+:cost: ``FLOAT`` cost to traverse from ``node`` using ``edge`` to the next node in the path sequence.
+:agg_cost: ``FLOAT`` total cost from ``start_vid`` to ``node``.
+
+
+
+Descriptions for version 2.0 signatures
+---------------------------------------
In general, the routing algorithms need an SQL query that contain one or more of the following required columns with the preferred type:
@@ -28,7 +79,7 @@ In general, the routing algorithms need an SQL query that contain one or more of
:x2: float8
:y2: float8
-When the edge table has the mentioned columns, the following SQL queries can be used.
+
.. code-block:: sql
diff --git a/doc/src/tutorial/index.rst b/doc/src/tutorial/index.rst
index cbd19e8..9d6fe27 100644
--- a/doc/src/tutorial/index.rst
+++ b/doc/src/tutorial/index.rst
@@ -29,8 +29,6 @@ Advanced Topics
- :ref:`analytics` for an overview of the analysis of a graph.
- :ref:`custom_query` that is used in the routing algorithms.
- :ref:`performance` to improve your performance.
- - :ref:`custom_wrapper` to colaborate with a wrapper.
- - :ref:`recipes` to colaborate with a recipe.
.. toctree::
:hidden:
@@ -44,8 +42,4 @@ Advanced Topics
An overview of the analysis of a graph. <analytics>
How to write a query for the routing algorithms <custom_query>
How to handle performance <performance>
- User's wrappers contributions <custom_wrapper>
- User's recipies contributions <recipes>
-
-
diff --git a/doc/src/tutorial/performance.rst b/doc/src/tutorial/performance.rst
index 658aee8..391c971 100644
--- a/doc/src/tutorial/performance.rst
+++ b/doc/src/tutorial/performance.rst
@@ -12,7 +12,14 @@
Performance Tips
===============================================================================
+For the Routing functions:
+--------------------------
+.. Note:: To get faster results bound your queries to the area of interest of routing to have, for example, no more than one million rows.
+
+
+For the topology functions:
+---------------------------
When "you know" that you are going to remove a set of edges from the edges table, and without those edges you are going to use a routing function you can do the following:
Analize the new topology based on the actual topology:
diff --git a/doc/src/tutorial/tutorial.rst b/doc/src/tutorial/tutorial.rst
index 06f9cca..408457a 100644
--- a/doc/src/tutorial/tutorial.rst
+++ b/doc/src/tutorial/tutorial.rst
@@ -138,14 +138,14 @@ to get more information about each step in the path.
* See also :ref:`type_cost_result` and :ref:`type_geom_result`.
-How to use other tools to view your graph and route
--------------------------------------------------------------------------------
+.. How to use other tools to view your graph and route
+.. -------------------------------------------------------------------------------
-TBD
+.. TBD
-How to create a web app
--------------------------------------------------------------------------------
+.. How to create a web app
+.. -------------------------------------------------------------------------------
-TBD
+.. TBD
diff --git a/doc/static/images/developers/disconnectEdgeDirected.graphmlz b/doc/static/images/developers/disconnectEdgeDirected.graphmlz
new file mode 100644
index 0000000..9b55538
Binary files /dev/null and b/doc/static/images/developers/disconnectEdgeDirected.graphmlz differ
diff --git a/doc/static/images/developers/disconnectEdgeDirected.png b/doc/static/images/developers/disconnectEdgeDirected.png
new file mode 100644
index 0000000..1a33e3a
Binary files /dev/null and b/doc/static/images/developers/disconnectEdgeDirected.png differ
diff --git a/doc/static/images/developers/disconnectEdgeUndirected.graphmlz b/doc/static/images/developers/disconnectEdgeUndirected.graphmlz
new file mode 100644
index 0000000..d091120
Binary files /dev/null and b/doc/static/images/developers/disconnectEdgeUndirected.graphmlz differ
diff --git a/doc/static/images/developers/disconnectEdgeUndirected.png b/doc/static/images/developers/disconnectEdgeUndirected.png
new file mode 100644
index 0000000..9590aef
Binary files /dev/null and b/doc/static/images/developers/disconnectEdgeUndirected.png differ
diff --git a/doc/static/images/developers/disconnectVertexDirected.graphmlz b/doc/static/images/developers/disconnectVertexDirected.graphmlz
new file mode 100644
index 0000000..80ac571
Binary files /dev/null and b/doc/static/images/developers/disconnectVertexDirected.graphmlz differ
diff --git a/doc/static/images/developers/disconnectVertexDirected.png b/doc/static/images/developers/disconnectVertexDirected.png
new file mode 100644
index 0000000..6a5c209
Binary files /dev/null and b/doc/static/images/developers/disconnectVertexDirected.png differ
diff --git a/doc/static/images/developers/disconnectVertexUndirected.graphmlz b/doc/static/images/developers/disconnectVertexUndirected.graphmlz
new file mode 100644
index 0000000..2570357
Binary files /dev/null and b/doc/static/images/developers/disconnectVertexUndirected.graphmlz differ
diff --git a/doc/static/images/developers/disconnectVertexUndirected.png b/doc/static/images/developers/disconnectVertexUndirected.png
new file mode 100644
index 0000000..1d6be3a
Binary files /dev/null and b/doc/static/images/developers/disconnectVertexUndirected.png differ
diff --git a/doc/test/alphashape-any.rest b/doc/test/alphashape-any.result
similarity index 100%
rename from doc/test/alphashape-any.rest
rename to doc/test/alphashape-any.result
diff --git a/doc/test/alphashape-any.test b/doc/test/alphashape-any.test
deleted file mode 100644
index 826ad6e..0000000
--- a/doc/test/alphashape-any.test
+++ /dev/null
@@ -1,24 +0,0 @@
---------------------------------------------------------------------------------
--- PGR_alphAShape
---------------------------------------------------------------------------------
--- testing with areas
---SELECT * FROM pgr_alphAShape('SELECT id, x, y FROM vertex_table');
---SELECT * FROM pgr_alphAShape('SELECT id::integer, st_x(the_geom)::float as x, st_y(the_geom)::float as y FROM edge_table_vertices_pgr');
-
-SELECT round(st_area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) as st_area
-from (select st_makeline(points order by id) as openline from
-(SELECT st_makepoint(x,y) as points ,row_number() over() AS id
-
-FROM pgr_alphAShape('SELECT id, x, y FROM vertex_table')
-
-) as a) as foo;
-
-\echo '-----------------------------'
-
-SELECT round(st_area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) as st_area
-from (select st_makeline(points order by id) as openline from
-(SELECT st_makepoint(x,y) as points ,row_number() over() AS id
-
-FROM pgr_alphAShape('SELECT id::integer, st_x(the_geom)::float as x, st_y(the_geom)::float as y FROM edge_table_vertices_pgr')
-
-) as a) as foo;
diff --git a/doc/test/alphashape-any.test.sql b/doc/test/alphashape-any.test.sql
new file mode 100644
index 0000000..bd638a7
--- /dev/null
+++ b/doc/test/alphashape-any.test.sql
@@ -0,0 +1,24 @@
+--------------------------------------------------------------------------------
+-- PGR_alphaShape
+--------------------------------------------------------------------------------
+-- testing with areas
+--SELECT * FROM pgr_alphaShape('SELECT id, x, y FROM vertex_table');
+--SELECT * FROM pgr_alphaShape('SELECT id::integer, ST_X(the_geom)::float AS x, ST_Y(the_geom)::float AS y FROM edge_table_vertices_pgr');
+
+SELECT round(ST_Area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) AS st_area
+FROM (SELECT ST_MakeLine(points ORDER BY id) AS openline FROM
+(SELECT ST_MakePoint(x, y) AS points, row_number() over() AS id
+
+FROM pgr_alphaShape('SELECT id, x, y FROM vertex_table')
+
+) AS a) AS foo;
+
+\echo '-----------------------------'
+
+SELECT round(ST_Area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) AS st_area
+FROM (SELECT ST_MakeLine(points ORDER BY id) AS openline FROM
+(SELECT ST_MakePoint(x, y) AS points, row_number() over() AS id
+
+FROM pgr_alphaShape('SELECT id::integer, ST_X(the_geom)::float AS x, ST_Y(the_geom)::float AS y FROM edge_table_vertices_pgr')
+
+) AS a) AS foo;
diff --git a/doc/test/analyzeGraph-any.rest b/doc/test/analyzeGraph-any.result
similarity index 91%
rename from doc/test/analyzeGraph-any.rest
rename to doc/test/analyzeGraph-any.result
index a5573e8..9e7807f 100644
--- a/doc/test/analyzeGraph-any.rest
+++ b/doc/test/analyzeGraph-any.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait.....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -9,7 +9,7 @@
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -24,7 +24,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -39,12 +39,13 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'id','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait...
- NOTICE: ERROR: Can not determine the srid of the geometry "id" in table public.edge_table
+ NOTICE: Performing checks, please wait...
+ NOTICE: Got function st_srid(integer) does not exist
+ NOTICE: ERROR: something went wrong when checking for SRID of id in table public.edge_table
FAIL
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -59,7 +60,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -74,7 +75,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -89,7 +90,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','id < 10')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -104,7 +105,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','the_geom && (SELECT st_buffer(the_geom,0.05) FROM edge_table WHERE id=5)')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -119,7 +120,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','the_geom && (SELECT st_buffer(other_geom,1) FROM otherTable WHERE gid=100)')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -134,7 +135,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -143,7 +144,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -158,12 +159,13 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.0001,'gid','mygeom','src','tgt','true')
- NOTICE: Performing checks, pelase wait...
- NOTICE: ERROR: Can not determine the srid of the geometry "gid" in table public.mytable
+ NOTICE: Performing checks, please wait...
+ NOTICE: Got function st_srid(integer) does not exist
+ NOTICE: ERROR: something went wrong when checking for SRID of gid in table public.mytable
FAIL
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -178,7 +180,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -193,7 +195,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','gid < 10')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -208,7 +210,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','gid < 10')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -223,7 +225,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(mygeom,1) FROM mytable WHERE gid=5)')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -238,7 +240,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(mygeom,1) FROM mytable WHERE gid=5)')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -253,7 +255,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(other_geom,1) FROM otherTable WHERE place='myhouse')')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -268,7 +270,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(other_geom,1) FROM otherTable WHERE place='myhouse')')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -283,7 +285,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -292,7 +294,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -307,7 +309,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','id < 10')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -322,7 +324,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','id >= 10')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -337,7 +339,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','id < 17')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -352,7 +354,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','id <17')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 16 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -361,7 +363,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
diff --git a/doc/test/analyzeGraph-any.test b/doc/test/analyzeGraph-any.test.sql
similarity index 100%
rename from doc/test/analyzeGraph-any.test
rename to doc/test/analyzeGraph-any.test.sql
diff --git a/doc/test/analyzeOneway-any.rest b/doc/test/analyzeOneway-any.result
similarity index 100%
rename from doc/test/analyzeOneway-any.rest
rename to doc/test/analyzeOneway-any.result
diff --git a/doc/test/analyzeOneway-any.test b/doc/test/analyzeOneway-any.test.sql
similarity index 100%
rename from doc/test/analyzeOneway-any.test
rename to doc/test/analyzeOneway-any.test.sql
diff --git a/doc/test/apspJohnson-any.rest b/doc/test/apspJohnson-any.result
similarity index 100%
rename from doc/test/apspJohnson-any.rest
rename to doc/test/apspJohnson-any.result
diff --git a/doc/test/apspJohnson-any.test b/doc/test/apspJohnson-any.test.sql
similarity index 100%
rename from doc/test/apspJohnson-any.test
rename to doc/test/apspJohnson-any.test.sql
diff --git a/doc/test/apspWarshall-any.rest b/doc/test/apspWarshall-any.result
similarity index 100%
rename from doc/test/apspWarshall-any.rest
rename to doc/test/apspWarshall-any.result
diff --git a/doc/test/apspWarshall-any.test b/doc/test/apspWarshall-any.test.sql
similarity index 100%
rename from doc/test/apspWarshall-any.test
rename to doc/test/apspWarshall-any.test.sql
diff --git a/doc/test/astar-any.rest b/doc/test/astar-any.rest
deleted file mode 100644
index 1bdf8fb..0000000
--- a/doc/test/astar-any.rest
+++ /dev/null
@@ -1,10 +0,0 @@
-0|4|16|1
-1|9|9|1
-2|6|8|1
-3|5|10|1
-4|10|-1|0
-0|4|3|1
-1|3|2|1
-2|2|4|1
-3|5|10|1
-4|10|-1|0
diff --git a/doc/test/astar-any.result b/doc/test/astar-any.result
new file mode 100644
index 0000000..0add5ab
--- /dev/null
+++ b/doc/test/astar-any.result
@@ -0,0 +1,10 @@
+0|4|16|1
+1|9|9|1
+2|6|11|1
+3|11|12|1
+4|10|-1|0
+0 |4|3|1
+1 |3|5|1
+2 |6|8|1
+3 |5|10|1
+4 |10|-1|0
diff --git a/doc/test/astar-any.test b/doc/test/astar-any.test.sql
similarity index 100%
rename from doc/test/astar-any.test
rename to doc/test/astar-any.test.sql
diff --git a/doc/test/bdDijkstra-any.rest b/doc/test/bdDijkstra-any.result
similarity index 100%
rename from doc/test/bdDijkstra-any.rest
rename to doc/test/bdDijkstra-any.result
diff --git a/doc/test/bdDijkstra-any.test b/doc/test/bdDijkstra-any.test.sql
similarity index 100%
rename from doc/test/bdDijkstra-any.test
rename to doc/test/bdDijkstra-any.test.sql
diff --git a/doc/test/bdstar-any.rest b/doc/test/bdstar-any.result
similarity index 100%
rename from doc/test/bdstar-any.rest
rename to doc/test/bdstar-any.result
diff --git a/doc/test/bdstar-any.test b/doc/test/bdstar-any.test.sql
similarity index 100%
rename from doc/test/bdstar-any.test
rename to doc/test/bdstar-any.test.sql
diff --git a/doc/test/createTopology-any.rest b/doc/test/createTopology-any.result
similarity index 85%
rename from doc/test/createTopology-any.rest
rename to doc/test/createTopology-any.result
index 1978318..8d60f7d 100644
--- a/doc/test/createTopology-any.rest
+++ b/doc/test/createTopology-any.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -9,7 +9,7 @@
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -17,13 +17,8 @@ OK
NOTICE: ----------------------------------------------
OK
NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edge_table',0.001,'id','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Can not determine the srid of the geometry "id" in table public.edge_table
-FAIL
- NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -32,7 +27,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -41,7 +36,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -50,7 +45,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','id < 10')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 9 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -59,7 +54,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','the_geom && (SELECT st_buffer(the_geom,0.05) FROM edge_table WHERE id=5)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 6 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -69,7 +64,7 @@ OK
NOTICE: table "othertable" does not exist, skipping
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','the_geom && (SELECT st_buffer(other_geom,1) FROM otherTable WHERE gid=100)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 12 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -79,7 +74,7 @@ OK
NOTICE: table "mytable" does not exist, skipping
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -87,13 +82,8 @@ OK
NOTICE: ----------------------------------------------
OK
NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('mytable',0.001,'gid','mygeom','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Can not determine the srid of the geometry "gid" in table public.mytable
-FAIL
- NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -102,7 +92,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -111,7 +101,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','gid < 10')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 9 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -120,7 +110,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','gid < 10')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 9 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -129,7 +119,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(mygeom,1) FROM mytable WHERE gid=5)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 16 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -138,7 +128,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(mygeom,1) FROM mytable WHERE gid=5)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 16 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -147,7 +137,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(other_geom,1) FROM otherTable WHERE gid=100)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 12 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -156,7 +146,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt','mygeom && (SELECT st_buffer(other_geom,1) FROM otherTable WHERE gid=100)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 12 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -165,7 +155,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','id<10')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 9 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -174,7 +164,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
diff --git a/doc/test/createTopology-any.test b/doc/test/createTopology-any.test.sql
similarity index 94%
rename from doc/test/createTopology-any.test
rename to doc/test/createTopology-any.test.sql
index 2f89651..83b84ce 100644
--- a/doc/test/createTopology-any.test
+++ b/doc/test/createTopology-any.test.sql
@@ -6,11 +6,12 @@
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
+\set verbosity terse
SELECT pgr_createTopology('edge_table',0.001);
SELECT pgr_createTopology('edge_table',0.001,'the_geom','id','source','target');
- SELECT pgr_createTopology('edge_table',0.001,'id','the_geom','source','target');
+ -- SELECT pgr_createTopology('edge_table',0.001,'id','the_geom','source','target');
SELECT pgr_createTopology('edge_table',0.001,the_geom:='the_geom',id:='id',source:='source',target:='target');
SELECT pgr_createTopology('edge_table',0.001,source:='source',id:='id',target:='target',the_geom:='the_geom');
SELECT pgr_createTopology('edge_table',0.001,source:='source');
@@ -22,7 +23,7 @@
DROP TABLE IF EXISTS mytable;
CREATE TABLE mytable AS (SELECT id AS gid, the_geom AS mygeom,source AS src ,target AS tgt FROM edge_table) ;
SELECT pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt');
- SELECT pgr_createTopology('mytable',0.001,'gid','mygeom','src','tgt');
+ -- SELECT pgr_createTopology('mytable',0.001,'gid','mygeom','src','tgt');
SELECT pgr_createTopology('mytable',0.001,the_geom:='mygeom',id:='gid',source:='src',target:='tgt');
SELECT pgr_createTopology('mytable',0.001,source:='src',id:='gid',target:='tgt',the_geom:='mygeom');
SELECT pgr_createTopology('mytable',0.001,'mygeom','gid','src','tgt',rows_where:='gid < 10');
diff --git a/doc/test/createVertTab-any.rest b/doc/test/createVertTab-any.result
similarity index 88%
rename from doc/test/createVertTab-any.rest
rename to doc/test/createVertTab-any.result
index 4aaff8d..5382bfa 100644
--- a/doc/test/createVertTab-any.rest
+++ b/doc/test/createVertTab-any.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -11,7 +11,7 @@
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -21,13 +21,8 @@ OK
NOTICE: ----------------------------------------------
OK
NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edge_table','source','the_geom','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Can not determine the srid of the geometry "source" in table public.edge_table
-FAIL
- NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -38,7 +33,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -49,7 +44,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -60,7 +55,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','id < 10')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 10 EDGES
@@ -71,7 +66,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','the_geom && (select st_buffer(the_geom,0.5) FROM edge_table WHERE id=5)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 9 EDGES
@@ -82,7 +77,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','the_geom && (select st_buffer(other_geom,0.5) FROM otherTable WHERE gid=100)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 10 VERTICES
NOTICE: FOR 12 EDGES
@@ -93,7 +88,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -103,13 +98,8 @@ OK
NOTICE: ----------------------------------------------
OK
NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('mytable','src','mygeom','tgt','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Can not determine the srid of the geometry "src" in table public.mytable
-FAIL
- NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -120,7 +110,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
@@ -131,7 +121,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','gid < 10')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 10 EDGES
@@ -142,7 +132,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','gid < 10')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 10 EDGES
@@ -153,7 +143,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','mygeom && (SELECT st_buffer(mygeom,0.5) FROM mytable WHERE gid=5)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 9 EDGES
@@ -164,7 +154,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','mygeom && (SELECT st_buffer(mygeom,0.5) FROM mytable WHERE gid=5)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 9 EDGES
@@ -175,7 +165,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','mygeom && (SELECT st_buffer(other_geom,0.5) FROM otherTable WHERE gid=100)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 10 VERTICES
NOTICE: FOR 12 EDGES
@@ -186,7 +176,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('mytable','mygeom','src','tgt','mygeom && (SELECT st_buffer(other_geom,0.5) FROM otherTable WHERE gid=100)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.mytable_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 10 VERTICES
NOTICE: FOR 12 EDGES
@@ -197,7 +187,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edge_table','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edge_table_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 17 VERTICES
NOTICE: FOR 18 EDGES
diff --git a/doc/test/createVertTab-any.test b/doc/test/createVertTab-any.test.sql
similarity index 95%
rename from doc/test/createVertTab-any.test
rename to doc/test/createVertTab-any.test.sql
index f7676f4..fd245ba 100644
--- a/doc/test/createVertTab-any.test
+++ b/doc/test/createVertTab-any.test.sql
@@ -7,7 +7,7 @@
-- SELECT pgr_createTopology('edge_table',0.001);
SELECT pgr_createVerticesTable('edge_table');
SELECT pgr_createVerticesTable('edge_table','the_geom','source','target');
- SELECT pgr_createVerticesTable('edge_table','source','the_geom','target');
+ -- SELECT pgr_createVerticesTable('edge_table','source','the_geom','target');
SELECT pgr_createVerticesTable('edge_table',the_geom:='the_geom',source:='source',target:='target');
SELECT pgr_createVerticesTable('edge_table',source:='source',target:='target',the_geom:='the_geom');
SELECT pgr_createVerticesTable('edge_table',source:='source');
@@ -19,7 +19,7 @@
DROP TABLE IF EXISTS mytable;
CREATE TABLE mytable AS (SELECT id AS gid, the_geom AS mygeom,source AS src ,target AS tgt FROM edge_table) ;
SELECT pgr_createVerticesTable('mytable','mygeom','src','tgt');
- SELECT pgr_createVerticesTable('mytable','src','mygeom','tgt');
+ -- SELECT pgr_createVerticesTable('mytable','src','mygeom','tgt');
SELECT pgr_createVerticesTable('mytable',the_geom:='mygeom',source:='src',target:='tgt');
SELECT pgr_createVerticesTable('mytable',source:='src',target:='tgt',the_geom:='mygeom');
SELECT pgr_createVerticesTable('mytable','mygeom','src','tgt',rows_where:='gid < 10');
diff --git a/doc/test/dijkstra-any.rest b/doc/test/dijkstra-any.rest
deleted file mode 100644
index 4842276..0000000
--- a/doc/test/dijkstra-any.rest
+++ /dev/null
@@ -1,12 +0,0 @@
-0|7|6|1
-1|8|7|1
-2|5|8|1
-3|6|9|1
-4|9|15|1
-5|12|-1|0
-0|7|6|1
-1|8|7|1
-2|5|8|1
-3|6|9|1
-4|9|15|1
-5|12|-1|0
diff --git a/doc/test/dijkstra-v2.result b/doc/test/dijkstra-v2.result
new file mode 100644
index 0000000..9518c72
--- /dev/null
+++ b/doc/test/dijkstra-v2.result
@@ -0,0 +1,12 @@
+0|2|4|1
+1|5|8|1
+2|6|9|1
+3|9|16|1
+4|4|3|1
+5|3|-1|0
+0|2|4|1
+1|5|8|1
+2|6|5|1
+3|3|-1|0
+0|2|2|1
+1|3|-1|0
diff --git a/doc/test/dijkstra-any.test b/doc/test/dijkstra-v2.test.sql
similarity index 51%
copy from doc/test/dijkstra-any.test
copy to doc/test/dijkstra-v2.test.sql
index 1593f19..1f7c86e 100644
--- a/doc/test/dijkstra-any.test
+++ b/doc/test/dijkstra-v2.test.sql
@@ -1,15 +1,30 @@
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
--- PGR_dijkstra
+-- PGR_dijkstra V.2.0
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
SELECT seq, id1 AS node, id2 AS edge, cost
FROM pgr_dijkstra(
- 'SELECT id, source, target, cost FROM edge_table order by id',
- 7, 12, false, false);
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2,3, true, false
+ );
SELECT seq, id1 AS node, id2 AS edge, cost
FROM pgr_dijkstra(
'SELECT id, source, target, cost, reverse_cost FROM edge_table',
- 7, 12, true, true);
+ 2,3, true, true
+ );
+
+SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, false, false
+ );
+
+SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3, false, true
+ );
+
diff --git a/doc/test/drivingDistance-any.rest b/doc/test/drivingDistance-any.rest
deleted file mode 100644
index ffa05f1..0000000
--- a/doc/test/drivingDistance-any.rest
+++ /dev/null
@@ -1,9 +0,0 @@
-0|3|1
-1|5|1
-2|6|0
-3|9|1
-4|11|1
-0|5|1
-1|6|0
-2|9|1
-3|11|1
diff --git a/doc/test/issue-353.test.sql b/doc/test/issue-353.test.sql
new file mode 100644
index 0000000..f7da593
--- /dev/null
+++ b/doc/test/issue-353.test.sql
@@ -0,0 +1,8 @@
+-- test for issue 353
+
+select * from pgr_dijkstra( 'select id, source, target, cost from edge_table',
+ array[2,7], array[5,6]);
+select * from pgr_dijkstra( 'select id, source, target, cost from edge_table',
+ array[2,7], array[17,18]);
+select * from pgr_dijkstra( 'select id, source, target, cost from edge_table',
+array[2,7], array[5,6,17,18]);
diff --git a/doc/test/kdijkstra-any.rest b/doc/test/kdijkstra-any.result
similarity index 100%
rename from doc/test/kdijkstra-any.rest
rename to doc/test/kdijkstra-any.result
diff --git a/doc/test/kdijkstra-any.test b/doc/test/kdijkstra-any.test.sql
similarity index 100%
rename from doc/test/kdijkstra-any.test
rename to doc/test/kdijkstra-any.test.sql
diff --git a/doc/test/ksp-any.rest b/doc/test/ksp-any.result
similarity index 100%
copy from doc/test/ksp-any.rest
copy to doc/test/ksp-any.result
diff --git a/doc/test/ksp-any.test b/doc/test/ksp-any.test.sql
similarity index 100%
copy from doc/test/ksp-any.test
copy to doc/test/ksp-any.test.sql
diff --git a/doc/test/nodeNetwork-any.rest b/doc/test/nodeNetwork-any.result
similarity index 79%
rename from doc/test/nodeNetwork-any.rest
rename to doc/test/nodeNetwork-any.result
index c396b16..c09f3b8 100644
--- a/doc/test/nodeNetwork-any.rest
+++ b/doc/test/nodeNetwork-any.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -9,7 +9,7 @@
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -24,14 +24,14 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_nodeNetwork('edge_table',0.001,'the_geom','id','noded')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Processing, pelase wait .....
- NOTICE: Splitted Edges: 3
- NOTICE: Untouched Edges: 15
+ NOTICE: Performing checks, please wait .....
+ NOTICE: Processing, please wait .....
+ NOTICE: Splitted Edges: 2
+ NOTICE: Untouched Edges: 16
NOTICE: Total original Edges: 18
- NOTICE: Edges generated: 6
- NOTICE: Untouched Edges: 15
- NOTICE: Total New segments: 21
+ NOTICE: Edges generated: 4
+ NOTICE: Untouched Edges: 16
+ NOTICE: Total New segments: 20
NOTICE: New Table: public.edge_table_noded
NOTICE: ----------------------------------
OK
@@ -50,7 +50,6 @@ OK
13|1
13|2
14|1
-14|2
15|1
16|1
17|1
@@ -58,56 +57,56 @@ OK
18|2
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table_noded',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 21 edges
+ NOTICE: -------------> TOPOLOGY CREATED FOR 20 edges
NOTICE: Rows with NULL geometry or NULL id: 0
NOTICE: Vertices table for table public.edge_table_noded is: public.edge_table_noded_vertices_pgr
NOTICE: ----------------------------------------------
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table_noded',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
NOTICE: Analyzing for ring geometries. Please wait...
NOTICE: Analyzing for intersections. Please wait...
NOTICE: ANALYSIS RESULTS FOR SELECTED EDGES:
- NOTICE: Isolated segments: 0
- NOTICE: Dead ends: 6
- NOTICE: Potential gaps found near dead ends: 0
+ NOTICE: Isolated segments: 1
+ NOTICE: Dead ends: 7
+ NOTICE: Potential gaps found near dead ends: 1
NOTICE: Intersections detected: 0
NOTICE: Ring geometries: 0
OK
NOTICE: column "old_id" of relation "edge_table" does not exist, skipping
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 24 edges
+ NOTICE: -------------> TOPOLOGY CREATED FOR 22 edges
NOTICE: Rows with NULL geometry or NULL id: 0
NOTICE: Vertices table for table public.edge_table is: public.edge_table_vertices_pgr
NOTICE: ----------------------------------------------
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','id not in (select old_id from edge_table where old_id is not null)')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
NOTICE: Analyzing for ring geometries. Please wait...
NOTICE: Analyzing for intersections. Please wait...
NOTICE: ANALYSIS RESULTS FOR SELECTED EDGES:
- NOTICE: Isolated segments: 0
- NOTICE: Dead ends: 6
- NOTICE: Potential gaps found near dead ends: 0
+ NOTICE: Isolated segments: 1
+ NOTICE: Dead ends: 7
+ NOTICE: Potential gaps found near dead ends: 1
NOTICE: Intersections detected: 0
NOTICE: Ring geometries: 0
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','old_id is null')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -122,16 +121,16 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
NOTICE: Analyzing for ring geometries. Please wait...
NOTICE: Analyzing for intersections. Please wait...
NOTICE: ANALYSIS RESULTS FOR SELECTED EDGES:
- NOTICE: Isolated segments: 0
- NOTICE: Dead ends: 3
- NOTICE: Potential gaps found near dead ends: 0
+ NOTICE: Isolated segments: 1
+ NOTICE: Dead ends: 5
+ NOTICE: Potential gaps found near dead ends: 1
NOTICE: Intersections detected: 5
NOTICE: Ring geometries: 0
OK
diff --git a/doc/test/nodeNetwork-any.test b/doc/test/nodeNetwork-any.test.sql
similarity index 100%
rename from doc/test/nodeNetwork-any.test
rename to doc/test/nodeNetwork-any.test.sql
diff --git a/doc/test/pointsAsPolygon-any.rest b/doc/test/pointsAsPolygon-any.result
similarity index 100%
rename from doc/test/pointsAsPolygon-any.rest
rename to doc/test/pointsAsPolygon-any.result
diff --git a/doc/test/pointsAsPolygon-any.test b/doc/test/pointsAsPolygon-any.test.sql
similarity index 100%
rename from doc/test/pointsAsPolygon-any.test
rename to doc/test/pointsAsPolygon-any.test.sql
diff --git a/doc/test/sampledata.data b/doc/test/sampledata.data
index a5e899c..37aa2d2 100644
--- a/doc/test/sampledata.data
+++ b/doc/test/sampledata.data
@@ -5,6 +5,7 @@
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
+drop table if exists edge_table;
CREATE TABLE edge_table (
id serial,
dir character varying,
@@ -46,6 +47,7 @@ UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
select pgr_createTopology('edge_table',0.001);
+drop table if exists vertex_table;
CREATE TABLE vertex_table (
id serial,
x double precision,
diff --git a/doc/test/sampledata.rest b/doc/test/sampledata.result
similarity index 60%
rename from doc/test/sampledata.rest
rename to doc/test/sampledata.result
index 03954bf..08945ce 100644
--- a/doc/test/sampledata.rest
+++ b/doc/test/sampledata.result
@@ -1,11 +1,9 @@
- NOTICE: CREATE TABLE will create implicit sequence "edge_table_id_seq" for serial column "edge_table.id"
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edge_table',0.001,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 18 edges
NOTICE: Rows with NULL geometry or NULL id: 0
NOTICE: Vertices table for table public.edge_table is: public.edge_table_vertices_pgr
NOTICE: ----------------------------------------------
OK
- NOTICE: CREATE TABLE will create implicit sequence "vertex_table_id_seq" for serial column "vertex_table.id"
diff --git a/doc/test/sampledata.test b/doc/test/sampledata.test.sql
similarity index 100%
copy from doc/test/sampledata.test
copy to doc/test/sampledata.test.sql
diff --git a/doc/test/test.conf b/doc/test/test.conf
index 52cf6e9..774feb2 100644
--- a/doc/test/test.conf
+++ b/doc/test/test.conf
@@ -10,12 +10,10 @@
sampledata
alphashape-any
apspJohnson-any
-apspWarshall-any
astar-any
bdstar-any
bdDijkstra-any
-dijkstra-any
-drivingDistance-any
+dijkstra-v2
pointsAsPolygon-any
kdijkstra-any
tsp-any
@@ -28,6 +26,9 @@ analyzeOneway-any
nodeNetwork-any
+)],
+ 'postgis2-2-notworking' => [qw(
+apspWarsh-all-any
)]
},
# 'vpg-vpgis' => {}, # for version specific tests
diff --git a/doc/test/trsp-any.rest b/doc/test/trsp-any.rest
deleted file mode 100644
index c391f44..0000000
--- a/doc/test/trsp-any.rest
+++ /dev/null
@@ -1,13 +0,0 @@
-0|7|6|1
-1|8|7|1
-2|5|8|1
-3|6|11|1
-4|11|13|1
-5|12|-1|0
- NOTICE: CREATE TABLE will create implicit sequence "restrictions_rid_seq" for serial column "restrictions.rid"
-0|7|6|1
-1|8|7|1
-2|5|8|1
-3|6|11|1
-4|11|13|1
-5|12|-1|0
diff --git a/doc/test/trsp-any.result b/doc/test/trsp-any.result
new file mode 100644
index 0000000..6695025
--- /dev/null
+++ b/doc/test/trsp-any.result
@@ -0,0 +1,37 @@
+0|7|6|1
+1|8|7|1
+2|5|8|1
+3|6|11|1
+4|11|13|1
+5|12|-1|0
+0|7|6|1
+1|8|7|1
+2|5|8|1
+3|6|11|1
+4|11|13|1
+5|12|-1|0
+1|1|1|1|1
+2|1|2|4|1
+3|1|5|8|1
+4|1|6|9|1
+5|1|9|16|1
+6|1|4|3|1
+7|1|3|5|1
+8|1|6|8|1
+9|1|5|7|1
+10|2|8|7|1
+11|2|5|10|1
+12|2|10|14|1
+13|3|13|14|1
+14|3|10|10|1
+15|3|5|-1|0
+1|1|-1|1|0.5
+2|1|2|4|1
+3|1|5|8|1
+4|1|6|11|1
+5|2|11|13|1
+6|2|12|15|1
+7|2|9|9|1
+8|2|6|8|1
+9|2|5|7|1
+10|2|8|6|0.5
diff --git a/doc/test/trsp-any.test b/doc/test/trsp-any.test.sql
similarity index 59%
rename from doc/test/trsp-any.test
rename to doc/test/trsp-any.test.sql
index 4504089..2b64e49 100644
--- a/doc/test/trsp-any.test
+++ b/doc/test/trsp-any.test.sql
@@ -3,7 +3,7 @@
-- PGR_pgr_trsp
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
-
+set log_min_messages='NOTICE'; /** hack to force EDB to log so uses hack elog for test **/
SELECT seq, id1 AS node, id2 AS edge, cost
FROM pgr_trsp(
@@ -31,3 +31,26 @@ INSERT INTO restrictions VALUES (3,100,9,16,null);
FROM_edge || coalesce('','' || via, '''') AS via_path
FROM restrictions'
);
+
+ SELECT * FROM pgr_trspViaVertices(
+ 'SELECT id, source::INTEGER, target::INTEGER, cost,
+ reverse_cost FROM edge_table',
+ ARRAY[1,8,13,5]::INTEGER[],
+ true,
+ true,
+
+ 'SELECT to_cost, to_edge AS target_id, FROM_edge ||
+ coalesce('',''||via,'''') AS via_path FROM restrictions');
+
+
+ SELECT * FROM pgr_trspViaEdges(
+ 'SELECT id, source::INTEGER, target::INTEGER,cost,
+ reverse_cost FROM edge_table',
+ ARRAY[1,11,6]::INTEGER[],
+ ARRAY[0.5, 0.5, 0.5]::FLOAT8[],
+ true,
+ true,
+
+ 'SELECT to_cost, to_edge AS target_id, FROM_edge ||
+ coalesce('',''||via,'''') AS via_path FROM restrictions');
+
diff --git a/doc/test/tsp-any.rest b/doc/test/tsp-any.result
similarity index 100%
rename from doc/test/tsp-any.rest
rename to doc/test/tsp-any.result
diff --git a/doc/test/tsp-any.test b/doc/test/tsp-any.test.sql
similarity index 100%
rename from doc/test/tsp-any.test
rename to doc/test/tsp-any.test.sql
diff --git a/doc/test/utilities-any.rest b/doc/test/utilities-any.rest
deleted file mode 100644
index f2e0a46..0000000
--- a/doc/test/utilities-any.rest
+++ /dev/null
@@ -1 +0,0 @@
-2.0.0|v2.0.0
diff --git a/doc/test/utilities-any.result b/doc/test/utilities-any.result
new file mode 100644
index 0000000..3a7fa76
--- /dev/null
+++ b/doc/test/utilities-any.result
@@ -0,0 +1 @@
+2.1.0|pgrouting-2.1.0
diff --git a/doc/test/utilities-any.test b/doc/test/utilities-any.test.sql
similarity index 100%
rename from doc/test/utilities-any.test
rename to doc/test/utilities-any.test.sql
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a26441a..5a45bb6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,44 +1,56 @@
SET(PACKAGE_SQL_FILES "")
SET(L_PACKAGE_SQL_FILES "")
-ADD_SUBDIRECTORY(common)
+
+
+ADD_SUBDIRECTORY(apsp_johnson)
+LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
+
+ADD_SUBDIRECTORY(apsp_warshall)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
ADD_SUBDIRECTORY(astar)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
+ADD_SUBDIRECTORY(bd_dijkstra)
+LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
+
ADD_SUBDIRECTORY(bd_astar)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
+ADD_SUBDIRECTORY(common)
+LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
+
ADD_SUBDIRECTORY(dijkstra)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
ADD_SUBDIRECTORY(kdijkstra)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-ADD_SUBDIRECTORY(bd_dijkstra)
+ADD_SUBDIRECTORY(ksp)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-ADD_SUBDIRECTORY(apsp_johnson)
+ADD_SUBDIRECTORY(trsp)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-ADD_SUBDIRECTORY(apsp_warshall)
+ADD_SUBDIRECTORY(tsp)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-#ADD_SUBDIRECTORY(shooting_star)
-#LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
+ADD_SUBDIRECTORY(driving_distance)
+LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-ADD_SUBDIRECTORY(trsp)
+ADD_SUBDIRECTORY(label_graph)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-ADD_SUBDIRECTORY(tsp)
+ADD_SUBDIRECTORY(vrp_basic)
+LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
+
+ADD_SUBDIRECTORY(vrppdtw)
LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-if("${POSTGRESQL_VERSION}" VERSION_GREATER "8.4.0")
- ADD_SUBDIRECTORY(ksp)
- LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
-endif("${POSTGRESQL_VERSION}" VERSION_GREATER "8.4.0")
+#ADD_SUBDIRECTORY(shooting_star)
+#LIST(APPEND L_PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}")
# Make sure this is after all the ADD_SUBDIRECTORY
SET(PACKAGE_SQL_FILES "${L_PACKAGE_SQL_FILES}" PARENT_SCOPE)
diff --git a/src/apsp_johnson/sql/apsp_johnson.sql b/src/apsp_johnson/sql/apsp_johnson.sql
index 6cb8e01..1eabb0e 100644
--- a/src/apsp_johnson/sql/apsp_johnson.sql
+++ b/src/apsp_johnson/sql/apsp_johnson.sql
@@ -1,5 +1,5 @@
CREATE OR REPLACE FUNCTION pgr_apspJohnson(sql text)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting', 'apsp_johnson'
+ AS '$libdir/librouting-2.1', 'apsp_johnson'
LANGUAGE C IMMUTABLE STRICT;
diff --git a/src/apsp_johnson/src/CMakeLists.txt b/src/apsp_johnson/src/CMakeLists.txt
index aaab201..c777b22 100644
--- a/src/apsp_johnson/src/CMakeLists.txt
+++ b/src/apsp_johnson/src/CMakeLists.txt
@@ -1,6 +1,9 @@
# FIXME: The following patch is required by apsp_johnson_boost_wrapper.cpp.
# With -fdelete-null-pointer-checks optimization, the assignments
# to Edge bundled properties doesn't occur.
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-delete-null-pointer-checks")
+
+if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-delete-null-pointer-checks")
+endif()
ADD_LIBRARY(apsp_johnson OBJECT apsp_johnson.c apsp_johnson_boost_wrapper.cpp)
diff --git a/src/apsp_johnson/src/apsp_johnson.c b/src/apsp_johnson/src/apsp_johnson.c
index 123d098..0b4e5eb 100644
--- a/src/apsp_johnson/src/apsp_johnson.c
+++ b/src/apsp_johnson/src/apsp_johnson.c
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -265,7 +265,9 @@ Datum apsp_johnson(PG_FUNCTION_ARGS) {
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int output_count = 0;
+#ifdef DEBUG
int ret;
+#endif
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
@@ -273,7 +275,10 @@ Datum apsp_johnson(PG_FUNCTION_ARGS) {
/* switch to memory context appropriate for multiple function calls */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- ret = compute_apsp_johnson(text2char(PG_GETARG_TEXT_P(0)), &output_edges,
+#ifdef DEBUG
+ ret =
+#endif
+ compute_apsp_johnson(text2char(PG_GETARG_TEXT_P(0)), &output_edges,
&output_count);
#ifdef DEBUG
diff --git a/src/apsp_johnson/src/apsp_johnson.h b/src/apsp_johnson/src/apsp_johnson.h
index 0ea8080..c5fb380 100644
--- a/src/apsp_johnson/src/apsp_johnson.h
+++ b/src/apsp_johnson/src/apsp_johnson.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/apsp_johnson/src/apsp_johnson_boost_wrapper.cpp b/src/apsp_johnson/src/apsp_johnson_boost_wrapper.cpp
index 323d8dd..2979289 100644
--- a/src/apsp_johnson/src/apsp_johnson_boost_wrapper.cpp
+++ b/src/apsp_johnson/src/apsp_johnson_boost_wrapper.cpp
@@ -15,12 +15,17 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <boost/config.hpp>
#include <boost/version.hpp>
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#if BOOST_VERSION > 103900
#include <boost/property_map/property_map.hpp>
@@ -72,13 +77,13 @@ try {
// FIXME: use a template for the directedS parameters
typedef adjacency_list<vecS, vecS, directedS, no_property, Edge> graph_t;
- typedef graph_traits<graph_t>::vertex_descriptor vertex_descriptor;
+ // typedef graph_traits<graph_t>::vertex_descriptor vertex_descriptor;
typedef graph_traits<graph_t>::edge_descriptor edge_descriptor;
- typedef graph_traits<graph_t>::edge_iterator edge_iterator;
+ // typedef graph_traits<graph_t>::edge_iterator edge_iterator;
graph_t graph;
- for (std::size_t j = 0; j < count; ++j) {
+ for (int j = 0; j < count; ++j) {
graph_add_edge<graph_t, edge_descriptor>(graph, edges[j].source,
edges[j].target, edges[j].cost);
diff --git a/src/apsp_johnson/test/apsp_johnson-any-00.rest b/src/apsp_johnson/test/apsp_johnson-any-00.result
similarity index 100%
rename from src/apsp_johnson/test/apsp_johnson-any-00.rest
rename to src/apsp_johnson/test/apsp_johnson-any-00.result
diff --git a/src/apsp_johnson/test/apsp_johnson-any-00.test b/src/apsp_johnson/test/apsp_johnson-any-00.test.sql
similarity index 100%
rename from src/apsp_johnson/test/apsp_johnson-any-00.test
rename to src/apsp_johnson/test/apsp_johnson-any-00.test.sql
diff --git a/src/apsp_warshall/doc/index.rst b/src/apsp_warshall/doc/index.rst
index 25835fe..92a1f9b 100644
--- a/src/apsp_warshall/doc/index.rst
+++ b/src/apsp_warshall/doc/index.rst
@@ -39,7 +39,7 @@ Description
.. code-block:: sql
- SELECT source, target, cost FROM edge_table;
+ SELECT id, source, target, cost FROM edge_table;
:id: ``int4`` identifier of the edge
:source: ``int4`` identifier of the source vertex for this edge
diff --git a/src/apsp_warshall/sql/apsp_warshall.sql b/src/apsp_warshall/sql/apsp_warshall.sql
index a45a259..bbe3886 100644
--- a/src/apsp_warshall/sql/apsp_warshall.sql
+++ b/src/apsp_warshall/sql/apsp_warshall.sql
@@ -2,5 +2,5 @@
CREATE OR REPLACE FUNCTION pgr_apspWarshall(sql text, directed boolean, has_reverse_cost boolean)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting', 'apsp_warshall'
+ AS '$libdir/librouting-2.1', 'apsp_warshall'
LANGUAGE 'c' IMMUTABLE STRICT;
diff --git a/src/apsp_warshall/src/apsp.c b/src/apsp_warshall/src/apsp.c
index 5d3cb55..f57d5c8 100644
--- a/src/apsp_warshall/src/apsp.c
+++ b/src/apsp_warshall/src/apsp.c
@@ -177,7 +177,7 @@ static int compute_apsp_warshall(char* sql, bool directed,
bool has_reverse_cost,
apsp_element_t **pair, int *pair_count)
{
- int i;
+ // int i;
int SPIcode;
void *SPIplan;
Portal SPIportal;
@@ -187,15 +187,15 @@ static int compute_apsp_warshall(char* sql, bool directed,
int total_tuples = 0;
edge_columns_t edge_columns = {.id= -1, .source= -1, .target= -1,
.cost= -1, .reverse_cost= -1};
- int v_max_id=0;
- int v_min_id=INT_MAX;
+ // int v_max_id=0;
+ // int v_min_id=INT_MAX;
- int s_count = 0;
- int t_count = 0;
+ // int s_count = 0;
+ // int t_count = 0;
char *err_msg;
int ret = -1;
- register int z;
+ // register int z;
// set<int> vertices;
@@ -335,7 +335,9 @@ apsp_warshall(PG_FUNCTION_ARGS)
{
MemoryContext oldcontext;
int pair_count = 0;
+#ifdef DEBUG
int ret;
+#endif
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
@@ -344,7 +346,10 @@ apsp_warshall(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- ret = compute_apsp_warshall(text2char(PG_GETARG_TEXT_P(0)),
+#ifdef DEBUG
+ ret =
+#endif
+ compute_apsp_warshall(text2char(PG_GETARG_TEXT_P(0)),
PG_GETARG_BOOL(1),
PG_GETARG_BOOL(2), &pair, &pair_count);
#ifdef DEBUG
diff --git a/src/apsp_warshall/src/apsp.h b/src/apsp_warshall/src/apsp.h
index c7f1ce9..d3c1b14 100644
--- a/src/apsp_warshall/src/apsp.h
+++ b/src/apsp_warshall/src/apsp.h
@@ -15,7 +15,7 @@ rm ap * but WITHOUT ANY WARRANTY; without even the implied warranty of
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/apsp_warshall/src/apsp_boost_wrapper.cpp b/src/apsp_warshall/src/apsp_boost_wrapper.cpp
index 4651fd0..246c8e5 100644
--- a/src/apsp_warshall/src/apsp_boost_wrapper.cpp
+++ b/src/apsp_warshall/src/apsp_boost_wrapper.cpp
@@ -15,12 +15,18 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <boost/lexical_cast.hpp>
#include <boost/config.hpp>
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
//#include <iostream>
//#include <fstream>
@@ -28,6 +34,7 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/floyd_warshall_shortest.hpp>
//#include <boost/graph/johnson_all_pairs_shortest_paths.hpp>
+
#include "string"
#include "apsp.h"
#include "set"
@@ -80,7 +87,7 @@ try {
float *weights = (float*) malloc(sizeof(float) * (edge_count));
- for(int i=0;i<edge_count;i++)
+ for(unsigned int i=0;i<edge_count;i++)
{
weights[i] = edges[i].cost;
vertices.insert(edges[i].source);
@@ -186,7 +193,7 @@ try {
}
}
-#ifdef JUNK
+#if 0
/*
void static_warshall()
{
@@ -259,7 +266,7 @@ int main()
typedef std::pair<int,int> Edge;
unsigned int edge_count = 4;
edge_t *edges = (edge_t*) malloc(sizeof(edge_t)*edge_count);
- /*Edge edge_array[ ] =
+ Edge edge_array[ ] =
{ Edge(0,1), Edge(0,2), Edge(0,3), Edge(0,4), Edge(0,5),
Edge(1,2), Edge(1,5), Edge(1,3), Edge(2,4), Edge(2,5),
Edge(3,2), Edge(4,3), Edge(4,1), Edge(5,4) };
diff --git a/src/apsp_warshall/test/apsp_warshall-any-00.rest b/src/apsp_warshall/test/apsp_warshall-any-00.result
similarity index 100%
rename from src/apsp_warshall/test/apsp_warshall-any-00.rest
rename to src/apsp_warshall/test/apsp_warshall-any-00.result
diff --git a/src/apsp_warshall/test/apsp_warshall-any-00.test b/src/apsp_warshall/test/apsp_warshall-any-00.test.sql
similarity index 100%
rename from src/apsp_warshall/test/apsp_warshall-any-00.test
rename to src/apsp_warshall/test/apsp_warshall-any-00.test.sql
diff --git a/src/astar/doc/index.rst b/src/astar/doc/index.rst
index ee97c4b..d77c1bd 100644
--- a/src/astar/doc/index.rst
+++ b/src/astar/doc/index.rst
@@ -84,17 +84,16 @@ Examples
4, 1, false, false
);
- seq | node | edge | cost
- -----+------+------+------
- 0 | 4 | 16 | 1
- 1 | 9 | 9 | 1
- 2 | 6 | 8 | 1
- 3 | 5 | 4 | 1
- 4 | 2 | 1 | 1
- 5 | 1 | -1 | 0
-
- (4 rows)
-
+ seq | node | edge | cost
+ -----+------+------+------
+ 0 | 4 | 16 | 1
+ 1 | 9 | 9 | 1
+ 2 | 6 | 8 | 1
+ 3 | 5 | 4 | 1
+ 4 | 2 | 1 | 1
+ 5 | 1 | -1 | 0
+
+ (6 rows)
* With ``reverse_cost``
diff --git a/src/astar/sql/astar.sql b/src/astar/sql/astar.sql
index 8fa5c98..f6b778a 100644
--- a/src/astar/sql/astar.sql
+++ b/src/astar/sql/astar.sql
@@ -14,7 +14,7 @@
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--
@@ -25,5 +25,5 @@
-----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION pgr_astar(sql text, source_id integer, target_id integer, directed boolean, has_reverse_cost boolean)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting', 'shortest_path_astar'
+ AS '$libdir/librouting-2.1', 'shortest_path_astar'
LANGUAGE c IMMUTABLE STRICT;
diff --git a/src/astar/src/astar.c b/src/astar/src/astar.c
index dd6c10e..11b7b44 100644
--- a/src/astar/src/astar.c
+++ b/src/astar/src/astar.c
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -427,7 +427,9 @@ shortest_path_astar(PG_FUNCTION_ARGS)
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int path_count = 0;
+#ifdef DEBUG
int ret;
+#endif
// XXX profiling messages are not thread safe
profstart(prof_total);
@@ -440,7 +442,10 @@ shortest_path_astar(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- ret = compute_shortest_path_astar(text2char(PG_GETARG_TEXT_P(0)),
+#ifdef DEBUG
+ ret =
+#endif
+ compute_shortest_path_astar(text2char(PG_GETARG_TEXT_P(0)),
PG_GETARG_INT32(1),
PG_GETARG_INT32(2),
PG_GETARG_BOOL(3),
diff --git a/src/astar/src/astar.h b/src/astar/src/astar.h
index d5872bb..41ddb36 100644
--- a/src/astar/src/astar.h
+++ b/src/astar/src/astar.h
@@ -15,15 +15,17 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#define _ASTAR_H
+#include <unistd.h>
#include "postgres.h"
-#include "dijkstra.h"
+#include "../../common/src/pgr_types.h"
+#if 0
typedef struct edge_astar
{
int id;
@@ -36,6 +38,8 @@ typedef struct edge_astar
float8 t_x;
float8 t_y;
} edge_astar_t;
+#endif
+
#ifdef __cplusplus
extern "C"
diff --git a/src/astar/src/astar_boost_wrapper.cpp b/src/astar/src/astar_boost_wrapper.cpp
index 5e1ca3d..96e80dd 100644
--- a/src/astar/src/astar_boost_wrapper.cpp
+++ b/src/astar/src/astar_boost_wrapper.cpp
@@ -15,12 +15,17 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
// Include C header first for windows build issue
-#include "astar.h"
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#include <boost/config.hpp>
@@ -29,6 +34,7 @@
#include <boost/graph/astar_search.hpp>
#include <cmath> // for sqrt
+#include "astar.h"
using namespace std;
using namespace boost;
@@ -172,10 +178,10 @@ try {
edges[j].target,
edges[j].source,
cost,
- edges[j].s_x,
- edges[j].s_y,
edges[j].t_x,
- edges[j].t_y);
+ edges[j].t_y,
+ edges[j].s_x,
+ edges[j].s_y);
}
}
@@ -262,9 +268,9 @@ try {
for (tie(out_i, out_end) = out_edges(v_src, graph);
out_i != out_end; ++out_i)
{
- graph_traits < graph_t >::vertex_descriptor v, targ;
+ graph_traits < graph_t >::vertex_descriptor targ; // v set but not used
e = *out_i;
- v = source(e, graph);
+ // v = source(e, graph);
targ = target(e, graph);
if (targ == v_targ)
@@ -287,6 +293,7 @@ try {
*err_msg = (char *) "Unknown exception caught!";
return -1;
}
- return -1;
+ *err_msg = (char *) "No path found";
+ return 0;
}
diff --git a/src/astar/test/spas-any-00.rest b/src/astar/test/spas-any-00.result
similarity index 100%
rename from src/astar/test/spas-any-00.rest
rename to src/astar/test/spas-any-00.result
diff --git a/src/astar/test/spas-any-00.test b/src/astar/test/spas-any-00.test.sql
similarity index 100%
rename from src/astar/test/spas-any-00.test
rename to src/astar/test/spas-any-00.test.sql
diff --git a/src/astar/test/spas-any-01.rest b/src/astar/test/spas-any-01.result
similarity index 100%
rename from src/astar/test/spas-any-01.rest
rename to src/astar/test/spas-any-01.result
diff --git a/src/astar/test/spas-any-01.test b/src/astar/test/spas-any-01.test.sql
similarity index 100%
rename from src/astar/test/spas-any-01.test
rename to src/astar/test/spas-any-01.test.sql
diff --git a/src/bd_astar/sql/routing_bd_astar.sql b/src/bd_astar/sql/routing_bd_astar.sql
index 5fd4376..ea59370 100644
--- a/src/bd_astar/sql/routing_bd_astar.sql
+++ b/src/bd_astar/sql/routing_bd_astar.sql
@@ -12,6 +12,6 @@ CREATE OR REPLACE FUNCTION pgr_bdAstar(
directed boolean,
has_reverse_cost boolean)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting_bd', 'bidir_astar_shortest_path'
+ AS '$libdir/librouting-2.1', 'bidir_astar_shortest_path'
LANGUAGE 'c' IMMUTABLE STRICT;
diff --git a/src/bd_astar/src/BiDirAStar.cpp b/src/bd_astar/src/BiDirAStar.cpp
index 8d61ae8..28ccd1a 100644
--- a/src/bd_astar/src/BiDirAStar.cpp
+++ b/src/bd_astar/src/BiDirAStar.cpp
@@ -29,6 +29,11 @@
#undef DEBUG
//#define DEBUG
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#ifdef DEBUG
#include <stdio.h>
@@ -236,12 +241,14 @@ void BiDirAStar::explore(int cur_node, double cur_cost, int dir, MinHeap &que)
GraphEdgeInfo edge = m_vecEdgeVector[edge_index];
// Get the connected node
int new_node = m_vecNodeVector[cur_node].Connected_Nodes[i];
+#if 0 // mult is set but not used
int mult;
if(edge.Direction == 0)
mult = 1;
else
mult = dir;
+#endif
if(cur_node == edge.StartNode)
{
// Current node is the startnode of the edge. For forward search it should use forward cost, otherwise it should use the reverse cost,
@@ -323,7 +330,7 @@ int BiDirAStar:: bidir_astar(edge_astar_t *edges, unsigned int edge_count, int m
m_lStartNodeId = start_vertex;
m_lEndNodeId = end_vertex;
- int nodeCount = m_vecNodeVector.size();
+ // int nodeCount = m_vecNodeVector.size();
MinHeap fque(maxNode + 2);
MinHeap rque(maxNode + 2);
@@ -345,9 +352,9 @@ int BiDirAStar:: bidir_astar(edge_astar_t *edges, unsigned int edge_count, int m
rque.push(std::make_pair(0.0, end_vertex));
int i;
- int new_node;
+ // int new_node;
int cur_node;
- int dir;
+ // int dir;
/*
The main loop. The algorithm is as follows:
1. IF the sum of the current minimum of both heap is greater than so far found path, we cannot get any better, so break the loop.
@@ -468,7 +475,7 @@ bool BiDirAStar::construct_graph(edge_astar_t* edges, int edge_count, int maxNod
bool BiDirAStar::addEdge(edge_astar_t edgeIn)
{
- long lTest;
+ // long lTest;
// Check if the edge is already processed.
Long2LongMap::iterator itMap = m_mapEdgeId2Index.find(edgeIn.id);
if(itMap != m_mapEdgeId2Index.end())
diff --git a/src/bd_astar/src/bdastar.c b/src/bd_astar/src/bdastar.c
index 32abb07..03bd604 100644
--- a/src/bd_astar/src/bdastar.c
+++ b/src/bd_astar/src/bdastar.c
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -84,7 +84,7 @@ Datum bidir_astar_shortest_path(PG_FUNCTION_ARGS);
// The number of tuples to fetch from the SPI cursor at each iteration
#define TUPLIMIT 1000
-#ifdef PG_MODULE_MAGIC
+#ifndef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
@@ -430,7 +430,9 @@ bidir_astar_shortest_path(PG_FUNCTION_ARGS)
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int path_count = 0;
+#ifdef DEBUG
int ret;
+#endif
// XXX profiling messages are not thread safe
profstart(prof_total);
@@ -443,7 +445,10 @@ bidir_astar_shortest_path(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- ret = compute_shortest_path_astar(text2char(PG_GETARG_TEXT_P(0)),
+#ifdef DEBUG
+ ret =
+#endif
+ compute_shortest_path_astar(text2char(PG_GETARG_TEXT_P(0)),
PG_GETARG_INT32(1),
PG_GETARG_INT32(2),
PG_GETARG_BOOL(3),
diff --git a/src/bd_astar/src/bdastar.h b/src/bd_astar/src/bdastar.h
index 2ce18e8..c631325 100644
--- a/src/bd_astar/src/bdastar.h
+++ b/src/bd_astar/src/bdastar.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef _BDASTAR_H
diff --git a/src/bd_astar/src/bdastar_core.cpp b/src/bd_astar/src/bdastar_core.cpp
index 1fa2710..038b010 100644
--- a/src/bd_astar/src/bdastar_core.cpp
+++ b/src/bd_astar/src/bdastar_core.cpp
@@ -26,6 +26,11 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#include <exception>
#include "BiDirAStar.h"
diff --git a/src/bd_astar/test/bd_astar-any-01.rest b/src/bd_astar/test/bd_astar-any-01.result
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-01.rest
rename to src/bd_astar/test/bd_astar-any-01.result
diff --git a/src/bd_astar/test/bd_astar-any-01.test b/src/bd_astar/test/bd_astar-any-01.test.sql
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-01.test
rename to src/bd_astar/test/bd_astar-any-01.test.sql
diff --git a/src/bd_astar/test/bd_astar-any-02.rest b/src/bd_astar/test/bd_astar-any-02.result
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-02.rest
rename to src/bd_astar/test/bd_astar-any-02.result
diff --git a/src/bd_astar/test/bd_astar-any-02.test b/src/bd_astar/test/bd_astar-any-02.test.sql
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-02.test
rename to src/bd_astar/test/bd_astar-any-02.test.sql
diff --git a/src/bd_astar/test/bd_astar-any-03.rest b/src/bd_astar/test/bd_astar-any-03.result
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-03.rest
rename to src/bd_astar/test/bd_astar-any-03.result
diff --git a/src/bd_astar/test/bd_astar-any-03.test b/src/bd_astar/test/bd_astar-any-03.test.sql
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-03.test
rename to src/bd_astar/test/bd_astar-any-03.test.sql
diff --git a/src/bd_astar/test/bd_astar-any-04.rest b/src/bd_astar/test/bd_astar-any-04.result
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-04.rest
rename to src/bd_astar/test/bd_astar-any-04.result
diff --git a/src/bd_astar/test/bd_astar-any-04.test b/src/bd_astar/test/bd_astar-any-04.test.sql
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-04.test
rename to src/bd_astar/test/bd_astar-any-04.test.sql
diff --git a/src/bd_astar/test/bd_astar-any-05.rest b/src/bd_astar/test/bd_astar-any-05.result
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-05.rest
rename to src/bd_astar/test/bd_astar-any-05.result
diff --git a/src/bd_astar/test/bd_astar-any-05.test b/src/bd_astar/test/bd_astar-any-05.test.sql
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-05.test
rename to src/bd_astar/test/bd_astar-any-05.test.sql
diff --git a/src/bd_astar/test/bd_astar-any-06.rest b/src/bd_astar/test/bd_astar-any-06.result
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-06.rest
rename to src/bd_astar/test/bd_astar-any-06.result
diff --git a/src/bd_astar/test/bd_astar-any-06.test b/src/bd_astar/test/bd_astar-any-06.test.sql
similarity index 100%
rename from src/bd_astar/test/bd_astar-any-06.test
rename to src/bd_astar/test/bd_astar-any-06.test.sql
diff --git a/src/bd_dijkstra/sql/routing_bd_dijkstra.sql b/src/bd_dijkstra/sql/routing_bd_dijkstra.sql
index 9c587d8..6565711 100644
--- a/src/bd_dijkstra/sql/routing_bd_dijkstra.sql
+++ b/src/bd_dijkstra/sql/routing_bd_dijkstra.sql
@@ -12,6 +12,6 @@ CREATE OR REPLACE FUNCTION pgr_bdDijkstra(
directed boolean,
has_reverse_cost boolean)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting_bd', 'bidir_dijkstra_shortest_path'
+ AS '$libdir/librouting-2.1', 'bidir_dijkstra_shortest_path'
LANGUAGE c IMMUTABLE STRICT;
diff --git a/src/bd_dijkstra/src/BiDirDijkstra.cpp b/src/bd_dijkstra/src/BiDirDijkstra.cpp
index 0ea8a80..4014c5a 100644
--- a/src/bd_dijkstra/src/BiDirDijkstra.cpp
+++ b/src/bd_dijkstra/src/BiDirDijkstra.cpp
@@ -27,6 +27,11 @@
*****************************************************************************/
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#include "BiDirDijkstra.h"
#undef DEBUG
@@ -314,9 +319,9 @@ int BiDirDijkstra::bidir_dijkstra(edge_t *edges, unsigned int edge_count, int ma
rque.push(std::make_pair(0.0, end_vertex));
int i;
- int new_node;
+ // int new_node;
int cur_node;
- int dir;
+ // int dir;
/*
The main loop. The algorithm is as follows:
@@ -445,7 +450,7 @@ bool BiDirDijkstra::construct_graph(edge_t* edges, int edge_count, int maxNode)
bool BiDirDijkstra::addEdge(edge_t edgeIn)
{
- long lTest;
+ // long lTest;
// Check if the edge is already processed.
Long2LongMap::iterator itMap = m_mapEdgeId2Index.find(edgeIn.id);
diff --git a/src/bd_dijkstra/src/bdsp.c b/src/bd_dijkstra/src/bdsp.c
index a85a526..5667e29 100644
--- a/src/bd_dijkstra/src/bdsp.c
+++ b/src/bd_dijkstra/src/bdsp.c
@@ -347,14 +347,16 @@ bidir_dijkstra_shortest_path(PG_FUNCTION_ARGS)
int max_calls;
TupleDesc tuple_desc;
path_element_t *path;
- char * sql;
+ // char * sql;
// stuff done only on the first call of the function
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int path_count = 0;
+#ifdef DEBUG
int ret = -1;
+#endif
int i;
// create a function context for cross-call persistence
@@ -371,7 +373,10 @@ bidir_dijkstra_shortest_path(PG_FUNCTION_ARGS)
DBG("Calling compute_bidirsp");
- ret = compute_bidirsp(text2char(PG_GETARG_TEXT_P(0)),
+#ifdef DEBUG
+ ret =
+#endif
+ compute_bidirsp(text2char(PG_GETARG_TEXT_P(0)),
PG_GETARG_INT32(1),
PG_GETARG_INT32(2),
PG_GETARG_BOOL(3),
diff --git a/src/bd_dijkstra/src/bdsp.h b/src/bd_dijkstra/src/bdsp.h
index 5b91ba2..05e2503 100644
--- a/src/bd_dijkstra/src/bdsp.h
+++ b/src/bd_dijkstra/src/bdsp.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef _BDSP_H
diff --git a/src/bd_dijkstra/src/bdsp_core.cpp b/src/bd_dijkstra/src/bdsp_core.cpp
index 4cfb3b9..2ed8eb6 100644
--- a/src/bd_dijkstra/src/bdsp_core.cpp
+++ b/src/bd_dijkstra/src/bdsp_core.cpp
@@ -27,6 +27,11 @@
*****************************************************************************/
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#include <exception>
#include "BiDirDijkstra.h"
#include "bdsp.h"
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-01.rest b/src/bd_dijkstra/test/bd_dijkstra-any-01.result
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-01.rest
rename to src/bd_dijkstra/test/bd_dijkstra-any-01.result
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-01.test b/src/bd_dijkstra/test/bd_dijkstra-any-01.test.sql
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-01.test
rename to src/bd_dijkstra/test/bd_dijkstra-any-01.test.sql
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-02.rest b/src/bd_dijkstra/test/bd_dijkstra-any-02.result
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-02.rest
rename to src/bd_dijkstra/test/bd_dijkstra-any-02.result
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-02.test b/src/bd_dijkstra/test/bd_dijkstra-any-02.test.sql
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-02.test
rename to src/bd_dijkstra/test/bd_dijkstra-any-02.test.sql
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-03.rest b/src/bd_dijkstra/test/bd_dijkstra-any-03.result
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-03.rest
rename to src/bd_dijkstra/test/bd_dijkstra-any-03.result
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-03.test b/src/bd_dijkstra/test/bd_dijkstra-any-03.test.sql
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-03.test
rename to src/bd_dijkstra/test/bd_dijkstra-any-03.test.sql
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-04.rest b/src/bd_dijkstra/test/bd_dijkstra-any-04.result
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-04.rest
rename to src/bd_dijkstra/test/bd_dijkstra-any-04.result
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-04.test b/src/bd_dijkstra/test/bd_dijkstra-any-04.test.sql
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-04.test
rename to src/bd_dijkstra/test/bd_dijkstra-any-04.test.sql
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-05.rest b/src/bd_dijkstra/test/bd_dijkstra-any-05.result
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-05.rest
rename to src/bd_dijkstra/test/bd_dijkstra-any-05.result
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-05.test b/src/bd_dijkstra/test/bd_dijkstra-any-05.test.sql
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-05.test
rename to src/bd_dijkstra/test/bd_dijkstra-any-05.test.sql
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-06.rest b/src/bd_dijkstra/test/bd_dijkstra-any-06.result
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-06.rest
rename to src/bd_dijkstra/test/bd_dijkstra-any-06.result
diff --git a/src/bd_dijkstra/test/bd_dijkstra-any-06.test b/src/bd_dijkstra/test/bd_dijkstra-any-06.test.sql
similarity index 100%
rename from src/bd_dijkstra/test/bd_dijkstra-any-06.test
rename to src/bd_dijkstra/test/bd_dijkstra-any-06.test.sql
diff --git a/src/common/doc/convenience/flip_edges.rst b/src/common/doc/convenience/flip_edges.rst
new file mode 100644
index 0000000..92d98a6
--- /dev/null
+++ b/src/common/doc/convenience/flip_edges.rst
@@ -0,0 +1,91 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_flip_edges:
+
+pgr_flipEdges
+==============================================================================
+
+.. index::
+ single: pgr_flipEdges(ga geometry[])
+ module: common
+
+
+Name
+------------------------------------------------------------------------------
+
+``pgr_flipEdges`` -
+
+
+Synopsis
+------------------------------------------------------------------------------
+
+The function returns:
+
+ - ``geometry[]`` An array of the input geometries with the geometries flipped end to end such that the geometries are oriented as a path from start to end.
+
+.. code-block:: sql
+
+ geometry[] pgr_flipEdges(ga geometry[])
+
+
+Description
+-----------------------------------------------------------------------------
+
+Given an array of linestrings that are supposedly connected end to end like the results of a route, check the edges and flip any end for end if they do not connect with the previous seegment and return the array with the segments flipped as appropriate.
+
+.. rubric:: Parameters
+
+:ga: ``geometry[]`` An array of geometries, like the results of a routing query.
+
+.. warning::
+
+ * No checking is done for edges that do not connect.
+ * Input geometries MUST be LINESTRING or MULTILINESTRING.
+ * Only the first LINESTRING of a MULTILINESTRING is considered.
+
+.. rubric:: History
+
+* New in version 2.1.0
+
+
+Examples
+-----------------------------------------------------------------------------
+
+.. code-block:: sql
+
+ select st_astext(e) from (select unnest(pgr_flipedges(ARRAY[
+ 'LINESTRING(2 1,2 2)'::geometry,
+ 'LINESTRING(2 2,2 3)'::geometry,
+ 'LINESTRING(2 2,2 3)'::geometry,
+ 'LINESTRING(2 2,3 2)'::geometry,
+ 'LINESTRING(3 2,4 2)'::geometry,
+ 'LINESTRING(4 1,4 2)'::geometry,
+ 'LINESTRING(3 1,4 1)'::geometry,
+ 'LINESTRING(2 1,3 1)'::geometry,
+ 'LINESTRING(2 0,2 1)'::geometry,
+ 'LINESTRING(2 0,2 1)'::geometry]::geometry[])) as e) as foo;
+ st_astext
+ ---------------------
+ LINESTRING(2 1,2 2)
+ LINESTRING(2 2,2 3)
+ LINESTRING(2 3,2 2)
+ LINESTRING(2 2,3 2)
+ LINESTRING(3 2,4 2)
+ LINESTRING(4 2,4 1)
+ LINESTRING(4 1,3 1)
+ LINESTRING(3 1,2 1)
+ LINESTRING(2 1,2 0)
+ LINESTRING(2 0,2 1)
+ (10 rows)
+
+
+See Also
+-----------------------------------------------------------------------------
+
diff --git a/src/common/doc/convenience/index.rst b/src/common/doc/convenience/index.rst
new file mode 100644
index 0000000..d4a3935
--- /dev/null
+++ b/src/common/doc/convenience/index.rst
@@ -0,0 +1,44 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _convenience_functions:
+
+Convenience Functions
+===============================================================================
+
+The following functions are general purpose convenience functions that might
+be useful when building a larger application or handling input from say an
+Ajax handler.
+
+ - :ref:`pgr_point_to_edgenode` - convert a point geometry to a ``vertex_id`` based on closest edge.
+ - :ref:`pgr_flip_edges` - flip the edges in an array of geometries so the connect end to end.
+ - :ref:`pgr_text_to_points` - convert a string of ``x,y;x,y;...`` locations into point geometries.
+ - :ref:`pgr_points_to_vids` - convert an array of point geometries into vertex ids.
+
+Distance Matrix Functions
+===============================================================================
+
+These function my be helpful when you need to create or manipulate distance matricies, like for TSP or VRP related problems.
+
+ - :ref:`pgr_points_to_dmatrix` - Create a distance matrix from an array of points.
+ - :ref:`pgr_vids_to_dmatrix` - Create a distance matrix from an array of ``vertix_id``.
+ - :ref:`pgr_vids_to_dmatrix2` - Create a distance matrix from an array of ``vertix_id``.
+
+.. toctree::
+ :hidden:
+
+ pgr_pointToEdgeNode - convert a point geometry to a ``vertex_id`` based on closest edge. <point_to_edgenode>
+ pgr_flipEdges - flip the edges in an array of geometries so the connect end to end. <flip_edges>
+ pgr_textToPoints - convert a string of ``x,y;x,y;...`` locations into point geometries. <text_to_points>
+ pgr_pointsToVids - convert an array of point geometries into ``node_id``s. <points_to_vids>
+
+ pgr_pointsToDMatrix - Create a distance matrix from an array of points. <points_to_dmatrix>
+ pgr_vidsToDMatrix - Create a distance matrix from an array of ``vertix_id``. <vids_to_dmatrix>
+ pgr_vidsToDMatrix - Create a distance matrix from an array of ``vertix_id``. <vids_to_dmatrix2>
+
diff --git a/src/common/doc/convenience/point_to_edgenode.rst b/src/common/doc/convenience/point_to_edgenode.rst
new file mode 100644
index 0000000..cfbc266
--- /dev/null
+++ b/src/common/doc/convenience/point_to_edgenode.rst
@@ -0,0 +1,83 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_point_to_edgenode:
+
+pgr_pointToEdgeNode
+==============================================================================
+
+.. index::
+ single: pgr_pointToEdgeNode(edges text, pnt geometry, tol float8)
+ module: common
+
+
+Name
+------------------------------------------------------------------------------
+
+``pgr_pointToEdgeNode`` - Converts a point to a ``vertex_id`` based on closest edge.
+
+
+Synopsis
+------------------------------------------------------------------------------
+
+The function returns:
+
+ - ``integer`` that is the vertex id of the closest edge in the ``edges`` table within the ``tol`` tolerance of ``pnt``. The vertex is selected by projection the ``pnt`` onto the edge and selecting which vertex is closer along the edge.
+
+.. code-block:: sql
+
+ integer pgr_pointToEdgeNode(edges text, pnt geometry, tol float8)
+
+
+Description
+-----------------------------------------------------------------------------
+
+Given an table ``edges`` with a spatial index on ``the_geom`` and a point geometry search for the closest edge within ``tol`` distance to the edges then compute the projection of the point onto the line segment and select source or target based on whether the projected point is closer to the respective end and return the source or target value.
+
+.. rubric:: Parameters
+
+The function accepts the following parameters:
+
+:edges: ``text`` The name of the edge table or view. (may contain the schema name AS well).
+:pnt: ``geometry`` A point geometry object in the same SRID as ``edges``.
+:tol: ``float8`` The maximum search distance for an edge.
+
+.. warning::
+
+ If no edge is within tol distance then return -1
+
+The ``edges`` table must have the following columns:
+
+ * ``source``
+ * ``target``
+ * ``the_geom``
+
+.. rubric:: History
+
+* New in version 2.1.0
+
+
+Examples
+-----------------------------------------------------------------------------
+
+.. code-block:: sql
+
+ select pgr_pointtoedgenode('edge_table', 'POINT(2 0)'::geometry, 0.02);
+ pgr_pointtoedgenode
+ -------------------
+ 1
+ (1 row)
+
+The example uses the :ref:`sampledata` network.
+
+See Also
+-----------------------------------------------------------------------------
+
+* :ref:`pgr_points_to_vids` - convert an array of point geometries into vertex ids.
+
diff --git a/src/common/doc/convenience/points_to_dmatrix.rst b/src/common/doc/convenience/points_to_dmatrix.rst
new file mode 100644
index 0000000..4a933a5
--- /dev/null
+++ b/src/common/doc/convenience/points_to_dmatrix.rst
@@ -0,0 +1,94 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_points_to_dmatrix:
+
+pgr_pointsToDMatrix
+==============================================================================
+
+.. index::
+ single: pgr_pointsToDMatrix(pnts geometry[], OUT dmatrix double precision[], OUT ids integer[])
+ module: common
+
+
+Name
+------------------------------------------------------------------------------
+
+``pgr_pointsToDMatrix`` - Creates a distance matrix from an array of points.
+
+
+Synopsis
+------------------------------------------------------------------------------
+
+Create a distance symetric distance matrix suitable for TSP using Euclidean distances based on the st_distance(). You might want to create a variant of this the uses st_distance_sphere() or st_distance_spheriod() or some other function.
+
+The function returns:
+
+ - ``record`` - with two fields as describe here
+ * :dmatrix: ``float8[]`` - the distance matrix suitable to pass to pgrTSP() function.
+ * :ids: ``integer[]`` - an array of ids for the distance matrix.
+
+.. code-block:: sql
+
+ record pgr_pointsToDMatrix(pnts geometry[], OUT dmatrix double precision[], OUT ids integer[])
+
+
+Description
+-----------------------------------------------------------------------------
+
+.. rubric:: Paramters
+
+:pnts: ``geometry[]`` - An array of point geometries.
+
+.. warning::
+
+ The generated matrix will be symmetric as required for pgr_TSP.
+
+
+.. rubric:: History
+
+* New in version 2.1.0
+
+
+Examples
+-----------------------------------------------------------------------------
+
+.. code-block:: sql
+
+ select unnest(dmatrix) from pgr_pointsToDMatrix(
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0)
+ ) limit 8;
+ unnest
+ ------------------
+ 0
+ 1
+ 1.4142135623731
+ 2
+ 2.23606797749979
+ 2.82842712474619
+ 3
+ 2.23606797749979
+ (8 rows)
+
+ select ids from pgr_pointstodmatrix(
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0)
+ );
+ ids
+ -------------------
+ {1,2,3,4,5,6,7,8}
+ (1 row)
+
+
+
+See Also
+-----------------------------------------------------------------------------
+
+* :ref:`pgr_vids_to_dmatrix` - convert a point geometry to the closest vertex_id of an edge..
+* :ref:`pgr_tsp<pgr_tsp>` - Traveling Sales Person
+
diff --git a/src/common/doc/convenience/points_to_vids.rst b/src/common/doc/convenience/points_to_vids.rst
new file mode 100644
index 0000000..70d52cf
--- /dev/null
+++ b/src/common/doc/convenience/points_to_vids.rst
@@ -0,0 +1,81 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_points_to_vids:
+
+pgr_pointsToVids
+==============================================================================
+
+.. index::
+ single: pgr_pointsToVids(pnts geometry[], edges text, tol float8 DEFAULT(0.01))
+ module: common
+
+
+Name
+------------------------------------------------------------------------------
+
+``pgr_pointsToVids`` - Converts an array of point geometries into vertex ids.
+
+
+Synopsis
+------------------------------------------------------------------------------
+
+Given an array of point geometries and an edge table and a max search tol distance the function converts points into vertex ids using pgr_pointtoedgenode().
+
+The function returns:
+
+ - ``integer[]`` - An array of ``vertex_id``.
+
+.. code-block:: sql
+
+ integer[] pgr_pointsToVids(pnts geometry[], edges text, tol float8 DEFAULT(0.01))
+
+
+Description
+-----------------------------------------------------------------------------
+
+.. rubric:: Paramters
+
+:pnts: ``geometry[]`` - An array of point geometries.
+:edges: ``text`` - The edge table to be used for the conversion.
+:tol: ``float8`` - The maximum search distance for locating the closest edge.
+
+.. warning::
+
+ You need to check the results for any vids=-1 which indicates if failed to locate an edge.
+
+
+.. rubric:: History
+
+* New in version 2.1.0
+
+
+Examples
+-----------------------------------------------------------------------------
+
+.. code-block:: sql
+
+ select * from pgr_pointstovids(
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0),
+ 'edge_table'
+ -- tol is not specified, so we use the default of 0.01
+ );
+ pgr_pointstovids
+ --------------------
+ {1,2,3,5,4,9,10,6}
+ (1 row)
+
+This example uses the :ref:`sampledata` network.
+
+
+See Also
+-----------------------------------------------------------------------------
+
+* :ref:`pgr_point_to_edgenode` - convert a point geometry to the closest vertex_id of an edge..
+
diff --git a/src/common/doc/convenience/text_to_points.rst b/src/common/doc/convenience/text_to_points.rst
new file mode 100644
index 0000000..824fde1
--- /dev/null
+++ b/src/common/doc/convenience/text_to_points.rst
@@ -0,0 +1,81 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_text_to_points:
+
+pgr_textToPoints
+==============================================================================
+
+.. index::
+ single: pgr_textToPoints(pnts text, srid integer DEFAULT(4326))
+ module: common
+
+
+Name
+------------------------------------------------------------------------------
+
+``pgr_textToPoints`` - Converts a text string of the format "x,y;x,y;x,y;..." into and array of point geometries.
+
+
+Synopsis
+------------------------------------------------------------------------------
+
+Given a text string of the format "x,y;x,y;x,y;..." and the srid to use, split the string and create and array point geometries.
+
+The function returns:
+
+ -
+
+.. code-block:: sql
+
+ integer pgr_textToPoints(pnts text, srid integer DEFAULT(4326))
+
+
+Description
+-----------------------------------------------------------------------------
+
+.. rubric:: Paramters
+
+:pnts: ``text`` A text string of the format "x,y;x,y;x,y;..." where x is longitude and y is latitude if use values in lat-lon.
+:srid: ``integer`` The SRID to use when constructing the point geometry. If the paratmeter is absent it defaults to ``SRID:4326``.
+
+.. rubric:: History
+
+* New in version 2.1.0
+
+
+Examples
+-----------------------------------------------------------------------------
+
+.. code-block:: sql
+
+ select st_astext(g) from (
+ select unnest(
+ pgr_texttopoints('0,0;1,1;1,0;0,1;1,4;1,5;0,4;0,5', 0)
+ ) as g
+ ) as foo;
+ st_astext
+ ------------
+ POINT(0 0)
+ POINT(1 1)
+ POINT(1 0)
+ POINT(0 1)
+ POINT(1 4)
+ POINT(1 5)
+ POINT(0 4)
+ POINT(0 5)
+ (8 rows)
+
+
+
+See Also
+-----------------------------------------------------------------------------
+
+* :ref:`pgr_point_to_edgenode` - convert a point geometry to a ``node_id`` based on closest edge.
+* :ref:`pgr_points_to_vids` - convert an array of point geometries into vertex ids.
diff --git a/src/common/doc/convenience/vids_to_dmatrix.rst b/src/common/doc/convenience/vids_to_dmatrix.rst
new file mode 100644
index 0000000..6f7ca47
--- /dev/null
+++ b/src/common/doc/convenience/vids_to_dmatrix.rst
@@ -0,0 +1,102 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_vids_to_dmatrix:
+
+pgr_vidsToDMatrix
+==============================================================================
+
+.. index::
+ single: pgr_vidsToDMatrix(IN vids integer[], IN pnts geometry[], IN edges text, tol float8 DEFAULT(0.1), OUT dmatrix double precision[], OUT ids integer[])
+ module: common
+
+
+Name
+------------------------------------------------------------------------------
+
+``pgr_vidsToDMatrix`` - Creates a distances matrix from an array of ``vertex_id``.
+
+
+Synopsis
+------------------------------------------------------------------------------
+
+This function takes an array of ``vertex_id``, the original array of points used to generate the array of ``vertex_id``, an edge table name and a tol. It then computes kdijkstra() distances for each vertex to all the other vertices and creates a symmetric distance matrix suitable for TSP. The pnt array and the tol are used to establish a BBOX for limiting selection of edges. The extents of the points is expanded by tol.
+
+The function returns:
+
+ - ``record`` - with two fields as describe here
+ * :dmatrix: ``float8[]`` - the distance matrix suitable to pass to pgrTSP() function.
+ * :ids: ``integer[]`` - an array of ids for the distance matrix.
+
+
+.. code-block:: sql
+
+ record pgr_vidsToDMatrix(IN vids integer[], IN pnts geometry[], IN edges text, tol float8 DEFAULT(0.1), OUT dmatrix double precision[], OUT ids integer[])
+
+
+Description
+-----------------------------------------------------------------------------
+
+.. rubric:: Paramters
+
+:vids: ``integer[]`` - An array of ``vertex_id``.
+:pnts: ``geometry[]`` - An array of point geometries that approximates the extents of the ``vertex_id``.
+:edges: ``text`` - The edge table to be used for the conversion.
+:tol: ``float8`` - The amount to expand the BBOX extents of ``pnts`` when building the graph.
+
+.. warning::
+
+ * we compute a symmetric matrix because TSP requires that so the distances are better the Euclidean but but are not perfect
+ * kdijkstra() can fail to find a path between some of the vertex ids. We to not detect this other than the cost might get set to -1.0, so the dmatrix shoule be checked for this as it makes it invalid for TSP
+
+
+.. rubric:: History
+
+* New in version 2.1.0
+
+
+Examples
+-----------------------------------------------------------------------------
+
+This example shows how this can be used in the context of feeding the results into pgr_tsp() function. We convert a text string of ``x,y;x,y;...`` into and array of points, then convert that into an array ``vertex_id``, then create a distance matrix that gets feed into ``pgr_tsp()`` that returns the final result.
+
+.. code-block:: sql
+
+ select * from pgr_tsp(
+ (select dmatrix::float8[]
+ from pgr_vidstodmatrix(
+ pgr_pointstovids(
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0),
+ 'edge_table'),
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0),
+ 'edge_table')
+ ),
+ 1
+ );
+ seq | id
+ -----+----
+ 0 | 1
+ 1 | 3
+ 2 | 7
+ 3 | 5
+ 4 | 4
+ 5 | 2
+ 6 | 6
+ 7 | 0
+ (8 rows)
+
+This example uses the :ref:`sampledata` network.
+
+
+See Also
+-----------------------------------------------------------------------------
+
+* :ref:`pgr_text_to_points` - Create an array of points from a text string.
+* :ref:`pgr_tsp<pgr_tsp>` - Traveling Sales Person
+
diff --git a/src/common/doc/convenience/vids_to_dmatrix2.rst b/src/common/doc/convenience/vids_to_dmatrix2.rst
new file mode 100644
index 0000000..b3bc755
--- /dev/null
+++ b/src/common/doc/convenience/vids_to_dmatrix2.rst
@@ -0,0 +1,101 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_vids_to_dmatrix2:
+
+pgr_vidsToDMatrix
+==============================================================================
+
+.. index::
+ single: pgr_vidsToDMatrix(IN sql text, IN vids integer[], IN directed boolean, IN has_reverse_cost boolean, IN want_symmetric boolean, OUT dmatrix double precision[])
+ module: kdijkstra
+
+
+Name
+------------------------------------------------------------------------------
+
+``pgr_vidsToDMatrix`` - Creates a distances matrix from an array of ``vertex_id``.
+
+
+Synopsis
+------------------------------------------------------------------------------
+
+This function takes an array of ``vertex_id``, a ``sql`` statement to select the edges, and some boolean arguments to control the behavior. It then computes kdijkstra() distances for each vertex to all the other vertices and creates a distance matrix suitable for TSP.
+
+The function returns:
+
+ * :dmatrix: ``float8[]`` - the distance matrix suitable to pass to pgr_TSP() function.
+
+.. code-block:: sql
+
+ pgr_vidsToDMatrix(IN sql text, IN vids integer[], IN directed boolean, IN has_reverse_cost boolean, IN want_symmetric boolean, OUT dmatrix double precision[])
+
+
+
+Description
+-----------------------------------------------------------------------------
+
+.. rubric:: Paramters
+
+:sql: ``text`` - A SQL statement to select the edges needed for the solution.
+:vids: ``integer[]`` - An array of ``vertex_id``.
+:directed: ``boolean`` - A flag to indicate if the graph is directed.
+:has_reverse_cost: ``boolean`` - A flag to indicate if the SQL has a column ``reverse_cost``.
+:want_symmetric: ``boolean`` - A flag to indicate if you want a symmetric or asymmetric matrix. You will need a symmetric matrix for pgr_TSP(). If the matriix is asymmetric, the then the cell(i,j) and cell(j,i) will be set to the average of those two cells except if one or the other are -1.0 then it will take the value of the other cell. If both are negative they will be left alone.
+
+.. warning::
+
+ * kdijkstra() can fail to find a path between some of the vertex ids. We to not detect this other than the cost might get set to -1.0, so the dmatrix shoule be checked for this as it makes it invalid for TSP
+
+
+.. rubric:: History
+
+* New in version 2.1.0
+
+
+Examples
+-----------------------------------------------------------------------------
+
+This example shows how this can be used in the context of feeding the results into pgr_tsp() function. We convert a text string of ``x,y;x,y;...`` into and array of points, then convert that into an array ``vertex_id``, then create a distance matrix that gets feed into ``pgr_tsp()`` that returns the final result.
+
+.. code-block:: sql
+
+ select * from pgr_tsp(
+ (select dmatrix::float8[]
+ from pgr_vidstodmatrix(
+ 'select id, source, target, cost, reverse_cost from edge_table',
+ pgr_pointstovids(
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0),
+ 'edge_table'),
+ true, true, true) as dmatrix
+ ),
+ 1
+ );
+ seq | id
+ -----+----
+ 0 | 1
+ 1 | 0
+ 2 | 6
+ 3 | 3
+ 4 | 7
+ 5 | 5
+ 6 | 4
+ 7 | 2
+ (8 rows)
+
+This example uses the :ref:`sampledata` network.
+
+
+See Also
+-----------------------------------------------------------------------------
+
+* :ref:`pgr_vids_to_dmatrix` - - Creates a distances matrix from an array of ``vertex_id``.
+* :ref:`pgr_text_to_points` - Create an array of points from a text string.
+* :ref:`pgr_tsp<pgr_tsp>` - Traveling Sales Person
+
diff --git a/src/common/doc/functions/create_topology.rst b/src/common/doc/functions/create_topology.rst
index 75409b6..87a3231 100644
--- a/src/common/doc/functions/create_topology.rst
+++ b/src/common/doc/functions/create_topology.rst
@@ -34,7 +34,8 @@ The function returns:
varchar pgr_createTopology(text edge_table, double precision tolerance,
text the_geom:='the_geom', text id:='id',
- text source:='source',text target:='target',text rows_where:='true')
+ text source:='source',text target:='target',
+ text rows_where:='true', boolean clean:=false)
@@ -51,7 +52,9 @@ The topology creation function accepts the following parameters:
:id: ``text`` Primary key column name of the network table. Default value is ``id``.
:source: ``text`` Source column name of the network table. Default value is ``source``.
:target: ``text`` Target column name of the network table. Default value is ``target``.
-:rows_where: ``text`` Condition to SELECT a subset or rows. Default value is ``true`` to indicate all rows.
+:rows_where: ``text`` Condition to SELECT a subset or rows. Default value is ``true`` to indicate
+ all rows that where ``source`` or ``target`` have a null value, otherwise the condition is used.
+:clean: ``boolean`` Clean any previous topology. Default value is ``false``.
.. warning::
diff --git a/src/common/doc/functions/images/Fig1-originalData.png b/src/common/doc/functions/images/Fig1-originalData.png
new file mode 100644
index 0000000..2784787
Binary files /dev/null and b/src/common/doc/functions/images/Fig1-originalData.png differ
diff --git a/src/common/doc/functions/images/Fig2-cost.png b/src/common/doc/functions/images/Fig2-cost.png
new file mode 100644
index 0000000..13307af
Binary files /dev/null and b/src/common/doc/functions/images/Fig2-cost.png differ
diff --git a/src/common/doc/functions/images/Fig3-reverseCost.png b/src/common/doc/functions/images/Fig3-reverseCost.png
new file mode 100644
index 0000000..8adb61b
Binary files /dev/null and b/src/common/doc/functions/images/Fig3-reverseCost.png differ
diff --git a/src/common/doc/functions/images/Fig4-costUndirected.png b/src/common/doc/functions/images/Fig4-costUndirected.png
new file mode 100644
index 0000000..17e7040
Binary files /dev/null and b/src/common/doc/functions/images/Fig4-costUndirected.png differ
diff --git a/src/common/doc/functions/images/Fig5-reverseCostUndirected.png b/src/common/doc/functions/images/Fig5-reverseCostUndirected.png
new file mode 100644
index 0000000..9802b6a
Binary files /dev/null and b/src/common/doc/functions/images/Fig5-reverseCostUndirected.png differ
diff --git a/src/common/doc/functions/images/Fig6-undirected.png b/src/common/doc/functions/images/Fig6-undirected.png
new file mode 100644
index 0000000..6272a43
Binary files /dev/null and b/src/common/doc/functions/images/Fig6-undirected.png differ
diff --git a/src/common/doc/index.rst b/src/common/doc/index.rst
index 09bbb51..839c54e 100644
--- a/src/common/doc/index.rst
+++ b/src/common/doc/index.rst
@@ -15,6 +15,7 @@ Common Functions
.. toctree::
:maxdepth: 1
+ convenience/index
utilities/index
functions/index
types/index
diff --git a/src/common/doc/utilities/end_point.rst b/src/common/doc/utilities/end_point.rst
index c5bc131..472a1be 100644
--- a/src/common/doc/utilities/end_point.rst
+++ b/src/common/doc/utilities/end_point.rst
@@ -13,8 +13,7 @@ pgr_endPoint
===============================================================================
.. index::
- single: pgr_endPoint(geometry)
- module: common
+ single: pgr_endPoint(geometry) -- deprecated
Name
-------------------------------------------------------------------------------
@@ -23,6 +22,8 @@ Name
.. note:: This function is intended for the developer's aid.
+.. warning:: This function is being deprecated on 2.1.
+ Use `_pgr_endPoint` instead
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/get_column_name.rst b/src/common/doc/utilities/get_column_name.rst
index 21b4d4c..e21c3cd 100644
--- a/src/common/doc/utilities/get_column_name.rst
+++ b/src/common/doc/utilities/get_column_name.rst
@@ -13,8 +13,7 @@ pgr_getColumnName
===============================================================================
.. index::
- single: pgr_getColumnName(text,text)
- module: common
+ single: pgr_getColumnName(text,text) -- deprecated
Name
-------------------------------------------------------------------------------
@@ -23,6 +22,10 @@ Name
.. note:: This function is intended for the developer’s aid.
+
+.. warning:: This function is deprecated in 2.1.
+ Use `_pgr_getColumnName` instead
+
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/get_table_name.rst b/src/common/doc/utilities/get_table_name.rst
index 9dfcbad..9bd420c 100644
--- a/src/common/doc/utilities/get_table_name.rst
+++ b/src/common/doc/utilities/get_table_name.rst
@@ -13,7 +13,7 @@ pgr_getTableName
===============================================================================
.. index::
- single: pgr_getTableName(text,text)
+ single: pgr_getTableName(text,text) -- deprecated
module: common
Name
@@ -23,6 +23,9 @@ Name
.. note:: This function is intended for the developer’s aid.
+.. warning:: This function is deprecated in 2.1
+ Use `_pgr_getTableName` instead
+
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/index.rst b/src/common/doc/utilities/index.rst
index dadfb9f..1807182 100644
--- a/src/common/doc/utilities/index.rst
+++ b/src/common/doc/utilities/index.rst
@@ -20,7 +20,6 @@ Functions to help you develop a wrapper or a recipe
- :ref:`pgr_is_column_in_table` - to check only for the existance of the column.
- :ref:`pgr_point_to_id` -to insert/get the id of the inserted point in a vertices table.
- :ref:`pgr_quote_ident` - to quotes the input text to be used as an identifier in an SQL statement string.
- - :ref:`pgr_version` - to get pgRouting's version information.
- :ref:`pgr_versionless` - to compare two version numbers.
- :ref:`pgr_start_point` - to get the start point of a (multi)linestring.
- :ref:`pgr_end_point` - to get the end point of a (multi)linestring.
@@ -34,7 +33,6 @@ Functions to help you develop a wrapper or a recipe
pgr_isColumnInTable - to check only for the existance of the column.<is_column_in_table>
pgr_pointToId -to insert/get the id of the inserted point in a vertices table.<point_to_id>
pgr_quote_ident - to quotes the input text to be used as an identifier in an SQL statement string.<quote_ident>
- pgr_version - to get pgRouting's version information. <version>
pgr_versionless - to compare two version numbers<versionless>
pgr_startPoint - to get the start point of a (multi)linestring<start_point>
pgr_endPoint - to get the end point of a (multi)linestring<end_point>
diff --git a/src/common/doc/utilities/is_column_in_table.rst b/src/common/doc/utilities/is_column_in_table.rst
index e20fba8..982d546 100644
--- a/src/common/doc/utilities/is_column_in_table.rst
+++ b/src/common/doc/utilities/is_column_in_table.rst
@@ -13,7 +13,7 @@ pgr_isColumnInTable
===============================================================================
.. index::
- single: pgr_isColumnInTable(text,text)
+ single: pgr_isColumnInTable(text,text) -- deprecated
module: common
Name
@@ -23,6 +23,11 @@ Name
.. note:: This function is intended for the developer’s aid.
+.. warning:: This function is deprecated in 2.1
+ Use `_pgr_isColumnInTable` instead
+
+
+
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/is_column_indexed.rst b/src/common/doc/utilities/is_column_indexed.rst
index 2a74358..377c862 100644
--- a/src/common/doc/utilities/is_column_indexed.rst
+++ b/src/common/doc/utilities/is_column_indexed.rst
@@ -13,7 +13,7 @@ pgr_isColumnIndexed
===============================================================================
.. index::
- single: pgr_isColumnIndexed(text,text)
+ single: pgr_isColumnIndexed(text,text) -- deprecated
module: common
Name
@@ -23,6 +23,10 @@ Name
.. note:: This function is intended for the developer’s aid.
+.. warning:: This function is deprecated in 2.1
+ Use `_pgr_isColumnIndexed` instead
+
+
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/point_to_id.rst b/src/common/doc/utilities/point_to_id.rst
index 459f035..e64e908 100644
--- a/src/common/doc/utilities/point_to_id.rst
+++ b/src/common/doc/utilities/point_to_id.rst
@@ -13,17 +13,19 @@ pgr_pointToId
===============================================================================
.. index::
- single: pgr_pointToId(geometry,double precisioni,text,integer)
- module: common
+ single: pgr_pointToId(geometry,double precision,text,integer) -- deprecated
Name
-------------------------------------------------------------------------------
``pgr_pointToId`` — Inserts a point into a vertices table and returns the corresponig id.
-.. note::
+.. note:: This function is intended for the developer's aid.
+
+ Use :ref:`pgr_createTopology <pgr_create_topology>` or :ref:`pgr_createVerticesTable <pgr_create_vert_table>` instead.
+
+.. warning:: This function is deprecated in 2.1
- This function is intended for the developer's aid. Use :ref:`pgr_createTopology <pgr_create_topology>` or :ref:`pgr_createVerticesTable <pgr_create_vert_table>` instead.
Synopsis
diff --git a/src/common/doc/utilities/quote_ident.rst b/src/common/doc/utilities/quote_ident.rst
index abb06fa..b496b5e 100644
--- a/src/common/doc/utilities/quote_ident.rst
+++ b/src/common/doc/utilities/quote_ident.rst
@@ -13,8 +13,7 @@ pgr_quote_ident
===============================================================================
.. index::
- single: pgr_quote_ident(text)
- module: common
+ single: pgr_quote_ident(text) -- deprecated
Name
-------------------------------------------------------------------------------
@@ -23,6 +22,9 @@ Name
.. note:: This function is intended for the developer's aid.
+.. warning:: This function is deprecated in 2.1
+ Use `_pgr_quote_ident` instead
+
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/start_point.rst b/src/common/doc/utilities/start_point.rst
index 3524148..f23f53b 100644
--- a/src/common/doc/utilities/start_point.rst
+++ b/src/common/doc/utilities/start_point.rst
@@ -13,8 +13,7 @@ pgr_startPoint
===============================================================================
.. index::
- single: pgr_startPoint(geometry)
- module: common
+ single: pgr_startPoint(geometry) -- deprecated
Name
-------------------------------------------------------------------------------
@@ -23,6 +22,8 @@ Name
.. note:: This function is intended for the developer's aid.
+.. warning:: This function is deprecated in 2.1
+ Use `_pgr_startPoint` instead
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/version.rst b/src/common/doc/utilities/version.rst
index ce2b594..4fe143b 100644
--- a/src/common/doc/utilities/version.rst
+++ b/src/common/doc/utilities/version.rst
@@ -13,8 +13,7 @@ pgr_version
===============================================================================
.. index::
- single: pgr_version()
- module: utilities
+ single: version()
Name
-------------------------------------------------------------------------------
diff --git a/src/common/doc/utilities/versionless.rst b/src/common/doc/utilities/versionless.rst
index 4ae7100..1efb23e 100644
--- a/src/common/doc/utilities/versionless.rst
+++ b/src/common/doc/utilities/versionless.rst
@@ -13,8 +13,7 @@ pgr_versionless
===============================================================================
.. index::
- single: pgr_versionless(text,text)
- module: utilities
+ single: pgr_versionless(text,text) -- deprecated
Name
-------------------------------------------------------------------------------
@@ -23,6 +22,9 @@ Name
.. note:: This function is intended for the developer’s aid.
+.. warning:: This function is deprecated in 2.1.
+ Use `_pgr_versionless` instead
+
Synopsis
-------------------------------------------------------------------------------
diff --git a/src/common/sql/CMakeLists.txt b/src/common/sql/CMakeLists.txt
index 1bb5901..d9afacb 100644
--- a/src/common/sql/CMakeLists.txt
+++ b/src/common/sql/CMakeLists.txt
@@ -4,10 +4,18 @@ LIST(APPEND PACKAGE_SQL_FILES
${CMAKE_CURRENT_SOURCE_DIR}/pgrouting_utilities.sql
${CMAKE_CURRENT_SOURCE_DIR}/pgrouting_topology.sql
${CMAKE_CURRENT_SOURCE_DIR}/pgrouting_analytics.sql
- ${CMAKE_CURRENT_SOURCE_DIR}/pgrouting_network_check.sql
${CMAKE_CURRENT_SOURCE_DIR}/pgrouting_node_network.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/pgrouting_conversion_tools.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/pgrouting_dmatrix_tools.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/pgr_parameter_check.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/utilities_pgr.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/noUnderUtilities.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/create_vertices_table.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/createIndex.sql
+
+# this one is in the main CMakelist becuse types have to go first
+# ${CMAKE_CURRENT_SOURCE_DIR}/types.sql
)
# set in parent scope
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
-#MESSAGE("core/common/sql: ${PACKAGE_SQL_FILES}")
diff --git a/src/common/sql/pgrouting_network_check.sql b/src/common/sql/OBSOLETE/pgrouting_network_check.sql
similarity index 100%
rename from src/common/sql/pgrouting_network_check.sql
rename to src/common/sql/OBSOLETE/pgrouting_network_check.sql
diff --git a/src/common/sql/OBSOLETE/routing_tsp_wrappers.sql b/src/common/sql/OBSOLETE/routing_tsp_wrappers.sql
index 5423902..060c867 100644
--- a/src/common/sql/OBSOLETE/routing_tsp_wrappers.sql
+++ b/src/common/sql/OBSOLETE/routing_tsp_wrappers.sql
@@ -14,7 +14,7 @@
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-- BEGIN;
diff --git a/src/common/sql/createIndex.sql b/src/common/sql/createIndex.sql
new file mode 100644
index 0000000..c903ebf
--- /dev/null
+++ b/src/common/sql/createIndex.sql
@@ -0,0 +1,111 @@
+/*PGR
+ createIndex.sql
+
+ Copyright (c) 2015 Celia Virginia Vergara Castillo
+ vicky_vergara at hotmail.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.
+
+*/
+
+
+/************************************************************************
+.. function:: _pgr_createIndex(tab, col,indextype)
+ _pgr_createIndex(sname,tname,colname,indextypes)
+
+ if the column is not indexed it creates a 'gist' index otherwise a 'btree' index
+ Examples:
+ * select _pgr_createIndex('tab','col','btree');
+ * select _pgr_createIndex('myschema','mytable','col','gist');
+ * perform 'select _pgr_createIndex('||quote_literal('tab')||','||quote_literal('col')||','||quote_literal('btree'))' ;
+ * perform 'select _pgr_createIndex('||quote_literal('myschema')||','||quote_literal('mytable')||','||quote_literal('col')||','||quote_literal('gist')')' ;
+ Precondition:
+ sname.tname.colname is a valid column on table tname in schema sname
+ indext is the indexType btree or gist
+ Postcondition:
+ sname.tname.colname its indexed using the indextype
+
+
+ Author: Vicky Vergara <vicky_vergara at hotmail.com>>
+
+ HISTORY
+ Created: 2014/JUL/28
+************************************************************************/
+
+CREATE OR REPLACE FUNCTION _pgr_createIndex(
+ sname text, tname text, colname text, indext text,
+ IN reportErrs int default 1, IN fnName text default '_pgr_createIndex')
+RETURNS void AS
+$BODY$
+DECLARE
+ debuglevel text;
+ naming record;
+ tabname text;
+ query text;
+ msgKind int;
+BEGIN
+ msgKind = 0; -- debug_
+
+ execute 'show client_min_messages' into debuglevel;
+ tabname=_pgr_quote_ident(sname||'.'||tname);
+ perform _pgr_msg(msgKind, fnName, 'Checking ' || colname || ' column in ' || tabname || ' is indexed');
+ IF (_pgr_isColumnIndexed(sname,tname,colname, 0, fnName)) then
+ perform _pgr_msg(msgKind, fnName);
+ else
+ if indext = 'gist' then
+ query = 'create index '||_pgr_quote_ident(tname||'_'||colname||'_idx')||'
+ on '||tabname||' using gist('||quote_ident(colname)||')';
+ else
+ query = 'create index '||_pgr_quote_ident(tname||'_'||colname||'_idx')||'
+ on '||tabname||' using btree('||quote_ident(colname)||')';
+ end if;
+ perform _pgr_msg(msgKind, fnName, 'Adding index ' || tabname || '_' || colname || '_idx');
+ perform _pgr_msg(msgKind, fnName, ' Using ' || query);
+ set client_min_messages to warning;
+ BEGIN
+ execute query;
+ EXCEPTION WHEN others THEN
+ perform _pgr_onError( true, reportErrs, fnName,
+ 'Could not create index on:' || cname, SQLERRM);
+ END;
+ execute 'set client_min_messages to '|| debuglevel;
+ perform _pgr_msg(msgKind, fnName);
+ END IF;
+END;
+
+$BODY$
+ LANGUAGE plpgsql VOLATILE STRICT;
+
+
+CREATE OR REPLACE FUNCTION _pgr_createIndex(tabname text, colname text, indext text,
+ IN reportErrs int default 1, IN fnName text default '_pgr_createIndex')
+RETURNS void AS
+$BODY$
+DECLARE
+ naming record;
+ sname text;
+ tname text;
+
+BEGIN
+ select * from _pgr_getTableName(tabname, 2, fnName) into naming;
+ sname=naming.sname;
+ tname=naming.tname;
+ execute _pgr_createIndex(sname, tname, colname, indext, reportErrs, fnName);
+END;
+
+$BODY$
+ LANGUAGE plpgsql VOLATILE STRICT;
+
+
diff --git a/src/common/sql/create_vertices_table.sql b/src/common/sql/create_vertices_table.sql
new file mode 100644
index 0000000..937e8d1
--- /dev/null
+++ b/src/common/sql/create_vertices_table.sql
@@ -0,0 +1,232 @@
+/* PGR
+
+create_vertices_table.sql
+This function should not be used directly. Use assign_vertex_id instead
+Inserts a point into the vertices tablei "vname" with the srid "srid", and return an id
+of a new point or an existing point. Tolerance is the minimal distance
+between existing points and the new point to create a new point.
+
+Modified by: Vicky Vergara <vicky_vergara at hotmail,com>
+
+HISTORY
+Last changes: 2013-03-22
+2013-08-19: handling schemas
+*/
+
+
+
+/*
+.. function:: pgr_createVerticesTable(edge_table text, the_geom text, source text default 'source', target text default 'target')
+
+ Based on "source" and "target" columns creates the vetrices_pgr table for edge_table
+ Ignores rows where "source" or "target" have NULL values
+
+ Author: Vicky Vergara <vicky_vergara at hotmail,com>
+
+ HISTORY
+ Created 2013-08-19
+*/
+
+CREATE OR REPLACE FUNCTION pgr_createverticestable(
+ edge_table text,
+ the_geom text DEFAULT 'the_geom'::text,
+ source text DEFAULT 'source'::text,
+ target text DEFAULT 'target'::text,
+ rows_where text DEFAULT 'true'::text
+)
+ RETURNS text AS
+$BODY$
+DECLARE
+ naming record;
+ sridinfo record;
+ sname text;
+ tname text;
+ tabname text;
+ vname text;
+ vertname text;
+ gname text;
+ sourcename text;
+ targetname text;
+ query text;
+ ecnt integer;
+ srid integer;
+ sourcetype text;
+ targettype text;
+ sql text;
+ totcount integer;
+ i integer;
+ notincluded integer;
+ included integer;
+ debuglevel text;
+ dummyRec text;
+ fnName text;
+ err bool;
+
+
+BEGIN
+ fnName = 'pgr_createVerticesTable';
+ raise notice 'PROCESSING:';
+ raise notice 'pgr_createVerticesTable(''%'',''%'',''%'',''%'',''%'')',edge_table,the_geom,source,target,rows_where;
+ execute 'show client_min_messages' into debuglevel;
+
+ raise notice 'Performing checks, please wait .....';
+
+ RAISE DEBUG 'Checking % exists',edge_table;
+ execute 'select * from _pgr_getTableName('|| quote_literal(edge_table)
+ || ',2,' || quote_literal(fnName) ||' )' into naming;
+
+ sname=naming.sname;
+ tname=naming.tname;
+ tabname=sname||'.'||tname;
+ vname=tname||'_vertices_pgr';
+ vertname= sname||'.'||vname;
+ rows_where = ' AND ('||rows_where||')';
+ raise debug '--> Edge table exists: OK';
+
+ raise debug 'Checking column names';
+ select * into sourcename from _pgr_getColumnName(sname, tname,source,2, fnName);
+ select * into targetname from _pgr_getColumnName(sname, tname,target,2, fnName);
+ select * into gname from _pgr_getColumnName(sname, tname,the_geom,2, fnName);
+
+
+ err = sourcename in (targetname,gname) or targetname=gname;
+ perform _pgr_onError(err, 2, fnName,
+ 'Two columns share the same name', 'Parameter names for the_geom,source and target must be different');
+ raise debug '--> Column names: OK';
+
+ raise debug 'Checking column types in edge table';
+ select * into sourcetype from _pgr_getColumnType(sname,tname,sourcename,1, fnName);
+ select * into targettype from _pgr_getColumnType(sname,tname,targetname,1, fnName);
+
+
+ err = sourcetype not in('integer','smallint','bigint');
+ perform _pgr_onError(err, 2, fnName,
+ 'Wrong type of Column source: '|| sourcename, ' Expected type of '|| sourcename || ' is integer,smallint or bigint but '||sourcetype||' was found');
+
+ err = targettype not in('integer','smallint','bigint');
+ perform _pgr_onError(err, 2, fnName,
+ 'Wrong type of Column target: '|| targetname, ' Expected type of '|| targetname || ' is integer,smallint or biginti but '||targettype||' was found');
+
+ raise debug '-->Column types:OK';
+
+ raise debug 'Checking SRID of geometry column';
+ query= 'SELECT ST_SRID(' || quote_ident(gname) || ') as srid '
+ || ' FROM ' || _pgr_quote_ident(tabname)
+ || ' WHERE ' || quote_ident(gname)
+ || ' IS NOT NULL LIMIT 1';
+ raise debug '%',query;
+ EXECUTE query INTO sridinfo;
+
+ err = sridinfo IS NULL OR sridinfo.srid IS NULL;
+ perform _pgr_onError(err, 2, fnName,
+ 'Can not determine the srid of the geometry '|| gname ||' in table '||tabname, 'Check the geometry of column '||gname);
+ srid := sridinfo.srid;
+ raise DEBUG ' --> OK';
+
+ raise debug 'Checking and creating Indices';
+ perform _pgr_createIndex(sname, tname , sourcename , 'btree'::text);
+ perform _pgr_createIndex(sname, tname , targetname , 'btree'::text);
+ perform _pgr_createIndex(sname, tname , gname , 'gist'::text);
+ raise DEBUG '-->Check and create indices: OK';
+
+ gname=quote_ident(gname);
+ sourcename=quote_ident(sourcename);
+ targetname=quote_ident(targetname);
+
+
+ BEGIN
+ raise debug 'Checking Condition';
+ -- issue #193 & issue #210 & #213
+ -- this sql is for trying out the where clause
+ -- the select * is to avoid any colum name conflicts
+ -- limit 1, just try on first record
+ -- if the where clasuse is ill formed it will be catched in the exception
+ sql = 'select * from '||_pgr_quote_ident(tabname)||' WHERE true'||rows_where ||' limit 1';
+ EXECUTE sql into dummyRec;
+ -- end
+
+ -- if above where clasue works this one should work
+ -- any error will be catched by the exception also
+ sql = 'select count(*) from '||_pgr_quote_ident(tabname)||' WHERE (' || gname || ' IS NULL or '||
+ sourcename||' is null or '||targetname||' is null)=true '||rows_where;
+ raise debug '%',sql;
+ EXECUTE SQL into notincluded;
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Got %', SQLERRM; -- issue 210,211
+ RAISE NOTICE 'ERROR: Condition is not correct, please execute the following query to test your condition';
+ RAISE NOTICE '%',sql;
+ RETURN 'FAIL';
+ END;
+
+
+
+
+ BEGIN
+ raise DEBUG 'initializing %',vertname;
+ execute 'select * from _pgr_getTableName('||quote_literal(vertname)||',0)' into naming;
+ IF sname=naming.sname AND vname=naming.tname THEN
+ execute 'TRUNCATE TABLE '||_pgr_quote_ident(vertname)||' RESTART IDENTITY';
+ execute 'SELECT DROPGEOMETRYCOLUMN('||quote_literal(sname)||','||quote_literal(vname)||','||quote_literal('the_geom')||')';
+ ELSE
+ set client_min_messages to warning;
+ execute 'CREATE TABLE '||_pgr_quote_ident(vertname)||' (id bigserial PRIMARY KEY,cnt integer,chk integer,ein integer,eout integer)';
+ END IF;
+ execute 'select addGeometryColumn('||quote_literal(sname)||','||quote_literal(vname)||','||
+ quote_literal('the_geom')||','|| srid||', '||quote_literal('POINT')||', 2)';
+ execute 'CREATE INDEX '||quote_ident(vname||'_the_geom_idx')||' ON '||_pgr_quote_ident(vertname)||' USING GIST (the_geom)';
+ execute 'set client_min_messages to '|| debuglevel;
+ raise DEBUG ' ------>OK';
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Got %', SQLERRM; -- issue 210,211
+ RAISE NOTICE 'ERROR: Initializing vertex table';
+ RAISE NOTICE '%',sql;
+ RETURN 'FAIL';
+ END;
+
+ BEGIN
+ raise notice 'Populating %, please wait...',vertname;
+ sql= 'with
+ lines as ((select distinct '||sourcename||' as id, _pgr_startpoint(st_linemerge('||gname||')) as the_geom from '||_pgr_quote_ident(tabname)||
+ ' where ('|| gname || ' IS NULL
+ or '||sourcename||' is null
+ or '||targetname||' is null)=false
+ '||rows_where||')
+ union (select distinct '||targetname||' as id,_pgr_endpoint(st_linemerge('||gname||')) as the_geom from '||_pgr_quote_ident(tabname)||
+ ' where ('|| gname || ' IS NULL
+ or '||sourcename||' is null
+ or '||targetname||' is null)=false
+ '||rows_where||'))
+ ,numberedLines as (select row_number() OVER (ORDER BY id) AS i,* from lines )
+ ,maxid as (select id,max(i) as maxi from numberedLines group by id)
+ insert into '||_pgr_quote_ident(vertname)||'(id,the_geom) (select id,the_geom from numberedLines join maxid using(id) where i=maxi order by id)';
+ RAISE debug '%',sql;
+ execute sql;
+ GET DIAGNOSTICS totcount = ROW_COUNT;
+
+ sql = 'select count(*) from '||_pgr_quote_ident(tabname)||' a, '||_pgr_quote_ident(vertname)||' b
+ where '||sourcename||'=b.id and '|| targetname||' in (select id from '||_pgr_quote_ident(vertname)||')';
+ RAISE debug '%',sql;
+ execute sql into included;
+
+
+
+ execute 'select max(id) from '||_pgr_quote_ident(vertname) into ecnt;
+ execute 'SELECT setval('||quote_literal(vertname||'_id_seq')||','||coalesce(ecnt,1)||' , false)';
+ raise notice ' -----> VERTICES TABLE CREATED WITH % VERTICES', totcount;
+ raise notice ' FOR % EDGES', included+notincluded;
+ RAISE NOTICE ' Edges with NULL geometry,source or target: %',notincluded;
+ RAISE NOTICE ' Edges processed: %',included;
+ Raise notice 'Vertices table for table % is: %',_pgr_quote_ident(tabname),_pgr_quote_ident(vertname);
+ raise notice '----------------------------------------------';
+ END;
+
+ RETURN 'OK';
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Unexpected error %', SQLERRM; -- issue 210,211
+ RETURN 'FAIL';
+END;
+$BODY$
+ LANGUAGE plpgsql VOLATILE STRICT;
+
+COMMENT ON FUNCTION pgr_createVerticesTable(text,text,text,text,text)
+IS 'args: edge_table, the_geom:=''the_geom'',source:=''source'', target:=''target'' rows_where:=''true'' - creates a vertices table based on the source and target identifiers for selected rows';
diff --git a/src/common/sql/noUnderUtilities.sql b/src/common/sql/noUnderUtilities.sql
new file mode 100644
index 0000000..f249284
--- /dev/null
+++ b/src/common/sql/noUnderUtilities.sql
@@ -0,0 +1,93 @@
+-- -------------------------------------------------------------------
+-- pgrouting_utilities.sql
+-- AuthorL Stephen Woodbridge <woodbri at imaptools.com>
+-- Copyright 2013 Stephen Woodbridge
+-- This file is release unde an MIT-X license.
+-- -------------------------------------------------------------------
+
+
+CREATE OR REPLACE FUNCTION pgr_getTableName(IN tab text,OUT sname text,OUT tname text)
+RETURNS RECORD AS
+$BODY$
+BEGIN
+ raise notice 'pgr_getTableName: This function will no longer be soported';
+ select * from _pgr_getTableName(tab, 0, 'pgr_getTableName') into sname,tname;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+CREATE OR REPLACE FUNCTION pgr_getColumnName(tab text, col text)
+RETURNS text AS
+$BODY$
+BEGIN
+ raise notice 'pgr_getColumnName: This function will no longer be soported';
+ return _pgr_getColumnName(tab,col, 0, 'pgr_getColumnName');
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+CREATE OR REPLACE FUNCTION pgr_isColumnInTable(tab text, col text)
+RETURNS boolean AS
+$BODY$
+DECLARE
+ cname text;
+BEGIN
+ raise notice 'pgr_isColumnInTable: This function will no longer be soported';
+ select * from _pgr_getColumnName(tab,col,0, 'pgr_isColumnInTable') into cname;
+ return cname IS not NULL;
+END;
+$BODY$
+ LANGUAGE plpgsql VOLATILE STRICT;
+
+CREATE OR REPLACE FUNCTION pgr_isColumnIndexed(tab text, col text)
+RETURNS boolean AS
+$BODY$
+BEGIN
+ raise notice 'pgr_isColumnIndexed: This function will no longer be soported';
+ return _pgr_isColumnIndexed(tab,col);
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+
+create or replace function pgr_quote_ident(idname text)
+returns text as
+$BODY$
+BEGIN
+ raise notice 'pgr_isColumnInTable: This function will no longer be soported';
+ return _pgr_quote_ident(idname);
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+CREATE OR REPLACE FUNCTION pgr_versionless(v1 text, v2 text)
+RETURNS boolean AS
+$BODY$
+BEGIN
+ raise notice 'pgr_versionless: This function will no longer be soported';
+ return _pgr_versionless(v1,v2);
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+create or replace function pgr_startPoint(g geometry)
+ returns geometry as
+$body$
+BEGIN
+ raise notice 'pgr_startPoint: This function will no longer be soported';
+ return _pgr_startPoint(g);
+END;
+$body$
+language plpgsql IMMUTABLE;
+
+
+
+create or replace function pgr_endPoint(g geometry)
+ returns geometry as
+$body$
+BEGIN
+ raise notice 'pgr_endPoint: This function will no longer be soported';
+ return _pgr_endPoint(g);
+END;
+$body$
+language plpgsql IMMUTABLE;
diff --git a/src/common/sql/pgr_parameter_check.sql b/src/common/sql/pgr_parameter_check.sql
new file mode 100644
index 0000000..283f665
--- /dev/null
+++ b/src/common/sql/pgr_parameter_check.sql
@@ -0,0 +1,111 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+-----------------------------------------------------------------------
+-- Function _pgr_parameter_check
+-- Check's the parameters type of the sql input
+-----------------------------------------------------------------------
+
+-- change the default to true when all the functions will use the bigint
+CREATE OR REPLACE FUNCTION _pgr_parameter_check(fn text, sql text, big boolean default false)
+ RETURNS bool AS
+ $BODY$
+
+ DECLARE
+ rec record;
+ rec1 record;
+ has_rcost boolean;
+ safesql text;
+ BEGIN
+ -- checking query is executable
+ BEGIN
+ safesql = 'select * from ('||sql||' ) AS __a__ limit 1';
+ execute safesql into rec;
+ EXCEPTION
+ WHEN OTHERS THEN
+ RAISE EXCEPTION 'Could not execute query please verify syntax of: '
+ USING HINT = sql;
+ END;
+
+ -- checking the fixed columns and data types of the integers
+ IF fn IN ('driving', 'dijkstra', 'ksp') THEN
+ BEGIN
+ execute 'select id,source,target,cost from ('||safesql||') as __b__' into rec;
+ EXCEPTION
+ WHEN OTHERS THEN
+ RAISE EXCEPTION 'An expected column was not found in the query'
+ USING HINT = 'Please veryfy the column names: id, source, target, cost';
+ END;
+ END IF;
+
+ IF fn IN ('driving', 'dijkstra', 'ksp') THEN
+ execute 'select pg_typeof(id)::text as id_type, pg_typeof(source)::text as source_type, pg_typeof(target)::text as target_type, pg_typeof(cost)::text as cost_type'
+ || ' from ('||safesql||') AS __b__ ' into rec;
+ if (big) then
+ if not (rec.id_type in ('bigint'::text, 'integer'::text, 'smallint'::text))
+ OR not (rec.source_type in ('bigint'::text, 'integer'::text, 'smallint'::text))
+ OR not (rec.target_type in ('bigint'::text, 'integer'::text, 'smallint'::text))
+ OR not (rec.cost_type in ('bigint'::text, 'integer'::text, 'smallint'::text, 'double precision'::text, 'real'::text)) then
+ RAISE EXCEPTION 'Illegar type found in query.';
+ end if;
+ else -- Version 2.0.0 is more restrictive
+ if not( (rec.id_type in ('integer'::text))
+ and (rec.source_type in ('integer'::text))
+ and (rec.target_type in ('integer'::text))
+ and (rec.cost_type = 'double precision'::text)) then
+ RAISE EXCEPTION 'Support for id,source,target columns only of type: integer. Support for Cost: double precision';
+ end if;
+ end if;
+ END IF;
+
+
+ -- Checking the data types of the optional reverse_cost";
+ has_rcost := false;
+ IF fn IN ('driving', 'dijkstra', 'ksp') THEN
+ BEGIN
+ execute 'select reverse_cost, pg_typeof(reverse_cost)::text as rev_type from ('||safesql||' ) AS __b__ limit 1 ' into rec1;
+ has_rcost := true;
+ EXCEPTION
+ WHEN OTHERS THEN
+ has_rcost = false;
+ return has_rcost;
+ END;
+ if (has_rcost) then
+ IF (big) then
+ IF not (rec1.rev_type in ('bigint'::text, 'integer'::text, 'smallint'::text, 'double precision'::text, 'real'::text)) then
+ RAISE EXCEPTION 'Illegar type in optional parameter reverse_cost.';
+ END IF;
+ ELSE -- Version 2.0.0 is more restrictive
+ IF (rec1.rev_type != 'double precision') then
+ RAISE EXCEPTION 'Illegal type in optimal parameter reverse_cost, expected: double precision';
+ END IF;
+ END IF;
+ end if;
+ return true;
+ END IF;
+ -- just for keeps
+ return true;
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 1;
+
+
diff --git a/src/common/sql/pgrouting-types.sql b/src/common/sql/pgrouting-types.sql
index 9bf85dc..d6a4f65 100644
--- a/src/common/sql/pgrouting-types.sql
+++ b/src/common/sql/pgrouting-types.sql
@@ -2,6 +2,8 @@
-- pgRouting 2.0 types
+
+
CREATE TYPE pgr_costResult AS
(
seq integer,
@@ -10,6 +12,8 @@ CREATE TYPE pgr_costResult AS
cost float8
);
+
+
CREATE TYPE pgr_costResult3 AS
(
seq integer,
diff --git a/src/common/sql/pgrouting_analytics.sql b/src/common/sql/pgrouting_analytics.sql
index 320ea55..5d9310e 100644
--- a/src/common/sql/pgrouting_analytics.sql
+++ b/src/common/sql/pgrouting_analytics.sql
@@ -37,17 +37,17 @@ HISOTRY
:Modified: 2013/08/20 by Vicky Vergara <vicky_vergara at hotmail.com>
Makes more checks:
- checks table edge_tab exists in the schema
+ checks table edge_tab exists in the schema
checks source and target columns exist in edge_tab
checks that source and target are completely populated i.e. do not have NULL values
checks table edge_tabVertices exist in the appropiate schema
if not, it creates it and populates it
- checks 'cnt','chk' columns exist in edge_tabVertices
+ checks 'cnt','chk' columns exist in edge_tabVertices
if not, it creates them
- checks if 'id' column of edge_tabVertices is indexed
+ checks if 'id' column of edge_tabVertices is indexed
if not, it creates the index
- checks if 'source','target',the_geom columns of edge_tab are indexed
- if not, it creates their index
+ checks if 'source','target',the_geom columns of edge_tab are indexed
+ if not, it creates their index
populates cnt in edge_tabVertices <--- changed the way it was processed, because on large tables took to long.
For sure I am wrong doing this, but it gave me the same result as the original.
populates chk <--- added a notice for big tables, because it takes time
@@ -76,8 +76,6 @@ DECLARE
targettype text;
geotype text;
gname text;
- cntname text;
- chkname text;
tabName text;
flag boolean ;
query text;
@@ -95,298 +93,242 @@ DECLARE
BEGIN
- raise notice 'PROCESSING:';
+ raise notice 'PROCESSING:';
raise notice 'pgr_analyzeGraph(''%'',%,''%'',''%'',''%'',''%'',''%'')',edge_table,tolerance,the_geom,id,source,target,rows_where;
- raise NOTICE 'Performing checks, pelase wait...';
+ raise notice 'Performing checks, please wait ...';
execute 'show client_min_messages' into debuglevel;
BEGIN
- RAISE DEBUG 'Cheking % exists',edge_table;
- execute 'select * from pgr_getTableName('||quote_literal(edge_table)||')' into naming;
+ RAISE DEBUG 'Checking % exists',edge_table;
+ execute 'select * from _pgr_getTableName('||quote_literal(edge_table)||',2)' into naming;
sname=naming.sname;
tname=naming.tname;
- IF sname IS NULL OR tname IS NULL THEN
- RAISE NOTICE '-------> % not found',edge_table;
- RETURN 'FAIL';
- ELSE
- RAISE DEBUG ' -----> OK';
- END IF;
-
tabname=sname||'.'||tname;
vname=tname||'_vertices_pgr';
vertname= sname||'.'||vname;
- rows_where = ' AND ('||rows_where||')';
+ rows_where = ' AND ('||rows_where||')';
+ raise DEBUG ' --> OK';
+/* EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the table name';
+ RETURN 'FAIL';
+*/
END;
- BEGIN
- raise DEBUG 'Checking id column "%" columns in % ',id,tabname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(the_geom)||')' INTO gname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(id)||')' INTO idname;
- IF idname is NULL then
- raise notice 'ERROR: id column "%" not found in %',id,tabname;
+ BEGIN
+ raise debug 'Checking Vertices table';
+ execute 'select * from _pgr_checkVertTab('||quote_literal(vertname) ||', ''{"id","cnt","chk"}''::text[])' into naming;
+ execute 'UPDATE '||_pgr_quote_ident(vertname)||' SET cnt=0 ,chk=0';
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the vertices table';
RETURN 'FAIL';
- END IF;
- raise DEBUG 'Checking geometry column "%" column in % ',the_geom,tabname;
- IF gname is not NULL then
- BEGIN
- raise DEBUG 'Checking the SRID of the geometry "%"', gname;
- EXECUTE 'SELECT ST_SRID(' || quote_ident(gname) || ') as srid '
- || ' FROM ' || pgr_quote_ident(tabname)
- || ' WHERE ' || quote_ident(gname)
- || ' IS NOT NULL LIMIT 1'
- INTO sridinfo;
-
- IF sridinfo IS NULL OR sridinfo.srid IS NULL THEN
- RAISE NOTICE 'ERROR: Can not determine the srid of the geometry "%" in table %', the_geom,tabname;
- RETURN 'FAIL';
- END IF;
- srid := sridinfo.srid;
- raise DEBUG ' -----> SRID found %',srid;
- EXCEPTION WHEN OTHERS THEN
- RAISE NOTICE 'ERROR: Can not determine the srid of the geometry "%" in table %', the_geom,tabname;
- RETURN 'FAIL';
- END;
- ELSE
- raise notice 'ERROR: Geometry column "%" not found in %',the_geom,tabname;
- RETURN 'FAIL';
- END IF;
END;
- BEGIN
- raise DEBUG 'Checking source column "%" and target column "%" in % ',source,target,tabname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(source)||')' INTO sourcename;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(target)||')' INTO targetname;
- IF sourcename is not NULL and targetname is not NULL then
- --check that the are integer
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(sourcename) into sourcetype;
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(targetname) into targettype;
- IF sourcetype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: source column "%" is not of integer type',sourcename;
- RETURN 'FAIL';
- END IF;
- IF targettype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: target column "%" is not of integer type',targetname;
- RETURN 'FAIL';
- END IF;
- raise DEBUG ' ------>OK ';
- END IF;
- IF sourcename is NULL THEN
- raise notice 'ERROR: source column "%" not found in %',source,tabname;
- RETURN 'FAIL';
- END IF;
- IF targetname is NULL THEN
- raise notice 'ERROR: target column "%" not found in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- IF sourcename=targetname THEN
- raise notice 'ERROR: source and target columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- IF sourcename=idname THEN
- raise notice 'ERROR: source and id columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- IF targetname=idname THEN
- raise notice 'ERROR: target and id columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
-
+
+ BEGIN
+ raise debug 'Checking column names in edge table';
+ select * into idname from _pgr_getColumnName(sname, tname,id,2);
+ select * into sourcename from _pgr_getColumnName(sname, tname,source,2);
+ select * into targetname from _pgr_getColumnName(sname, tname,target,2);
+ select * into gname from _pgr_getColumnName(sname, tname,the_geom,2);
+
+
+ perform _pgr_onError( sourcename in (targetname,idname,gname) or targetname in (idname,gname) or idname=gname, 2,
+ 'pgr_analyzeGraph', 'Two columns share the same name', 'Parameter names for id,the_geom,source and target must be different',
+ 'Column names are OK');
+
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the column names';
+ RETURN 'FAIL';
END;
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',sourcename,tabname;
- if (pgr_isColumnIndexed(tabname,sourcename)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding index "%_%_idx".',tabname,sourcename;
- execute 'create index '||tname||'_'||sourcename||'_idx on '||tabname||' using btree('||quote_ident(sourcename)||')';
- END IF;
- END;
+ BEGIN
+ raise debug 'Checking column types in edge table';
+ select * into sourcetype from _pgr_getColumnType(sname,tname,sourcename,1);
+ select * into targettype from _pgr_getColumnType(sname,tname,targetname,1);
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',targetname,tabname;
- if (pgr_isColumnIndexed(tabname,targetname)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding index "%_%_idx".',tabname,targetname;
- execute 'create index '||tname||'_'||targetname||'_idx on '||tabname||' using btree('||quote_ident(targetname)||')';
- END IF;
+ perform _pgr_onError(sourcetype not in('integer','smallint','bigint') , 2,
+ 'pgr_analyzeGraph', 'Wrong type of Column '|| sourcename, ' Expected type of '|| sourcename || ' is integer,smallint or bigint but '||sourcetype||' was found',
+ 'Type of Column '|| sourcename || ' is ' || sourcetype);
+
+ perform _pgr_onError(targettype not in('integer','smallint','bigint') , 2,
+ 'pgr_analyzeGraph', 'Wrong type of Column '|| targetname, ' Expected type of '|| targetname || ' is integer,smallint or biginti but '||targettype||' was found',
+ 'Type of Column '|| targetname || ' is ' || targettype);
+
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the column types';
+ RETURN 'FAIL';
+ END;
+
+ BEGIN
+ raise debug 'Checking SRID of geometry column';
+ query= 'SELECT ST_SRID(' || quote_ident(gname) || ') as srid '
+ || ' FROM ' || _pgr_quote_ident(tabname)
+ || ' WHERE ' || quote_ident(gname)
+ || ' IS NOT NULL LIMIT 1';
+ EXECUTE QUERY INTO sridinfo;
+
+ perform _pgr_onError( sridinfo IS NULL OR sridinfo.srid IS NULL,2,
+ 'Can not determine the srid of the geometry '|| gname ||' in table '||tabname, 'Check the geometry of column '||gname,
+ 'SRID of '||gname||' is '||sridinfo.srid);
+
+ IF sridinfo IS NULL OR sridinfo.srid IS NULL THEN
+ RAISE NOTICE ' Can not determine the srid of the geometry "%" in table %', the_geom,tabname;
+ RETURN 'FAIL';
+ END IF;
+ srid := sridinfo.srid;
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Got %', SQLERRM;--issue 210,211,213
+ RAISE NOTICE 'ERROR: something went wrong when checking for SRID of % in table %', the_geom,tabname;
+ RETURN 'FAIL';
END;
+
BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',gname,tabname;
- if (pgr_iscolumnindexed(tabname,gname)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding unique index "%_%_gidx".',tabname,gname;
- execute 'CREATE INDEX '
- || quote_ident(tname || '_' || gname || '_gidx' )
- || ' ON ' || tabname
- || ' USING gist (' || quote_ident(gname) || ')';
- END IF;
- END;
+ raise debug 'Checking indices in edge table';
+ perform _pgr_createIndex(tabname , idname , 'btree');
+ perform _pgr_createIndex(tabname , sourcename , 'btree');
+ perform _pgr_createIndex(tabname , targetname , 'btree');
+ perform _pgr_createIndex(tabname , gname , 'gist');
-
gname=quote_ident(gname);
sourcename=quote_ident(sourcename);
targetname=quote_ident(targetname);
idname=quote_ident(idname);
-
- BEGIN
- raise DEBUG 'Checking table %.% exists ',sname ,vname;
- execute 'select * from pgr_getTableName('||quote_literal(vertname)||')' into naming;
- IF sname=naming.sname AND vname=naming.tname THEN
- raise DEBUG ' ------>OK';
- ELSE
- raise notice ' --->Table %.% does not exists',sname ,vname;
- raise notice ' --->Please create %.% using pgr_createTopology() or pgr_createVerticesTable()',sname ,vname;
- return 'FAIL';
- END IF;
- END;
-
-
- BEGIN
- RAISE DEBUG 'Cheking for "cnt" and "chk" column in %',vertname;
- execute 'select pgr_getcolumnName('||quote_literal(vertname)||','||quote_literal('cnt')||')' into cntname;
- execute 'select pgr_getcolumnName('||quote_literal(vertname)||','||quote_literal('chk')||')' into chkname;
- if cntname is not null and chkname is not null then
- cntname=quote_ident(cntname);
- RAISE DEBUG ' ------>OK';
- else if cntname is not null then
- RAISE NOTICE ' ------>Adding "cnt" column in %',vertname;
- set client_min_messages to warning;
- execute 'ALTER TABLE '||pgr_quote_ident(vertname)||' ADD COLUMN cnt integer';
- execute 'set client_min_messages to '|| debuglevel;
- cntname=quote_ident('cnt');
- end if;
- if chkname is not null then
- RAISE DEBUG ' ------>Adding "chk" column in %',vertname;
- set client_min_messages to warning;
- execute 'ALTER TABLE '||pgr_quote_ident(vertname)||' ADD COLUMN chk integer';
- execute 'set client_min_messages to '|| debuglevel;
- cntname=quote_ident('chk');
- end if;
- END IF;
- execute 'UPDATE '||pgr_quote_ident(vertname)||' SET '||cntname||'=0 ,'||chkname||'=0';
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking indices';
+ RETURN 'FAIL';
END;
BEGIN
- RAISE DEBUG 'Cheking "id" column in % is indexed',vertname;
- if (pgr_iscolumnindexed(vertname,'id')) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding unique index "%_vertices_id_idx".',vname;
- set client_min_messages to warning;
- execute 'create unique index '||vname||'_id_idx on '||pgr_quote_ident(vertname)||' using btree(id)';
- execute 'set client_min_messages to '|| debuglevel;
- END IF;
- END;
-
- BEGIN
- query='select count(*) from '||pgr_quote_ident(tabname)||' where true '||rows_where;
+ query='select count(*) from '||_pgr_quote_ident(tabname)||' where true '||rows_where;
EXECUTE query into ecnt;
- EXCEPTION WHEN OTHERS THEN
- BEGIN
- RAISE NOTICE 'ERROR: Condition is not correct. Please execute the following query to test your condition';
+ raise DEBUG '-->Rows Where condition: OK';
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Got %', SQLERRM; --issue 210,211,213
+ RAISE NOTICE 'ERROR: Condition is not correct. Please execute the following query to test your condition';
RAISE NOTICE '%',query;
- RETURN 'FAIL';
- END;
- END;
+ RETURN 'FAIL';
+ END;
- selectionquery ='with
- selectedRows as( (select '||sourcename||' as id from '||pgr_quote_ident(tabname)||' where true '||rows_where||')
+ selectionquery ='with
+ selectedRows as( (select '||sourcename||' as id from '||_pgr_quote_ident(tabname)||' where true '||rows_where||')
union
- (select '||targetname||' as id from '||pgr_quote_ident(tabname)||' where true '||rows_where||'))';
-
+ (select '||targetname||' as id from '||_pgr_quote_ident(tabname)||' where true '||rows_where||'))';
+
+
-
BEGIN
RAISE NOTICE 'Analyzing for dead ends. Please wait...';
- query= 'with countingsource as (select a.'||sourcename||' as id,count(*) as cnts
- from (select * from '||pgr_quote_ident(tabname)||' where true '||rows_where||' ) a group by a.'||sourcename||')
- ,countingtarget as (select a.'||targetname||' as id,count(*) as cntt
- from (select * from '||pgr_quote_ident(tabname)||' where true '||rows_where||' ) a group by a.'||targetname||')
+ query= 'with countingsource as (select a.'||sourcename||' as id,count(*) as cnts
+ from (select * from '||_pgr_quote_ident(tabname)||' where true '||rows_where||' ) a group by a.'||sourcename||')
+ ,countingtarget as (select a.'||targetname||' as id,count(*) as cntt
+ from (select * from '||_pgr_quote_ident(tabname)||' where true '||rows_where||' ) a group by a.'||targetname||')
,totalcount as (select id,case when cnts is null and cntt is null then 0
- when cnts is null then cntt
+ when cnts is null then cntt
when cntt is null then cnts
- else cnts+cntt end as totcnt
- from ('||pgr_quote_ident(vertname)||' as a left
+ else cnts+cntt end as totcnt
+ from ('||_pgr_quote_ident(vertname)||' as a left
join countingsource as t using(id) ) left join countingtarget using(id))
- update '||pgr_quote_ident(vertname)||' as a set cnt=totcnt from totalcount as b where a.id=b.id';
- raise debug '%',query;
- execute query;
- query=selectionquery||'
- SELECT count(*) FROM '||pgr_quote_ident(vertname)||' WHERE cnt=1 and id in (select id from selectedRows)';
- raise debug '%',query;
- execute query INTO numdeadends;
+ update '||_pgr_quote_ident(vertname)||' as a set cnt=totcnt from totalcount as b where a.id=b.id';
+ raise debug '%',query;
+ execute query;
+ query=selectionquery||'
+ SELECT count(*) FROM '||_pgr_quote_ident(vertname)||' WHERE cnt=1 and id in (select id from selectedRows)';
+ raise debug '%',query;
+ execute query INTO numdeadends;
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'Got %', SQLERRM; --issue 210,211,213
+ RAISE NOTICE 'ERROR: something went wrong when analizing for dead ends';
+ RETURN 'FAIL';
END;
BEGIN
RAISE NOTICE 'Analyzing for gaps. Please wait...';
- query = 'with
- buffer as (select id,st_buffer(the_geom,'||tolerance||') as buff from '||pgr_quote_ident(vertname)||' where cnt=1)
- ,veryclose as (select b.id,st_crosses(a.'||gname||',b.buff) as flag
- from (select * from '||pgr_quote_ident(tabname)||' where true '||rows_where||' ) as a
- join buffer as b on (a.'||gname||'&&b.buff)
+ query = 'with
+ buffer as (select id,st_buffer(the_geom,'||tolerance||') as buff from '||_pgr_quote_ident(vertname)||' where cnt=1)
+ ,veryclose as (select b.id,st_crosses(a.'||gname||',b.buff) as flag
+ from (select * from '||_pgr_quote_ident(tabname)||' where true '||rows_where||' ) as a
+ join buffer as b on (a.'||gname||'&&b.buff)
where '||sourcename||'!=b.id and '||targetname||'!=b.id )
- update '||pgr_quote_ident(vertname)||' set chk=1 where id in (select distinct id from veryclose where flag=true)';
- raise debug '%' ,query;
- execute query;
- GET DIAGNOSTICS numgaps= ROW_COUNT;
- END;
-
+ update '||_pgr_quote_ident(vertname)||' set chk=1 where id in (select distinct id from veryclose where flag=true)';
+ raise debug '%' ,query;
+ execute query;
+ GET DIAGNOSTICS numgaps= ROW_COUNT;
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong when Analyzing for gaps';
+ RETURN 'FAIL';
+ END;
+
BEGIN
- RAISE NOTICE 'Analyzing for isolated edges. Please wait...';
- query=selectionquery|| ' SELECT count(*) FROM (select * from '||pgr_quote_ident(tabname)||' where true '||rows_where||' ) as a,
- '||pgr_quote_ident(vertname)||' as b,
- '||pgr_quote_ident(vertname)||' as c
- WHERE b.id in (select id from selectedRows) and a.'||sourcename||' =b.id
- AND b.cnt=1 AND a.'||targetname||' =c.id
+ RAISE NOTICE 'Analyzing for isolated edges. Please wait...';
+ query=selectionquery|| ' SELECT count(*) FROM (select * from '||_pgr_quote_ident(tabname)||' where true '||rows_where||' ) as a,
+ '||_pgr_quote_ident(vertname)||' as b,
+ '||_pgr_quote_ident(vertname)||' as c
+ WHERE b.id in (select id from selectedRows) and a.'||sourcename||' =b.id
+ AND b.cnt=1 AND a.'||targetname||' =c.id
AND c.cnt=1';
- raise debug '%' ,query;
- execute query INTO NumIsolated;
+ raise debug '%' ,query;
+ execute query INTO NumIsolated;
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong when Analyzing for isolated edges';
+ RETURN 'FAIL';
END;
BEGIN
- RAISE NOTICE 'Analyzing for ring geometries. Please wait...';
- execute 'SELECT geometrytype('||gname||') FROM '||pgr_quote_ident(tabname) limit 1 into geotype;
- IF (geotype='MULTILINESTRING') THEN
- query ='SELECT count(*) FROM '||pgr_quote_ident(tabname)||'
- WHERE true '||rows_where||' and st_isRing(st_linemerge('||gname||'))';
- raise debug '%' ,query;
- execute query INTO numRings;
- ELSE query ='SELECT count(*) FROM '||pgr_quote_ident(tabname)||'
- WHERE true '||rows_where||' and st_isRing('||gname||')';
- raise debug '%' ,query;
- execute query INTO numRings;
- END IF;
+ RAISE NOTICE 'Analyzing for ring geometries. Please wait...';
+ execute 'SELECT geometrytype('||gname||') FROM '||_pgr_quote_ident(tabname) limit 1 into geotype;
+ IF (geotype='MULTILINESTRING') THEN
+ query ='SELECT count(*) FROM '||_pgr_quote_ident(tabname)||'
+ WHERE true '||rows_where||' and st_isRing(st_linemerge('||gname||'))';
+ raise debug '%' ,query;
+ execute query INTO numRings;
+ ELSE query ='SELECT count(*) FROM '||_pgr_quote_ident(tabname)||'
+ WHERE true '||rows_where||' and st_isRing('||gname||')';
+ raise debug '%' ,query;
+ execute query INTO numRings;
+ END IF;
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong when Analyzing for ring geometries';
+ RETURN 'FAIL';
END;
BEGIN
- RAISE NOTICE 'Analyzing for intersections. Please wait...';
- query = 'select count(*) from (select distinct case when a.'||idname||' < b.'||idname||' then a.'||idname||'
- else b.'||idname||' end,
- case when a.'||idname||' < b.'||idname||' then b.'||idname||'
- else a.'||idname||' end
- FROM (select * from '||pgr_quote_ident(tabname)||' where true '||rows_where||') as a
- JOIN (select * from '||pgr_quote_ident(tabname)||' where true '||rows_where||') as b
- ON (a.'|| gname||' && b.'||gname||')
- WHERE a.'||idname||' != b.'||idname|| '
- and (a.'||sourcename||' in (b.'||sourcename||',b.'||targetname||')
- or a.'||targetname||' in (b.'||sourcename||',b.'||targetname||')) = false
- and st_intersects(a.'||gname||', b.'||gname||')=true) as d ';
+ RAISE NOTICE 'Analyzing for intersections. Please wait...';
+ query = 'select count(*) from (select distinct case when a.'||idname||' < b.'||idname||' then a.'||idname||'
+ else b.'||idname||' end,
+ case when a.'||idname||' < b.'||idname||' then b.'||idname||'
+ else a.'||idname||' end
+ FROM (select * from '||_pgr_quote_ident(tabname)||' where true '||rows_where||') as a
+ JOIN (select * from '||_pgr_quote_ident(tabname)||' where true '||rows_where||') as b
+ ON (a.'|| gname||' && b.'||gname||')
+ WHERE a.'||idname||' != b.'||idname|| '
+ and (a.'||sourcename||' in (b.'||sourcename||',b.'||targetname||')
+ or a.'||targetname||' in (b.'||sourcename||',b.'||targetname||')) = false
+ and st_intersects(a.'||gname||', b.'||gname||')=true) as d ';
raise debug '%' ,query;
execute query INTO numCrossing;
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong when Analyzing for intersections';
+ RETURN 'FAIL';
END;
@@ -411,7 +353,7 @@ COMMENT ON FUNCTION pgr_analyzeGraph(text,double precision,text,text,text,text,t
/*
-.. function:: pgr_analyzeOneway(tab, col, s_in_rules, s_out_rules, t_in_rules, t_out_rules)
+.. function:: _pgr_analyzeOneway(tab, col, s_in_rules, s_out_rules, t_in_rules, t_out_rules)
This function analyzes oneway streets in a graph and identifies any
flipped segments. Basically if you count the edges coming into a node
@@ -452,7 +394,7 @@ COMMENT ON FUNCTION pgr_analyzeGraph(text,double precision,text,text,text,text,t
.. code-block:: sql
- select pgr_analyzeOneway('st', 'one_way',
+ select _pgr_analyzeOneway('st', 'one_way',
ARRAY['', 'B', 'TF'],
ARRAY['', 'B', 'FT'],
ARRAY['', 'B', 'FT'],
@@ -479,12 +421,12 @@ a network that is not properly noded.
*/
CREATE OR REPLACE FUNCTION pgr_analyzeOneway(
- edge_table text,
- s_in_rules TEXT[],
- s_out_rules TEXT[],
- t_in_rules TEXT[],
- t_out_rules TEXT[],
- two_way_if_null boolean default true,
+ edge_table text,
+ s_in_rules TEXT[],
+ s_out_rules TEXT[],
+ t_in_rules TEXT[],
+ t_out_rules TEXT[],
+ two_way_if_null boolean default true,
oneway text default 'oneway',
source text default 'source',
target text default 'target')
@@ -507,136 +449,77 @@ DECLARE
sourcetype text;
targettype text;
vertname text;
- einname text;
- eoutname text;
debuglevel text;
BEGIN
- raise notice 'PROCESSING:';
+ raise notice 'PROCESSING:';
raise notice 'pgr_analyzeOneway(''%'',''%'',''%'',''%'',''%'',''%'',''%'',''%'',%)',
edge_table, s_in_rules , s_out_rules, t_in_rules, t_out_rules, oneway, source ,target,two_way_if_null ;
execute 'show client_min_messages' into debuglevel;
BEGIN
- RAISE DEBUG 'Cheking % exists',edge_table;
- execute 'select * from pgr_getTableName('||quote_literal(edge_table)||')' into naming;
+ RAISE DEBUG 'Checking % exists',edge_table;
+ execute 'select * from _pgr_getTableName('||quote_literal(edge_table)||',2)' into naming;
sname=naming.sname;
tname=naming.tname;
- IF sname IS NULL OR tname IS NULL THEN
- RAISE NOTICE '-------> % not found',edge_table;
- RETURN 'FAIL';
- ELSE
- RAISE DEBUG ' -----> OK';
- END IF;
-
tabname=sname||'.'||tname;
vname=tname||'_vertices_pgr';
vertname= sname||'.'||vname;
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the table name';
+ RETURN 'FAIL';
END;
-
- BEGIN
- raise DEBUG 'Checking oneway, source column "%" and target column "%" in % ',source,target,tabname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(source)||')' INTO sourcename;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(oneway)||')' INTO owname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(target)||')' INTO targetname;
- IF sourcename is not NULL and targetname is not NULL then
- --check that the are integer
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(sourcename) into sourcetype;
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(targetname) into targettype;
- IF sourcetype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: source column "%" is not of integer type',sourcename;
- RETURN 'FAIL';
- END IF;
- IF targettype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: target column "%" is not of integer type',targetname;
- RETURN 'FAIL';
- END IF;
- raise DEBUG ' ------>OK ';
- END IF;
- IF owname is NULL THEN
- raise notice 'ERROR: oneway column "%" not found in %',oneway,tabname;
- RETURN 'FAIL';
- END IF;
- IF sourcename is NULL THEN
- raise notice 'ERROR: source column "%" not found in %',source,tabname;
- RETURN 'FAIL';
- END IF;
- IF targetname is NULL THEN
- raise notice 'ERROR: target column "%" not found in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- IF sourcename=targetname THEN
- raise notice 'ERROR: source and target columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- IF sourcename=owname THEN
- raise notice 'ERROR: source and owname columns have the same name "%" in %',source,tabname;
- RETURN 'FAIL';
- END IF;
- IF targetname=owname THEN
- raise notice 'ERROR: target and owname columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- sourcename=quote_ident(sourcename);
- targetname=quote_ident(targetname);
- owname=quote_ident(owname);
-
+ BEGIN
+ raise debug 'Checking Vertices table';
+ execute 'select * from _pgr_checkVertTab('||quote_literal(vertname) ||', ''{"id","ein","eout"}''::text[])' into naming;
+ execute 'UPDATE '||_pgr_quote_ident(vertname)||' SET eout=0 ,ein=0';
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the vertices table';
+ RETURN 'FAIL';
END;
- BEGIN
- raise DEBUG 'Checking table %.% exists ',sname ,vname;
- execute 'select * from pgr_getTableName('||quote_literal(sname||'.'||vname)||')' into naming;
- vname=naming.tname;
- vertname=sname||'.'||vname;
- IF naming.sname is not NULL and naming.tname IS NOT NULL then
- raise DEBUG ' ------>OK';
- ELSE
- raise notice ' --->Table %.% does not exists',sname ,vname;
- raise exception ' --->Please create %.% using pgr_createTopology() or pgr_makeVerticesTable()',sname ,vname;
- END IF;
- END;
+ BEGIN
+ raise debug 'Checking column names in edge table';
+ select * into sourcename from _pgr_getColumnName(sname, tname,source,2);
+ select * into targetname from _pgr_getColumnName(sname, tname,target,2);
+ select * into owname from _pgr_getColumnName(sname, tname,oneway,2);
- BEGIN
- RAISE DEBUG 'Cheking for "ein" column in %',vertname;
- execute 'select pgr_getcolumnName('||quote_literal(vertname)||','||quote_literal('ein')||')' into einname;
- if einname is not null then
- einname=quote_ident(einname);
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------>Adding "ein" column in %',vertname;
- set client_min_messages to warning;
- execute 'ALTER TABLE '||pgr_quote_ident(vertname)||' ADD COLUMN ein integer';
- execute 'set client_min_messages to '|| debuglevel;
- einname=quote_ident('ein');
- END IF;
- END;
+ perform _pgr_onError( sourcename in (targetname,owname) or targetname=owname, 2,
+ '_pgr_createToplogy', 'Two columns share the same name', 'Parameter names for oneway,source and target must be different',
+ 'Column names are OK');
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the column names';
+ RETURN 'FAIL';
+ END;
- BEGIN
- RAISE DEBUG 'Cheking for "eout" column in %',vertname;
- execute 'select pgr_getcolumnName('||quote_literal(vertname)||','||quote_literal('eout')||')' into eoutname;
- if eoutname is not null then
- eoutname=quote_ident(eoutname);
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------>Adding "eout" column in %',verticesTable;
- set client_min_messages to warning;
- execute 'ALTER TABLE '||pgr_quote_ident(vertname)||' ADD COLUMN eout integer';
- execute 'set client_min_messages to '|| debuglevel;
- eoutname=quote_ident('eout');
- END IF;
- END;
+ BEGIN
+ raise debug 'Checking column types in edge table';
+ select * into sourcetype from _pgr_getColumnType(sname,tname,sourcename,1);
+ select * into targettype from _pgr_getColumnType(sname,tname,targetname,1);
+
+
+ perform _pgr_onError(sourcetype not in('integer','smallint','bigint') , 2,
+ '_pgr_createTopology', 'Wrong type of Column '|| sourcename, ' Expected type of '|| sourcename || ' is integer,smallint or bigint but '||sourcetype||' was found',
+ 'Type of Column '|| sourcename || ' is ' || sourcetype);
+
+ perform _pgr_onError(targettype not in('integer','smallint','bigint') , 2,
+ '_pgr_createTopology', 'Wrong type of Column '|| targetname, ' Expected type of '|| targetname || ' is integer,smallint or biginti but '||targettype||' was found',
+ 'Type of Column '|| targetname || ' is ' || targettype);
+
+ raise DEBUG ' --> OK';
+ EXCEPTION WHEN raise_exception THEN
+ RAISE NOTICE 'ERROR: something went wrong checking the column types';
+ RETURN 'FAIL';
+ END;
- BEGIN
- RAISE DEBUG 'Zeroing columns "ein" and "eout" on "%".', vertname;
- execute 'UPDATE '||pgr_quote_ident(vertname)||' SET '||einname||'=0, '||eoutname||'=0';
- END;
RAISE NOTICE 'Analyzing graph for one way street errors.';
@@ -646,10 +529,10 @@ BEGIN
ELSE '' END;
instr := '''' || array_to_string(s_in_rules, ''',''') || '''';
- EXECUTE 'update '||pgr_quote_ident(vertname)||' a set '||einname||'=coalesce('||einname||',0)+b.cnt
+ EXECUTE 'update '||_pgr_quote_ident(vertname)||' a set ein=coalesce(ein,0)+b.cnt
from (
- select '|| sourcename ||', count(*) as cnt
- from '|| tabname ||'
+ select '|| sourcename ||', count(*) as cnt
+ from '|| tabname ||'
where '|| rule || owname ||' in ('|| instr ||')
group by '|| sourcename ||' ) b
where a.id=b.'|| sourcename;
@@ -657,43 +540,43 @@ BEGIN
RAISE NOTICE 'Analysis 25%% complete ...';
instr := '''' || array_to_string(t_in_rules, ''',''') || '''';
- EXECUTE 'update '||pgr_quote_ident(vertname)||' a set '||einname||'=coalesce('||einname||',0)+b.cnt
+ EXECUTE 'update '||_pgr_quote_ident(vertname)||' a set ein=coalesce(ein,0)+b.cnt
from (
- select '|| targetname ||', count(*) as cnt
- from '|| tabname ||'
+ select '|| targetname ||', count(*) as cnt
+ from '|| tabname ||'
where '|| rule || owname ||' in ('|| instr ||')
group by '|| targetname ||' ) b
where a.id=b.'|| targetname;
-
+
RAISE NOTICE 'Analysis 50%% complete ...';
instr := '''' || array_to_string(s_out_rules, ''',''') || '''';
- EXECUTE 'update '||pgr_quote_ident(vertname)||' a set '||eoutname||'=coalesce('||eoutname||',0)+b.cnt
+ EXECUTE 'update '||_pgr_quote_ident(vertname)||' a set eout=coalesce(eout,0)+b.cnt
from (
- select '|| sourcename ||', count(*) as cnt
- from '|| tabname ||'
+ select '|| sourcename ||', count(*) as cnt
+ from '|| tabname ||'
where '|| rule || owname ||' in ('|| instr ||')
group by '|| sourcename ||' ) b
where a.id=b.'|| sourcename;
RAISE NOTICE 'Analysis 75%% complete ...';
instr := '''' || array_to_string(t_out_rules, ''',''') || '''';
- EXECUTE 'update '||pgr_quote_ident(vertname)||' a set '||eoutname||'=coalesce('||eoutname||',0)+b.cnt
+ EXECUTE 'update '||_pgr_quote_ident(vertname)||' a set eout=coalesce(eout,0)+b.cnt
from (
- select '|| targetname ||', count(*) as cnt
- from '|| tabname ||'
+ select '|| targetname ||', count(*) as cnt
+ from '|| tabname ||'
where '|| rule || owname ||' in ('|| instr ||')
group by '|| targetname ||' ) b
where a.id=b.'|| targetname;
RAISE NOTICE 'Analysis 100%% complete ...';
- EXECUTE 'SELECT count(*) FROM '||pgr_quote_ident(vertname)||' WHERE ein=0 or eout=0' INTO ecnt;
+ EXECUTE 'SELECT count(*) FROM '||_pgr_quote_ident(vertname)||' WHERE ein=0 or eout=0' INTO ecnt;
RAISE NOTICE 'Found % potential problems in directionality' ,ecnt;
RETURN 'OK';
-
+
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
diff --git a/src/common/sql/pgrouting_conversion_tools.sql b/src/common/sql/pgrouting_conversion_tools.sql
new file mode 100644
index 0000000..196a135
--- /dev/null
+++ b/src/common/sql/pgrouting_conversion_tools.sql
@@ -0,0 +1,161 @@
+create or replace function pgr_pointtoedgenode(edges text, pnt geometry, tol float8)
+ returns integer as
+$body$
+/*
+ * pgr_pointtoedgenode(edges text, pnt geometry, tol float8)
+ *
+ * Given and table of edges with a spatial index on the_geom
+ * and a point geometry search for the closest edge within tol distance to the edges
+ * then compute the projection of the point onto the line segment and select source or target
+ * based on whether the projected point is closer to the respective end and return source or target.
+ * If no edge is within tol distance then return -1
+*/
+declare
+ rr record;
+ pct float;
+ debuglevel text;
+
+begin
+ -- find the closest edge within tol distance
+ execute 'select * from ' || _pgr_quote_ident(edges) ||
+ ' where st_dwithin(''' || pnt::text ||
+ '''::geometry, the_geom, ' || tol || ') order by st_distance(''' || pnt::text ||
+ '''::geometry, the_geom) asc limit 1' into rr;
+
+ if rr.the_geom is not null then
+ -- deal with MULTILINESTRINGS
+ if geometrytype(rr.the_geom)='MULTILINESTRING' THEN
+ rr.the_geom := ST_GeometryN(rr.the_geom, 1);
+ end if;
+
+ -- project the point onto the linestring
+ execute 'show client_min_messages' into debuglevel;
+ SET client_min_messages='ERROR';
+ pct := st_line_locate_point(rr.the_geom, pnt);
+ execute 'set client_min_messages to '|| debuglevel;
+
+ -- return the node we are closer to
+ if pct < 0.5 then
+ return rr.source;
+ else
+ return rr.target;
+ end if;
+ else
+ -- return a failure to find an edge within tol distance
+ return -1;
+ end if;
+end;
+$body$
+ language plpgsql volatile
+ cost 5;
+
+
+----------------------------------------------------------------------------
+
+create or replace function pgr_flipedges(ga geometry[])
+ returns geometry[] as
+$body$
+/*
+ * pgr_flipedges(ga geometry[])
+ *
+ * Given an array of linestrings that are supposedly connected end to end like the results
+ * of a route, check the edges and flip any end for end if they do not connect with the
+ * previous seegment and return the array with the segments flipped as appropriate.
+ *
+ * NOTE: no error checking is done for conditions like adjacent edges are not connected.
+*/
+declare
+ nn integer;
+ i integer;
+ g geometry;
+
+begin
+ -- get the count of edges, and return if only one edge
+ nn := array_length(ga, 1);
+ if nn=1 then
+ return ga;
+ end if;
+
+ -- determine if first needs to be flipped
+ g := _pgr_startpoint(ga[1]);
+
+ -- if the start of the first is connected to the second then it needs to be flipped
+ if _pgr_startpoint(ga[2])=g or _pgr_endpoint(ga[2])=g then
+ ga[1] := st_reverse(ga[1]);
+ end if;
+ g := _pgr_endpoint(ga[1]);
+
+ -- now if the end of the last edge matchs the end of the current edge we need to flip it
+ for i in 2 .. nn loop
+ if _pgr_endpoint(ga[i])=g then
+ ga[i] := st_reverse(ga[i]);
+ end if;
+ -- save the end of this edge into the last end for the next cycle
+ g := _pgr_endpoint(ga[i]);
+ end loop;
+
+ return ga;
+end;
+$body$
+ language plpgsql immutable;
+
+
+------------------------------------------------------------------------------
+
+create or replace function pgr_texttopoints(pnts text, srid integer DEFAULT(4326))
+ returns geometry[] as
+$body$
+/*
+ * pgr_texttopoints(pnts text, srid integer DEFAULT(4326))
+ *
+ * Given a text string of the format "x,y;x,y;x,y;..." and the srid to use,
+ * split the string and create and array point geometries
+*/
+declare
+ a text[];
+ t text;
+ p geometry;
+ g geometry[];
+
+begin
+ -- convert commas to space and split on ';'
+ a := string_to_array(replace(pnts, ',', ' '), ';');
+ -- convert each 'x y' into a point geometry and concattenate into a new array
+ for t in select unnest(a) loop
+ p := st_pointfromtext('POINT(' || t || ')', srid);
+ g := g || p;
+ end loop;
+
+ return g;
+end;
+$body$
+ language plpgsql immutable;
+
+-----------------------------------------------------------------------
+
+create or replace function pgr_pointstovids(pnts geometry[], edges text, tol float8 DEFAULT(0.01))
+ returns integer[] as
+$body$
+/*
+ * pgr_pointstovids(pnts geometry[], edges text, tol float8 DEFAULT(0.01))
+ *
+ * Given an array of point geometries and an edge table and a max search tol distance
+ * convert points into vertex ids using pgr_pointtoedgenode()
+ *
+ * NOTE: You need to check the results for any vids=-1 which indicates if failed to locate an edge
+*/
+declare
+ v integer[];
+ g geometry;
+
+begin
+ -- cycle through each point and locate the nearest edge and vertex on that edge
+ for g in select unnest(pnts) loop
+ v := v || pgr_pointtoedgenode(edges, g, tol);
+ end loop;
+
+ return v;
+end;
+$body$
+ language plpgsql stable;
+
diff --git a/src/common/sql/pgrouting_dmatrix_tools.sql b/src/common/sql/pgrouting_dmatrix_tools.sql
new file mode 100644
index 0000000..46b87a4
--- /dev/null
+++ b/src/common/sql/pgrouting_dmatrix_tools.sql
@@ -0,0 +1,120 @@
+create or replace function pgr_pointstodmatrix(pnts geometry[], mode integer default (0), OUT dmatrix double precision[], OUT ids integer[])
+ returns record as
+$body$
+/*
+ * pgr_pointstodmatrix(pnts geometry[], OUT dmatrix double precision[], OUT ids integer[])
+ *
+ * Create a distance symetric distance matrix suitable for TSP using Euclidean distances
+ * based on the st_distance(). You might want to create a variant of this the uses st_distance_sphere()
+ * or st_distance_spheriod() or some other function.
+ *
+*/
+declare
+ r record;
+
+begin
+ dmatrix := array[]::double precision[];
+ ids := array[]::integer[];
+
+ -- create an id for each point in the array and unnest it into a table nodes in the with clause
+ for r in with nodes as (select row_number() over()::integer as id, p from (select unnest(pnts) as p) as foo)
+ -- compute a row of distances
+ select i, array_agg(dist) as arow from (
+ select a.id as i, b.id as j,
+ case when mode=0
+ then st_distance(a.p, b.p)
+ else st_distance_sphere(a.p, b.p)
+ end as dist
+ from nodes a, nodes b
+ order by a.id, b.id
+ ) as foo group by i order by i loop
+
+ -- you must concat an array[array[]] to make dmatrix[][]
+ -- concat the row of distances to the dmatrix
+ dmatrix := array_cat(dmatrix, array[r.arow]);
+ ids := ids || array[r.i];
+ end loop;
+end;
+$body$
+ language plpgsql stable;
+
+
+------------------------------------------------------------------------------
+
+create or replace function pgr_vidstodmatrix(IN vids integer[], IN pnts geometry[], IN edges text, tol float8 DEFAULT(0.1), OUT dmatrix double precision[], OUT ids integer[])
+ returns record as
+$body$
+/*
+ * pgr_vidstodmatrix(IN vids integer[], IN pnts geometry[], IN edges text, tol float8 DEFAULT(0.1),
+ * OUT dmatrix double precision[], OUT ids integer[])
+ *
+ * This function thats an array vertex ids, the original array of points, the edge table name and a tol.
+ * It then computes kdijkstra() distances for each vertex to all the other vertices and creates a symmetric
+ * distances matrix suitable for TSP. The pnt array and the tol are used to establish a BBOX for limiteding
+ * selection of edges.the extents of the points is expanded by tol.
+ *
+ * NOTES:
+ * 1. we compute a symmetric matrix because TSP requires that so the distances are better the Euclidean but
+ * but are not perfect
+ * 2. kdijkstra() can fail to find a path between some of the vertex ids. We to not detect this other than
+ * the cost might get set to -1.0, so the dmatrix shoule be checked for this as it makes it invalid for TSP
+ *
+*/
+declare
+ i integer;
+ j integer;
+ nn integer;
+ rr record;
+ bbox geometry;
+ t float8[];
+
+begin
+ -- check if the input arrays has any -1 values, maybe this whould be a raise exception
+ if vids @> ARRAY[-1] then
+ raise notice 'Some vids are undefined (-1)!';
+ dmatrix := null;
+ ids := null;
+ return;
+ end if;
+
+ ids := vids;
+
+ -- get the count of nodes
+ nn := array_length(vids,1);
+
+ -- zero out a dummy row
+ for i in 1 .. nn loop
+ t := t || 0.0::float8;
+ end loop;
+
+ -- using the dummy row, zero out the whole matrix
+ for i in 1 .. nn loop
+ dmatrix := dmatrix || ARRAY[t];
+ end loop;
+
+ for i in 1 .. nn-1 loop
+ j := i;
+ -- compute the bbox for the point needed for this row
+ select st_expand(st_collect(pnts[id]), tol) into bbox
+ from (select generate_series as id from generate_series(i, nn)) as foo;
+
+ -- compute kdijkstra() for this row
+ for rr in execute 'select * from pgr_kdijkstracost($1, $2, $3, false, false)'
+ using 'select id, source, target, cost from ' || edges ||
+ ' where the_geom && ''' || bbox::text || '''::geometry'::text, vids[i], vids[i+1:nn] loop
+
+ -- TODO need to check that all node were reachable from source
+ -- I think unreachable paths between nodes returns cost=-1.0
+
+ -- populate the matrix with the cost values, remember this is symmetric
+ j := j + 1;
+ -- raise notice 'cost(%,%)=%', i, j, rr.cost;
+ dmatrix[i][j] := rr.cost;
+ dmatrix[j][i] := rr.cost;
+ end loop;
+ end loop;
+
+end;
+$body$
+ language plpgsql stable cost 200;
+
diff --git a/src/common/sql/pgrouting_legacy.sql b/src/common/sql/pgrouting_legacy.sql
index e358d57..429c980 100644
--- a/src/common/sql/pgrouting_legacy.sql
+++ b/src/common/sql/pgrouting_legacy.sql
@@ -14,7 +14,7 @@
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-- BEGIN;
@@ -150,7 +150,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT;
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--
CREATE OR REPLACE FUNCTION pgr_shootingStar(sql text, source_id integer, target_id integer,directed boolean, has_reverse_cost boolean)
@@ -315,7 +315,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT;
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--
@@ -941,7 +941,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT;
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--
diff --git a/src/common/sql/pgrouting_node_network.sql b/src/common/sql/pgrouting_node_network.sql
index 22eafdb..9b32462 100644
--- a/src/common/sql/pgrouting_node_network.sql
+++ b/src/common/sql/pgrouting_node_network.sql
@@ -13,7 +13,7 @@ DECLARE
*/
p_num int := 0;
p_ret text := '';
- pgis_ver_old boolean := pgr_versionless(postgis_lib_version(), '2.1.0.0');
+ pgis_ver_old boolean := _pgr_versionless(postgis_lib_version(), '2.1.0.0');
vst_line_substring text;
vst_line_locate_point text;
intab text;
@@ -36,12 +36,12 @@ DECLARE
BEGIN
raise notice 'PROCESSING:';
raise notice 'pgr_nodeNetwork(''%'',%,''%'',''%'',''%'')',edge_table,tolerance,the_geom,id,table_ending;
- raise notice 'Performing checks, pelase wait .....';
+ raise notice 'Performing checks, please wait .....';
execute 'show client_min_messages' into debuglevel;
BEGIN
- RAISE DEBUG 'Cheking % exists',edge_table;
- execute 'select * from pgr_getTableName('||quote_literal(edge_table)||')' into naming;
+ RAISE DEBUG 'Checking % exists',edge_table;
+ execute 'select * from _pgr_getTableName('||quote_literal(edge_table)||',0)' into naming;
sname=naming.sname;
tname=naming.tname;
IF sname IS NULL OR tname IS NULL THEN
@@ -59,7 +59,7 @@ BEGIN
BEGIN
raise DEBUG 'Checking id column "%" columns in % ',id,intab;
- EXECUTE 'select pgr_getColumnName('||quote_literal(intab)||','||quote_literal(id)||')' INTO n_pkey;
+ EXECUTE 'select _pgr_getColumnName('||quote_literal(intab)||','||quote_literal(id)||')' INTO n_pkey;
IF n_pkey is NULL then
raise notice 'ERROR: id column "%" not found in %',id,intab;
RETURN 'FAIL';
@@ -69,7 +69,7 @@ BEGIN
BEGIN
raise DEBUG 'Checking id column "%" columns in % ',the_geom,intab;
- EXECUTE 'select pgr_getColumnName('||quote_literal(intab)||','||quote_literal(the_geom)||')' INTO n_geom;
+ EXECUTE 'select _pgr_getColumnName('||quote_literal(intab)||','||quote_literal(the_geom)||')' INTO n_geom;
IF n_geom is NULL then
raise notice 'ERROR: the_geom column "%" not found in %',the_geom,intab;
RETURN 'FAIL';
@@ -84,7 +84,7 @@ BEGIN
BEGIN
raise DEBUG 'Checking the SRID of the geometry "%"', n_geom;
EXECUTE 'SELECT ST_SRID(' || quote_ident(n_geom) || ') as srid '
- || ' FROM ' || pgr_quote_ident(intab)
+ || ' FROM ' || _pgr_quote_ident(intab)
|| ' WHERE ' || quote_ident(n_geom)
|| ' IS NOT NULL LIMIT 1' INTO sridinfo;
IF sridinfo IS NULL OR sridinfo.srid IS NULL THEN
@@ -99,28 +99,28 @@ BEGIN
END;
BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',n_pkey,intab;
- if (pgr_isColumnIndexed(intab,n_pkey)) then
+ RAISE DEBUG 'Checking "%" column in % is indexed',n_pkey,intab;
+ if (_pgr_isColumnIndexed(intab,n_pkey)) then
RAISE DEBUG ' ------>OK';
else
RAISE DEBUG ' ------> Adding index "%_%_idx".',n_pkey,intab;
set client_min_messages to warning;
- execute 'create index '||tname||'_'||n_pkey||'_idx on '||pgr_quote_ident(intab)||' using btree('||quote_ident(n_pkey)||')';
+ execute 'create index '||tname||'_'||n_pkey||'_idx on '||_pgr_quote_ident(intab)||' using btree('||quote_ident(n_pkey)||')';
execute 'set client_min_messages to '|| debuglevel;
END IF;
END;
BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',n_geom,intab;
- if (pgr_iscolumnindexed(intab,n_geom)) then
+ RAISE DEBUG 'Checking "%" column in % is indexed',n_geom,intab;
+ if (_pgr_iscolumnindexed(intab,n_geom)) then
RAISE DEBUG ' ------>OK';
else
RAISE DEBUG ' ------> Adding unique index "%_%_gidx".',intab,n_geom;
set client_min_messages to warning;
execute 'CREATE INDEX '
|| quote_ident(tname || '_' || n_geom || '_gidx' )
- || ' ON ' || pgr_quote_ident(intab)
+ || ' ON ' || _pgr_quote_ident(intab)
|| ' USING gist (' || quote_ident(n_geom) || ')';
execute 'set client_min_messages to '|| debuglevel;
END IF;
@@ -128,26 +128,26 @@ BEGIN
---------------
BEGIN
raise DEBUG 'initializing %',outtab;
- execute 'select * from pgr_getTableName('||quote_literal(outtab)||')' into naming;
+ execute 'select * from _pgr_getTableName('||quote_literal(outtab)||',0)' into naming;
IF sname=naming.sname AND outname=naming.tname THEN
- execute 'TRUNCATE TABLE '||pgr_quote_ident(outtab)||' RESTART IDENTITY';
+ execute 'TRUNCATE TABLE '||_pgr_quote_ident(outtab)||' RESTART IDENTITY';
execute 'SELECT DROPGEOMETRYCOLUMN('||quote_literal(sname)||','||quote_literal(outname)||','||quote_literal(n_geom)||')';
ELSE
set client_min_messages to warning;
- execute 'CREATE TABLE '||pgr_quote_ident(outtab)||' (id bigserial PRIMARY KEY,old_id integer,sub_id integer,
+ execute 'CREATE TABLE '||_pgr_quote_ident(outtab)||' (id bigserial PRIMARY KEY,old_id integer,sub_id integer,
source bigint,target bigint)';
END IF;
- execute 'select geometrytype('||quote_ident(n_geom)||') from '||pgr_quote_ident(intab)||' limit 1' into geomtype;
+ execute 'select geometrytype('||quote_ident(n_geom)||') from '||_pgr_quote_ident(intab)||' limit 1' into geomtype;
execute 'select addGeometryColumn('||quote_literal(sname)||','||quote_literal(outname)||','||
quote_literal(n_geom)||','|| srid||', '||quote_literal(geomtype)||', 2)';
- execute 'CREATE INDEX '||quote_ident(outname||'_'||n_geom||'_idx')||' ON '||pgr_quote_ident(outtab)||' USING GIST ('||quote_ident(n_geom)||')';
+ execute 'CREATE INDEX '||quote_ident(outname||'_'||n_geom||'_idx')||' ON '||_pgr_quote_ident(outtab)||' USING GIST ('||quote_ident(n_geom)||')';
execute 'set client_min_messages to '|| debuglevel;
raise DEBUG ' ------>OK';
END;
----------------
- raise notice 'Processing, pelase wait .....';
+ raise notice 'Processing, please wait .....';
if pgis_ver_old then
@@ -163,17 +163,17 @@ BEGIN
select l1.' || quote_ident(n_pkey) || ' as l1id,
l2.' || quote_ident(n_pkey) || ' as l2id,
l1.' || quote_ident(n_geom) || ' as line,
- pgr_startpoint(l2.' || quote_ident(n_geom) || ') as source,
- pgr_endpoint(l2.' || quote_ident(n_geom) || ') as target,
+ _pgr_startpoint(l2.' || quote_ident(n_geom) || ') as source,
+ _pgr_endpoint(l2.' || quote_ident(n_geom) || ') as target,
st_intersection(l1.' || quote_ident(n_geom) || ', l2.' || quote_ident(n_geom) || ') as geom
- from ' || pgr_quote_ident(intab) || ' l1
- join ' || pgr_quote_ident(intab) || ' l2
+ from ' || _pgr_quote_ident(intab) || ' l1
+ join ' || _pgr_quote_ident(intab) || ' l2
on (st_dwithin(l1.' || quote_ident(n_geom) || ', l2.' || quote_ident(n_geom) || ', ' || tolerance || '))'||
'where l1.' || quote_ident(n_pkey) || ' <> l2.' || quote_ident(n_pkey)||' and
- st_equals(Pgr_startpoint(l1.' || quote_ident(n_geom) || '),pgr_startpoint(l2.' || quote_ident(n_geom) || '))=false and
- st_equals(Pgr_startpoint(l1.' || quote_ident(n_geom) || '),pgr_endpoint(l2.' || quote_ident(n_geom) || '))=false and
- st_equals(Pgr_endpoint(l1.' || quote_ident(n_geom) || '),pgr_startpoint(l2.' || quote_ident(n_geom) || '))=false and
- st_equals(Pgr_endpoint(l1.' || quote_ident(n_geom) || '),pgr_endpoint(l2.' || quote_ident(n_geom) || '))=false )';
+ st_equals(_pgr_startpoint(l1.' || quote_ident(n_geom) || '),_pgr_startpoint(l2.' || quote_ident(n_geom) || '))=false and
+ st_equals(_pgr_startpoint(l1.' || quote_ident(n_geom) || '),_pgr_endpoint(l2.' || quote_ident(n_geom) || '))=false and
+ st_equals(_pgr_endpoint(l1.' || quote_ident(n_geom) || '),_pgr_startpoint(l2.' || quote_ident(n_geom) || '))=false and
+ st_equals(_pgr_endpoint(l1.' || quote_ident(n_geom) || '),_pgr_endpoint(l2.' || quote_ident(n_geom) || '))=false )';
raise debug '%',p_ret;
EXECUTE p_ret;
@@ -183,11 +183,15 @@ BEGIN
-- drop table if exists inter_loc;
--HAD TO CHANGE THIS QUERY
- p_ret= 'create temp table inter_loc on commit drop as ( select * from (
- (select l1id, l2id, ' || vst_line_locate_point || '(line,source) as locus from intergeom)
- union
- (select l1id, l2id, ' || vst_line_locate_point || '(line,target) as locus from intergeom)) as foo
- where locus<>0 and locus<>1)';
+ p_ret= 'create temp table inter_loc on commit drop as (
+ select l1id, l2id, ' || vst_line_locate_point || '(line,point) as locus from (
+ select DISTINCT l1id, l2id, line, (ST_DumpPoints(geom)).geom as point from intergeom) as foo
+ where ' || vst_line_locate_point || '(line,point)<>0 and ' || vst_line_locate_point || '(line,point)<>1)';
+-- p_ret= 'create temp table inter_loc on commit drop as ( select * from (
+-- (select l1id, l2id, ' || vst_line_locate_point || '(line,source) as locus from intergeom)
+-- union
+-- (select l1id, l2id, ' || vst_line_locate_point || '(line,target) as locus from intergeom)) as foo
+-- where locus<>0 and locus<>1)';
raise debug '%',p_ret;
EXECUTE p_ret;
@@ -200,18 +204,18 @@ BEGIN
--- outab needs to be formally created with id, old_id, subid,the_geom, source,target
--- so it can be inmediatly be used with createTopology
--- EXECUTE 'drop table if exists ' || pgr_quote_ident(outtab);
--- EXECUTE 'create table ' || pgr_quote_ident(outtab) || ' as
- P_RET = 'insert into '||pgr_quote_ident(outtab)||' (old_id,sub_id,'||quote_ident(n_geom)||') ( with cut_locations as (
+-- EXECUTE 'drop table if exists ' || _pgr_quote_ident(outtab);
+-- EXECUTE 'create table ' || _pgr_quote_ident(outtab) || ' as
+ P_RET = 'insert into '||_pgr_quote_ident(outtab)||' (old_id,sub_id,'||quote_ident(n_geom)||') ( with cut_locations as (
select l1id as lid, locus
from inter_loc
-- then generates start and end locus for each line that have to be cut buy a location point
UNION ALL
select i.l1id as lid, 0 as locus
- from inter_loc i left join ' || pgr_quote_ident(intab) || ' b on (i.l1id = b.' || quote_ident(n_pkey) || ')
+ from inter_loc i left join ' || _pgr_quote_ident(intab) || ' b on (i.l1id = b.' || quote_ident(n_pkey) || ')
UNION ALL
select i.l1id as lid, 1 as locus
- from inter_loc i left join ' || pgr_quote_ident(intab) || ' b on (i.l1id = b.' || quote_ident(n_pkey) || ')
+ from inter_loc i left join ' || _pgr_quote_ident(intab) || ' b on (i.l1id = b.' || quote_ident(n_pkey) || ')
order by lid, locus
),
-- we generate a row_number index column for each input line
@@ -222,22 +226,22 @@ BEGIN
)
-- finally, each original line is cut with consecutive locations using linear referencing functions
select l.' || quote_ident(n_pkey) || ', loc1.idx as sub_id, ' || vst_line_substring || '(l.' || quote_ident(n_geom) || ', loc1.locus, loc2.locus) as ' || quote_ident(n_geom) || '
- from loc_with_idx loc1 join loc_with_idx loc2 using (lid) join ' || pgr_quote_ident(intab) || ' l on (l.' || quote_ident(n_pkey) || ' = loc1.lid)
+ from loc_with_idx loc1 join loc_with_idx loc2 using (lid) join ' || _pgr_quote_ident(intab) || ' l on (l.' || quote_ident(n_pkey) || ' = loc1.lid)
where loc2.idx = loc1.idx+1
-- keeps only linestring geometries
and geometryType(' || vst_line_substring || '(l.' || quote_ident(n_geom) || ', loc1.locus, loc2.locus)) = ''LINESTRING'') ';
raise debug '%',p_ret;
EXECUTE p_ret;
GET DIAGNOSTICS splits = ROW_COUNT;
- execute 'with diff as (select distinct old_id from '||pgr_quote_ident(outtab)||' )
+ execute 'with diff as (select distinct old_id from '||_pgr_quote_ident(outtab)||' )
select count(*) from diff' into touched;
-- here, it misses all original line that did not need to be cut by intersection points: these lines
-- are already clean
-- inserts them in the final result: all lines which gid is not in the res table.
- EXECUTE 'insert into ' || pgr_quote_ident(outtab) || ' (old_id , sub_id, ' || quote_ident(n_geom) || ')
- ( with used as (select distinct old_id from '|| pgr_quote_ident(outtab)||')
+ EXECUTE 'insert into ' || _pgr_quote_ident(outtab) || ' (old_id , sub_id, ' || quote_ident(n_geom) || ')
+ ( with used as (select distinct old_id from '|| _pgr_quote_ident(outtab)||')
select ' || quote_ident(n_pkey) || ', 1 as sub_id, ' || quote_ident(n_geom) ||
- ' from '|| pgr_quote_ident(intab) ||' where '||quote_ident(n_pkey)||' not in (select * from used))';
+ ' from '|| _pgr_quote_ident(intab) ||' where '||quote_ident(n_pkey)||' not in (select * from used))';
GET DIAGNOSTICS untouched = ROW_COUNT;
raise NOTICE ' Splitted Edges: %', touched;
diff --git a/src/common/sql/pgrouting_topology.sql b/src/common/sql/pgrouting_topology.sql
index d01fd6a..3838653 100644
--- a/src/common/sql/pgrouting_topology.sql
+++ b/src/common/sql/pgrouting_topology.sql
@@ -1,40 +1,38 @@
-
/*
-.. function:: pgr_pointToId(point geometry, tolerance double precision,vname text,srid integer)
-
- This function should not be used directly. Use assign_vertex_id instead
-
- Inserts a point into the vertices tablei "vname" with the srid "srid", and return an id
- of a new point or an existing point. Tolerance is the minimal distance
- between existing points and the new point to create a new point.
-
- Last changes: 2013-03-22
- Author: Christian Gonzalez
- Author: Stephen Woodbridge <woodbri at imaptools.com>
- Modified by: Vicky Vergara <vicky_vergara at hotmail,com>
-
- HISTORY
- Last changes: 2013-03-22
- 2013-08-19: handling schemas
+.. function:: _pgr_pointToId(point geometry, tolerance double precision,vname text,srid integer)
+
+This function should not be used directly. Use assign_vertex_id instead
+Inserts a point into the vertices tablei "vname" with the srid "srid", and return an id
+of a new point or an existing point. Tolerance is the minimal distance
+between existing points and the new point to create a new point.
+
+Last changes: 2013-03-22
+Author: Christian Gonzalez
+Author: Stephen Woodbridge <woodbri at imaptools.com>
+Modified by: Vicky Vergara <vicky_vergara at hotmail,com>
+
+HISTORY
+Last changes: 2013-03-22
+2013-08-19: handling schemas
*/
-CREATE OR REPLACE FUNCTION pgr_pointToId(point geometry, tolerance double precision,vertname text,srid integer)
+CREATE OR REPLACE FUNCTION _pgr_pointToId(point geometry, tolerance double precision,vertname text,srid integer)
RETURNS bigint AS
-$BODY$
+$BODY$
DECLARE
- rec record;
- pid bigint;
+ rec record;
+ pid bigint;
BEGIN
execute 'SELECT ST_Distance(the_geom,ST_GeomFromText(st_astext('||quote_literal(point::text)||'),'||srid||')) AS d, id, the_geom
- FROM '||pgr_quote_ident(vertname)||'
- WHERE ST_DWithin(the_geom, ST_GeomFromText(st_astext('||quote_literal(point::text)||'),'||srid||'),'|| tolerance||')
- ORDER BY d
- LIMIT 1' INTO rec ;
+FROM '||_pgr_quote_ident(vertname)||'
+WHERE ST_DWithin(the_geom, ST_GeomFromText(st_astext('||quote_literal(point::text)||'),'||srid||'),'|| tolerance||')
+ORDER BY d
+LIMIT 1' INTO rec ;
IF rec.id is not null THEN
pid := rec.id;
ELSE
- execute 'INSERT INTO '||pgr_quote_ident(vertname)||' (the_geom) VALUES ('||quote_literal(point::text)||')';
+ execute 'INSERT INTO '||_pgr_quote_ident(vertname)||' (the_geom) VALUES ('||quote_literal(point::text)||')';
pid := lastval();
END IF;
@@ -43,28 +41,30 @@ BEGIN
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
-COMMENT ON FUNCTION pgr_pointToId(geometry,double precision, text,integer) IS 'args: point geometry,tolerance,verticesTable,srid - inserts the point into the vertices table using tolerance to determine if its an existing point and returns the id assigned to it' ;
+COMMENT ON FUNCTION _pgr_pointToId(geometry,double precision, text,integer) IS 'args: point geometry,tolerance,verticesTable,srid - inserts the point into the vertices table using tolerance to determine if its an existing point and returns the id assigned to it' ;
/*
-.. function:: pgr_createtopology(edge_table, tolerance,the_geom,id,source,target,rows_where)
+.. function:: _pgr_createtopology(edge_table, tolerance,the_geom,id,source,target,rows_where)
- Fill the source and target column for all lines. All line ends
- with a distance less than tolerance, are assigned the same id
+Fill the source and target column for all lines. All line ends
+with a distance less than tolerance, are assigned the same id
- Author: Christian Gonzalez <christian.gonzalez at sigis.com.ve>
- Author: Stephen Woodbridge <woodbri at imaptools.com>
- Modified by: Vicky Vergara <vicky_vergara at hotmail,com>
+Author: Christian Gonzalez <christian.gonzalez at sigis.com.ve>
+Author: Stephen Woodbridge <woodbri at imaptools.com>
+Modified by: Vicky Vergara <vicky_vergara at hotmail,com>
- HISTORY
- Last changes: 2013-03-22
- 2013-08-19: handling schemas
+HISTORY
+Last changes: 2013-03-22
+2013-08-19: handling schemas
+2014-july: fixes issue 211
*/
CREATE OR REPLACE FUNCTION pgr_createtopology(edge_table text, tolerance double precision,
- the_geom text default 'the_geom', id text default 'id',
- source text default 'source', target text default 'target',rows_where text default 'true')
- RETURNS VARCHAR AS
+ the_geom text default 'the_geom', id text default 'id',
+ source text default 'source', target text default 'target',rows_where text default 'true',
+ clean boolean default true)
+RETURNS VARCHAR AS
$BODY$
DECLARE
@@ -88,511 +88,219 @@ DECLARE
notincluded integer;
i integer;
naming record;
+ info record;
flag boolean;
query text;
- sourcetype text;
+ idtype text;
+ gtype text;
+ sourcetype text;
targettype text;
debuglevel text;
+ dummyRec text;
+ fnName text;
+ err bool;
+ msgKind int;
BEGIN
- raise notice 'PROCESSING:';
- raise notice 'pgr_createTopology(''%'',%,''%'',''%'',''%'',''%'',''%'')',edge_table,tolerance,the_geom,id,source,target,rows_where;
- raise notice 'Performing checks, pelase wait .....';
- execute 'show client_min_messages' into debuglevel;
-
-
- BEGIN
- RAISE DEBUG 'Cheking % exists',edge_table;
- execute 'select * from pgr_getTableName('||quote_literal(edge_table)||')' into naming;
- sname=naming.sname;
- tname=naming.tname;
- IF sname IS NULL OR tname IS NULL THEN
- RAISE NOTICE '-------> % not found',edge_table;
- RETURN 'FAIL';
- ELSE
- RAISE DEBUG ' -----> OK';
- END IF;
-
- tabname=sname||'.'||tname;
- vname=tname||'_vertices_pgr';
- vertname= sname||'.'||vname;
- rows_where = ' AND ('||rows_where||')';
- END;
-
- BEGIN
- raise DEBUG 'Checking id column "%" columns in % ',id,tabname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(the_geom)||')' INTO gname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(id)||')' INTO idname;
- IF idname is NULL then
- raise notice 'ERROR: id column "%" not found in %',id,tabname;
- RETURN 'FAIL';
- END IF;
- raise DEBUG 'Checking geometry column "%" column in % ',the_geom,tabname;
- IF gname is not NULL then
- BEGIN
- raise DEBUG 'Checking the SRID of the geometry "%"', gname;
- query= 'SELECT ST_SRID(' || quote_ident(gname) || ') as srid '
- || ' FROM ' || pgr_quote_ident(tabname)
- || ' WHERE ' || quote_ident(gname)
- || ' IS NOT NULL LIMIT 1';
- EXECUTE QUERY
- INTO sridinfo;
-
- IF sridinfo IS NULL OR sridinfo.srid IS NULL THEN
- RAISE NOTICE 'ERROR: Can not determine the srid of the geometry "%" in table %', the_geom,tabname;
- RETURN 'FAIL';
- END IF;
- srid := sridinfo.srid;
- raise DEBUG ' -----> SRID found %',srid;
- EXCEPTION WHEN OTHERS THEN
- RAISE NOTICE 'ERROR: Can not determine the srid of the geometry "%" in table %', the_geom,tabname;
- RETURN 'FAIL';
- END;
- ELSE
- raise notice 'ERROR: Geometry column "%" not found in %',the_geom,tabname;
- RETURN 'FAIL';
- END IF;
- END;
-
- BEGIN
- raise DEBUG 'Checking source column "%" and target column "%" in % ',source,target,tabname;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(source)||')' INTO sourcename;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(target)||')' INTO targetname;
- IF sourcename is not NULL and targetname is not NULL then
- --check that the are integer
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(sourcename) into sourcetype;
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(targetname) into targettype;
- IF sourcetype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: source column "%" is not of integer type',sourcename;
- RETURN 'FAIL';
- END IF;
- IF targettype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: target column "%" is not of integer type',targetname;
- RETURN 'FAIL';
- END IF;
- raise DEBUG ' ------>OK ';
- END IF;
- IF sourcename is NULL THEN
- raise notice 'ERROR: source column "%" not found in %',source,tabname;
- RETURN 'FAIL';
- END IF;
- IF targetname is NULL THEN
- raise notice 'ERROR: target column "%" not found in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- END;
-
-
- IF sourcename=targetname THEN
- raise notice 'ERROR: source and target columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- IF sourcename=idname THEN
- raise notice 'ERROR: source and id columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- IF targetname=idname THEN
- raise notice 'ERROR: target and id columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
-
+ msgKind = 1; -- notice
+ fnName = 'pgr_createTopology';
+ raise notice 'PROCESSING:';
+ raise notice 'pgr_createTopology(''%'',%,''%'',''%'',''%'',''%'',''%'')',edge_table,tolerance,the_geom,id,source,target,rows_where;
+ -- raise notice 'pgr_createTopology(''%'',%,''%'',''%'',''%'',''%'',''%'',''%'')',edge_table,tolerance,the_geom,id,source,target,rows_where,clean;
+ execute 'show client_min_messages' into debuglevel;
+
+
+ raise notice 'Performing checks, please wait .....';
+
+ execute 'select * from _pgr_getTableName('|| quote_literal(edge_table)
+ || ',2,' || quote_literal(fnName) ||' )' into naming;
+ sname=naming.sname;
+ tname=naming.tname;
+ tabname=sname||'.'||tname;
+ vname=tname||'_vertices_pgr';
+ vertname= sname||'.'||vname;
+ rows_where = ' AND ('||rows_where||')';
+ raise DEBUG ' --> OK';
+
+
+ raise debug 'Checking column names in edge table';
+ select * into idname from _pgr_getColumnName(sname, tname,id,2,fnName);
+ select * into sourcename from _pgr_getColumnName(sname, tname,source,2,fnName);
+ select * into targetname from _pgr_getColumnName(sname, tname,target,2,fnName);
+ select * into gname from _pgr_getColumnName(sname, tname,the_geom,2,fnName);
+
+
+ err = sourcename in (targetname,idname,gname) or targetname in (idname,gname) or idname=gname;
+ perform _pgr_onError( err, 2, fnName,
+ 'Two columns share the same name', 'Parameter names for id,the_geom,source and target must be different',
+ 'Column names are OK');
+
+ raise DEBUG ' --> OK';
+
+ raise debug 'Checking column types in edge table';
+ select * into sourcetype from _pgr_getColumnType(sname,tname,sourcename,1, fnName);
+ select * into targettype from _pgr_getColumnType(sname,tname,targetname,1, fnName);
+ select * into idtype from _pgr_getColumnType(sname,tname,idname,1, fnName);
+
+ err = idtype not in('integer','smallint','bigint');
+ perform _pgr_onError(err, 2, fnName,
+ 'Wrong type of Column id:'|| idname, ' Expected type of '|| idname || ' is integer,smallint or bigint but '||idtype||' was found');
+
+ err = sourcetype not in('integer','smallint','bigint');
+ perform _pgr_onError(err, 2, fnName,
+ 'Wrong type of Column source:'|| sourcename, ' Expected type of '|| sourcename || ' is integer,smallint or bigint but '||sourcetype||' was found');
+
+ err = targettype not in('integer','smallint','bigint');
+ perform _pgr_onError(err, 2, fnName,
+ 'Wrong type of Column target:'|| targetname, ' Expected type of '|| targetname || ' is integer,smallint or bigint but '||targettype||' was found');
+
+ raise DEBUG ' --> OK';
+
+ raise debug 'Checking SRID of geometry column';
+ query= 'SELECT ST_SRID(' || quote_ident(gname) || ') as srid '
+ || ' FROM ' || _pgr_quote_ident(tabname)
+ || ' WHERE ' || quote_ident(gname)
+ || ' IS NOT NULL LIMIT 1';
+ raise debug '%',query;
+ EXECUTE query INTO sridinfo;
+
+ err = sridinfo IS NULL OR sridinfo.srid IS NULL;
+ perform _pgr_onError(err, 2, fnName,
+ 'Can not determine the srid of the geometry '|| gname ||' in table '||tabname, 'Check the geometry of column '||gname);
+
+ srid := sridinfo.srid;
+ raise DEBUG ' --> OK';
+
+ raise debug 'Checking and creating indices in edge table';
+ perform _pgr_createIndex(sname, tname , idname , 'btree'::text);
+ perform _pgr_createIndex(sname, tname , sourcename , 'btree'::text);
+ perform _pgr_createIndex(sname, tname , targetname , 'btree'::text);
+ perform _pgr_createIndex(sname, tname , gname , 'gist'::text);
+
+ gname=quote_ident(gname);
+ idname=quote_ident(idname);
+ sourcename=quote_ident(sourcename);
+ targetname=quote_ident(targetname);
+ raise DEBUG ' --> OK';
+
+
+
+
+
+ BEGIN
+ -- issue #193 & issue #210 & #213
+ -- this sql is for trying out the where clause
+ -- the select * is to avoid any colum name conflicts
+ -- limit 1, just try on first record
+ -- if the where clasuse is ill formed it will be catched in the exception
+ sql = 'select * from '||_pgr_quote_ident(tabname)||' WHERE true'||rows_where ||' limit 1';
+ EXECUTE sql into dummyRec;
+ -- end
+
+ -- if above where clasue works this one should work
+ -- any error will be catched by the exception also
+ sql = 'select count(*) from '||_pgr_quote_ident(tabname)||' WHERE (' || gname || ' IS NOT NULL AND '||
+ idname||' IS NOT NULL)=false '||rows_where;
+ EXECUTE SQL into notincluded;
+
+ if clean then
+ raise debug 'Cleaning previous Topology ';
+ execute 'UPDATE ' || _pgr_quote_ident(tabname) ||
+ ' SET '||sourcename||' = NULL,'||targetname||' = NULL';
+ else
+ raise debug 'Creating topology for edges with non assigned topology';
+ if rows_where=' AND (true)' then
+ rows_where= ' and ('||quote_ident(sourcename)||' is null or '||quote_ident(targetname)||' is null)';
+ end if;
+ end if;
+ -- my thoery is that the select Count(*) will never go thru here
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Got %', SQLERRM; -- issue 210,211
+ RAISE NOTICE 'ERROR: Condition is not correct, please execute the following query to test your condition';
+ RAISE NOTICE '%',sql;
+ RETURN 'FAIL';
+ END;
BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',idname,tabname;
- if (pgr_isColumnIndexed(tabname,idname)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding index "%_%_idx".',tabname,idname;
- set client_min_messages to warning;
- execute 'create index '||pgr_quote_ident(tname||'_'||idname||'_idx')||'
- on '||pgr_quote_ident(tabname)||' using btree('||quote_ident(idname)||')';
- execute 'set client_min_messages to '|| debuglevel;
- END IF;
- END;
-
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',sourcename,tabname;
- if (pgr_isColumnIndexed(tabname,sourcename)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding index "%_%_idx".',tabname,sourcename;
- set client_min_messages to warning;
- execute 'create index '||pgr_quote_ident(tname||'_'||sourcename||'_idx')||'
- on '||pgr_quote_ident(tabname)||' using btree('||quote_ident(sourcename)||')';
- execute 'set client_min_messages to '|| debuglevel;
- END IF;
- END;
-
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',targetname,tabname;
- if (pgr_isColumnIndexed(tabname,targetname)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding index "%_%_idx".',tabname,targetname;
- set client_min_messages to warning;
- execute 'create index '||pgr_quote_ident(tname||'_'||targetname||'_idx')||'
- on '||pgr_quote_ident(tabname)||' using btree('||quote_ident(targetname)||')';
- execute 'set client_min_messages to ' ||debuglevel;
- END IF;
- END;
-
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',gname,tabname;
- if (pgr_iscolumnindexed(tabname,gname)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding unique index "%_%_gidx".',tabname,gname;
- set client_min_messages to warning;
- execute 'CREATE INDEX '
- || quote_ident(tname || '_' || gname || '_gidx' )
- || ' ON ' || pgr_quote_ident(tabname)
- || ' USING gist (' || quote_ident(gname) || ')';
- execute 'set client_min_messages to '|| debuglevel;
- END IF;
- END;
- gname=quote_ident(gname);
- idname=quote_ident(idname);
- sourcename=quote_ident(sourcename);
- targetname=quote_ident(targetname);
-
-
-
- BEGIN
- raise DEBUG 'initializing %',vertname;
- execute 'select * from pgr_getTableName('||quote_literal(vertname)||')' into naming;
- IF sname=naming.sname AND vname=naming.tname THEN
- execute 'TRUNCATE TABLE '||pgr_quote_ident(vertname)||' RESTART IDENTITY';
- execute 'SELECT DROPGEOMETRYCOLUMN('||quote_literal(sname)||','||quote_literal(vname)||','||quote_literal('the_geom')||')';
- ELSE
- set client_min_messages to warning;
- execute 'CREATE TABLE '||pgr_quote_ident(vertname)||' (id bigserial PRIMARY KEY,cnt integer,chk integer,ein integer,eout integer)';
- END IF;
- execute 'select addGeometryColumn('||quote_literal(sname)||','||quote_literal(vname)||','||
- quote_literal('the_geom')||','|| srid||', '||quote_literal('POINT')||', 2)';
- execute 'CREATE INDEX '||quote_ident(vname||'_the_geom_idx')||' ON '||pgr_quote_ident(vertname)||' USING GIST (the_geom)';
- execute 'set client_min_messages to '|| debuglevel;
- raise DEBUG ' ------>OK';
+ if clean then
+ raise DEBUG 'initializing %',vertname;
+ execute 'select * from _pgr_getTableName('||quote_literal(vertname)
+ || ',0,' || quote_literal(fnName) ||' )' into naming;
+ set client_min_messages to warning;
+ IF sname=naming.sname AND vname=naming.tname THEN
+ execute 'TRUNCATE TABLE '||_pgr_quote_ident(vertname)||' RESTART IDENTITY';
+ execute 'SELECT DROPGEOMETRYCOLUMN('||quote_literal(sname)||','||quote_literal(vname)||','||quote_literal('the_geom')||')';
+ ELSE
+ execute 'CREATE TABLE '||_pgr_quote_ident(vertname)||' (id bigserial PRIMARY KEY,cnt integer,chk integer,ein integer,eout integer)';
+ END IF;
+ execute 'select addGeometryColumn('||quote_literal(sname)||','||quote_literal(vname)||','||
+ quote_literal('the_geom')||','|| srid||', '||quote_literal('POINT')||', 2)';
+
+ perform _pgr_createIndex(vertname , 'the_geom'::text , 'gist'::text);
+
+ execute 'set client_min_messages to '|| debuglevel;
+ else
+ execute 'select * from _pgr_checkVertTab('||quote_literal(vertname) ||', ''{"id"}''::text[])' into naming;
+ end if;
+ raise DEBUG ' ------>OK';
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Got %', SQLERRM; -- issue 210,211
+ RAISE NOTICE 'ERROR: something went wrong when initializing the verties table';
+ RETURN 'FAIL';
END;
-
- BEGIN
- sql = 'select * from '||pgr_quote_ident(tabname)||' WHERE true'||rows_where ||' limit 1';
- EXECUTE sql into i;
- sql = 'select count(*) from '||pgr_quote_ident(tabname)||' WHERE (' || gname || ' IS NOT NULL AND '||
- idname||' IS NOT NULL)=false '||rows_where;
- EXECUTE SQL into notincluded;
- EXCEPTION WHEN OTHERS THEN BEGIN
- RAISE NOTICE 'ERROR: Condition is not correct, please execute the following query to test your condition';
- RAISE NOTICE '%',sql;
- RETURN 'FAIL';
- END;
- END;
- BEGIN
raise notice 'Creating Topology, Please wait...';
- execute 'UPDATE ' || pgr_quote_ident(tabname) ||
- ' SET '||sourcename||' = NULL,'||targetname||' = NULL';
- rowcount := 0;
- FOR points IN EXECUTE 'SELECT ' || idname || '::bigint AS id,'
- || ' PGR_StartPoint(' || gname || ') AS source,'
- || ' PGR_EndPoint(' || gname || ') AS target'
- || ' FROM ' || pgr_quote_ident(tabname)
- || ' WHERE ' || gname || ' IS NOT NULL AND ' || idname||' IS NOT NULL '||rows_where
- LOOP
-
- rowcount := rowcount + 1;
- IF rowcount % 1000 = 0 THEN
- RAISE NOTICE '% edges processed', rowcount;
- END IF;
-
-
- source_id := pgr_pointToId(points.source, tolerance,vertname,srid);
- target_id := pgr_pointToId(points.target, tolerance,vertname,srid);
- BEGIN
- sql := 'UPDATE ' || pgr_quote_ident(tabname) ||
- ' SET '||sourcename||' = '|| source_id::text || ','||targetname||' = ' || target_id::text ||
- ' WHERE ' || idname || ' = ' || points.id::text;
-
- IF sql IS NULL THEN
- RAISE NOTICE 'WARNING: UPDATE % SET source = %, target = % WHERE % = % ', tabname, source_id::text, target_id::text, idname, points.id::text;
- ELSE
- EXECUTE sql;
- END IF;
- EXCEPTION WHEN OTHERS THEN
- RAISE NOTICE '%', SQLERRM;
- RAISE NOTICE '%',sql;
- RETURN 'FAIL';
- end;
- END LOOP;
- raise notice '-------------> TOPOLOGY CREATED FOR % edges', rowcount;
- RAISE NOTICE 'Rows with NULL geometry or NULL id: %',notincluded;
- Raise notice 'Vertices table for table % is: %',pgr_quote_ident(tabname),pgr_quote_ident(vertname);
- raise notice '----------------------------------------------';
- END;
- RETURN 'OK';
+ rowcount := 0;
+ FOR points IN EXECUTE 'SELECT ' || idname || '::bigint AS id,'
+ || ' _pgr_StartPoint(' || gname || ') AS source,'
+ || ' _pgr_EndPoint(' || gname || ') AS target'
+ || ' FROM ' || _pgr_quote_ident(tabname)
+ || ' WHERE ' || gname || ' IS NOT NULL AND ' || idname||' IS NOT NULL '||rows_where
+ LOOP
+
+ rowcount := rowcount + 1;
+ IF rowcount % 1000 = 0 THEN
+ RAISE NOTICE '% edges processed', rowcount;
+ END IF;
+
+
+ source_id := _pgr_pointToId(points.source, tolerance,vertname,srid);
+ target_id := _pgr_pointToId(points.target, tolerance,vertname,srid);
+ BEGIN
+ sql := 'UPDATE ' || _pgr_quote_ident(tabname) ||
+ ' SET '||sourcename||' = '|| source_id::text || ','||targetname||' = ' || target_id::text ||
+ ' WHERE ' || idname || ' = ' || points.id::text;
+
+ IF sql IS NULL THEN
+ RAISE NOTICE 'WARNING: UPDATE % SET source = %, target = % WHERE % = % ', tabname, source_id::text, target_id::text, idname, points.id::text;
+ ELSE
+ EXECUTE sql;
+ END IF;
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE '%', SQLERRM;
+ RAISE NOTICE '%',sql;
+ RETURN 'FAIL';
+ end;
+ END LOOP;
+ raise notice '-------------> TOPOLOGY CREATED FOR % edges', rowcount;
+ RAISE NOTICE 'Rows with NULL geometry or NULL id: %',notincluded;
+ Raise notice 'Vertices table for table % is: %',_pgr_quote_ident(tabname), _pgr_quote_ident(vertname);
+ raise notice '----------------------------------------------';
+ RETURN 'OK';
+ EXCEPTION WHEN OTHERS THEN
+ RAISE NOTICE 'Unexpected error %', SQLERRM; -- issue 210,211
+ RETURN 'FAIL';
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
-COMMENT ON FUNCTION pgr_createTopology(text, double precision,text,text,text,text,text)
+COMMENT ON FUNCTION pgr_createTopology(text, double precision,text,text,text,text,text,boolean)
IS 'args: edge_table,tolerance, the_geom:=''the_geom'',source:=''source'', target:=''target'',rows_where:=''true'' - fills columns source and target in the geometry table and creates a vertices table for selected rows';
-/*------------------------------------------------*/
-
-
-/*
-.. function:: pgr_createVerticesTable(edge_table text, the_geom text, source text default 'source', target text default 'target')
-
- Based on "source" and "target" columns creates the vetrices_pgr table for edge_table
- Ignores rows where "source" or "target" have NULL values
-
- Author: Vicky Vergara <vicky_vergara at hotmail,com>
-
- HISTORY
- Created 2013-08-19
-*/
-
-CREATE OR REPLACE FUNCTION pgr_createverticestable(edge_table text, the_geom text DEFAULT 'the_geom'::text, source text DEFAULT 'source'::text, target text DEFAULT 'target'::text, rows_where text DEFAULT 'true'::text)
- RETURNS text AS
-$BODY$
-DECLARE
- naming record;
- sridinfo record;
- sname text;
- tname text;
- tabname text;
- vname text;
- vertname text;
- gname text;
- sourcename text;
- targetname text;
- query text;
- ecnt integer;
- srid integer;
- sourcetype text;
- targettype text;
- sql text;
- totcount integer;
- i integer;
- notincluded integer;
- included integer;
- debuglevel text;
-
-BEGIN
- raise notice 'PROCESSING:';
- raise notice 'pgr_createVerticesTable(''%'',''%'',''%'',''%'',''%'')',edge_table,the_geom,source,target,rows_where;
- raise notice 'Performing checks, pelase wait .....';
- execute 'show client_min_messages' into debuglevel;
-
- BEGIN
- RAISE DEBUG 'Cheking % exists',edge_table;
- execute 'select * from pgr_getTableName('||quote_literal(edge_table)||')' into naming;
- sname=naming.sname;
- tname=naming.tname;
- IF sname IS NULL OR tname IS NULL THEN
- RAISE NOTICE '-------> % not found',edge_table;
- RETURN 'FAIL';
- ELSE
- RAISE DEBUG ' -----> OK';
- END IF;
-
- tabname=sname||'.'||tname;
- vname=tname||'_vertices_pgr';
- vertname= sname||'.'||vname;
- rows_where = ' AND ('||rows_where||')';
- END;
-
-
- BEGIN
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(the_geom)||')' INTO gname;
- raise DEBUG 'Checking geometry column "%" column in % ',the_geom,tabname;
- IF gname is not NULL then
- BEGIN
- raise DEBUG 'Checking the SRID of the geometry "%"', gname;
- EXECUTE 'SELECT ST_SRID(' || quote_ident(gname) || ') as srid '
- || ' FROM ' || pgr_quote_ident(tabname)
- || ' WHERE ' || quote_ident(gname)
- || ' IS NOT NULL LIMIT 1'
- INTO sridinfo;
-
- IF sridinfo IS NULL OR sridinfo.srid IS NULL THEN
- RAISE NOTICE 'ERROR: Can not determine the srid of the geometry "%" in table %', the_geom,tabname;
- RETURN 'FAIL';
- END IF;
- srid := sridinfo.srid;
- raise DEBUG ' -----> SRID found %',srid;
- EXCEPTION WHEN OTHERS THEN
- RAISE NOTICE 'ERROR: Can not determine the srid of the geometry "%" in table %', the_geom,tabname;
- RETURN 'FAIL';
- END;
- ELSE
- raise notice 'ERROR: Geometry column "%" not found in %',the_geom,tabname;
- RETURN 'FAIL';
- END IF;
- END;
-
- BEGIN
- raise DEBUG 'Checking source column "%" and target column "%" in % ',source,target,tabname;
- IF source=target THEN
- raise notice 'ERROR: source and target columns have the same name "%" in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(source)||')' INTO sourcename;
- EXECUTE 'select pgr_getColumnName('||quote_literal(tabname)||','||quote_literal(target)||')' INTO targetname;
- IF sourcename is not NULL and targetname is not NULL then
- --check that the are integer
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(sourcename) into sourcetype;
- EXECUTE 'select data_type from information_schema.columns where table_name = '||quote_literal(tname)||
- ' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(targetname) into targettype;
- IF sourcetype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: source column "%" is not of integer type',sourcename;
- RETURN 'FAIL';
- END IF;
- IF targettype not in('integer','smallint','bigint') THEN
- raise notice 'ERROR: target column "%" is not of integer type',targetname;
- RETURN 'FAIL';
- END IF;
- raise DEBUG ' ------>OK ';
- END IF;
- IF sourcename is NULL THEN
- raise notice 'ERROR: source column "%" not found in %',source,tabname;
- RETURN 'FAIL';
- END IF;
- IF targetname is NULL THEN
- raise notice 'ERROR: target column "%" not found in %',target,tabname;
- RETURN 'FAIL';
- END IF;
- END;
-
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',sourcename,tabname;
- if (pgr_isColumnIndexed(tabname,sourcename)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding index "%_%_idx".',tabname,sourcename;
- set client_min_messages to warning;
- execute 'create index '||pgr_quote_ident(tname||'_'||sourcename||'_idx')||'
- on '||pgr_quote_ident(tabname)||' using btree('||quote_ident(sourcename)||')';
- execute 'set client_min_messages to '|| debuglevel;
- END IF;
- END;
-
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',targetname,tabname;
- if (pgr_isColumnIndexed(tabname,targetname)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding index "%_%_idx".',tabname,targetname;
- set client_min_messages to warning;
- execute 'create index '||pgr_quote_ident(tname||'_'||targetname||'_idx')||'
- on '||pgr_quote_ident(tabname)||' using btree('||quote_ident(targetname)||')';
- execute 'set client_min_messages to '|| debuglevel;
- END IF;
- END;
-
- BEGIN
- RAISE DEBUG 'Cheking "%" column in % is indexed',gname,tabname;
- if (pgr_iscolumnindexed(tabname,gname)) then
- RAISE DEBUG ' ------>OK';
- else
- RAISE DEBUG ' ------> Adding unique index "%_%_gidx".',tabname,gname;
- set client_min_messages to warning;
- execute 'CREATE INDEX '
- || quote_ident(tname || '_' || gname || '_gidx' )
- || ' ON ' || pgr_quote_ident(tabname)
- || ' USING gist (' || quote_ident(gname) || ')';
- execute 'set client_min_messages to '|| debuglevel;
- END IF;
- END;
- gname=quote_ident(gname);
- sourcename=quote_ident(sourcename);
- targetname=quote_ident(targetname);
-
-
-
-
- BEGIN
- raise DEBUG 'initializing %',vertname;
- execute 'select * from pgr_getTableName('||quote_literal(vertname)||')' into naming;
- IF sname=naming.sname AND vname=naming.tname THEN
- execute 'TRUNCATE TABLE '||pgr_quote_ident(vertname)||' RESTART IDENTITY';
- execute 'SELECT DROPGEOMETRYCOLUMN('||quote_literal(sname)||','||quote_literal(vname)||','||quote_literal('the_geom')||')';
- ELSE
- set client_min_messages to warning;
- execute 'CREATE TABLE '||pgr_quote_ident(vertname)||' (id bigserial PRIMARY KEY,cnt integer,chk integer,ein integer,eout integer)';
- END IF;
- execute 'select addGeometryColumn('||quote_literal(sname)||','||quote_literal(vname)||','||
- quote_literal('the_geom')||','|| srid||', '||quote_literal('POINT')||', 2)';
- execute 'CREATE INDEX '||quote_ident(vname||'_the_geom_idx')||' ON '||pgr_quote_ident(vertname)||' USING GIST (the_geom)';
- execute 'set client_min_messages to '|| debuglevel;
- raise DEBUG ' ------>OK';
- END;
-
- BEGIN
- sql = 'select * from '||pgr_quote_ident(tabname)||' WHERE true'||rows_where||' limit 1';
- EXECUTE sql into i;
- sql = 'select count(*) from '||pgr_quote_ident(tabname)||' WHERE (' || gname || ' IS NULL or '||
- sourcename||' is null or '||targetname||' is null)=true '||rows_where;
- raise debug '%',sql;
- EXECUTE SQL into notincluded;
- EXCEPTION WHEN OTHERS THEN BEGIN
- RAISE NOTICE 'ERROR: Condition is not correct, please execute the following query to test your condition';
- RAISE NOTICE '%',sql;
- RETURN 'FAIL';
- END;
- END;
-
-
- BEGIN
- raise notice 'Populating %, please wait...',vertname;
- sql= 'with
- lines as ((select distinct '||sourcename||' as id, pgr_startpoint(st_linemerge('||gname||')) as the_geom from '||pgr_quote_ident(tabname)||
- ' where ('|| gname || ' IS NULL
- or '||sourcename||' is null
- or '||targetname||' is null)=false
- '||rows_where||')
- union (select distinct '||targetname||' as id,pgr_endpoint(st_linemerge('||gname||')) as the_geom from '||pgr_quote_ident(tabname)||
- ' where ('|| gname || ' IS NULL
- or '||sourcename||' is null
- or '||targetname||' is null)=false
- '||rows_where||'))
- ,numberedLines as (select row_number() OVER (ORDER BY id) AS i,* from lines )
- ,maxid as (select id,max(i) as maxi from numberedLines group by id)
- insert into '||pgr_quote_ident(vertname)||'(id,the_geom) (select id,the_geom from numberedLines join maxid using(id) where i=maxi order by id)';
- RAISE debug '%',sql;
- execute sql;
- GET DIAGNOSTICS totcount = ROW_COUNT;
-
- sql = 'select count(*) from '||pgr_quote_ident(tabname)||' a, '||pgr_quote_ident(vertname)||' b
- where '||sourcename||'=b.id and '|| targetname||' in (select id from '||pgr_quote_ident(vertname)||')';
- RAISE debug '%',sql;
- execute sql into included;
-
-
-
- execute 'select max(id) from '||pgr_quote_ident(vertname) into ecnt;
- execute 'SELECT setval('||quote_literal(vertname||'_id_seq')||','||coalesce(ecnt,1)||' , false)';
- raise notice ' -----> VERTICES TABLE CREATED WITH % VERTICES', totcount;
- raise notice ' FOR % EDGES', included+notincluded;
- RAISE NOTICE ' Edges with NULL geometry,source or target: %',notincluded;
- RAISE NOTICE ' Edges processed: %',included;
- Raise notice 'Vertices table for table % is: %',pgr_quote_ident(tabname),pgr_quote_ident(vertname);
- raise notice '----------------------------------------------';
- END;
-
- RETURN 'OK';
-END;
-$BODY$
- LANGUAGE plpgsql VOLATILE STRICT;
-
-COMMENT ON FUNCTION pgr_createVerticesTable(text,text,text,text,text)
-IS 'args: edge_table, the_geom:=''the_geom'',source:=''source'', target:=''target'' rows_where:=''true'' - creates a vertices table based on the source and target identifiers for selected rows';
diff --git a/src/common/sql/pgrouting_utilities.sql b/src/common/sql/pgrouting_utilities.sql
index faf1396..84b9c81 100644
--- a/src/common/sql/pgrouting_utilities.sql
+++ b/src/common/sql/pgrouting_utilities.sql
@@ -1,24 +1,25 @@
-- -------------------------------------------------------------------
-- pgrouting_utilities.sql
--- AuthorL Stephen Woodbridge <woodbri at imaptools.com>
--- Copyright 2013 Stephen Woodbridge
+-- Author Vicky Vergara <vicky_vergara at hotmail.com>
+-- Copyright 2015 Vicky Vergara
-- This file is release unde an MIT-X license.
-- -------------------------------------------------------------------
+
/*
-.. function:: pgr_getTableName(tab)
-
- Examples:
- * select * from pgr_getTableName('tab');
+.. function:: _pgr_getTableName(tab)
+
+ Examples:
+ * select * from _pgr_getTableName('tab');
* naming record;
- excecute 'select * from pgr_getTableName('||quote_literal(tab)||')' INTO naming;
- schema=naming.sname; table=naming.tname
-
+ excecute 'select * from _pgr_getTableName('||quote_literal(tab)||')' INTO naming;
+ schema=naming.sname; table=naming.tname
+
Returns (schema,name) of table "tab" considers Caps and when not found considers lowercases
- (schema,NULL) when table was not found
- (NULL,NULL) when schema was not found.
+ (schema,NULL) when table was not found
+ (NULL,NULL) when schema was not found.
Author: Vicky Vergara <vicky_vergara at hotmail.com>>
@@ -26,87 +27,132 @@
Created: 2013/08/19 for handling schemas
*/
-CREATE OR REPLACE FUNCTION pgr_getTableName(IN tab text,OUT sname text,OUT tname text)
+
+
+CREATE OR REPLACE FUNCTION _pgr_getTableName(IN tab text, IN reportErrs int default 0, IN fnName text default '_pgr_getTableName', OUT sname text,OUT tname text)
RETURNS RECORD AS
-$BODY$
+$BODY$
DECLARE
- naming record;
- i integer;
- query text;
+ naming record;
+ i integer;
+ query text;
sn text;
tn text;
+ err boolean;
+ debuglevel text;
BEGIN
+ execute 'show client_min_messages' into debuglevel;
+
+
+ perform _pgr_msg( 0, fnName, 'Checking table ' || tab || ' exists');
+ --RAISE DEBUG 'Checking % exists',tab;
+
execute 'select strpos('||quote_literal(tab)||','||quote_literal('.')||')' into i;
- if (i!=0) then
- execute 'select substr('||quote_literal(tab)||',1,strpos('||quote_literal(tab)||','||quote_literal('.')||')-1)' into sn;
- execute 'select substr('||quote_literal(tab)||',strpos('||quote_literal(tab)||','||quote_literal('.')||')+1),length('||quote_literal(tab)||')' into tn;
- else
+ if (i!=0) then
+ execute 'select substr('||quote_literal(tab)||',1,strpos('||quote_literal(tab)||','||quote_literal('.')||')-1)' into sn;
+ execute 'select substr('||quote_literal(tab)||',strpos('||quote_literal(tab)||','||quote_literal('.')||')+1),length('||quote_literal(tab)||')' into tn;
+ else
execute 'select current_schema' into sn;
tn =tab;
end if;
-
-
+
+
EXECUTE 'SELECT schema_name FROM information_schema.schemata WHERE schema_name = '||quote_literal(sn) into naming;
sname=naming.schema_name;
-
+
if sname is NOT NULL THEN -- found schema (as is)
- EXECUTE 'select table_name from information_schema.tables where
- table_type='||quote_literal('BASE TABLE')||' and
- table_schema='||quote_literal(sname)||' and
- table_name='||quote_literal(tn) INTO naming;
- tname=naming.table_name;
- IF tname is NULL THEN
- EXECUTE 'select table_name from information_schema.tables where
- table_type='||quote_literal('BASE TABLE')||' and
- table_schema='||quote_literal(sname)||' and
- table_name='||quote_literal(lower(tn))||'order by table_name' INTO naming;
- tname=naming.table_name;
- END IF;
- END IF;
- IF sname is NULL or tname is NULL THEN --schema not found or table in schema was not found
- EXECUTE 'SELECT schema_name FROM information_schema.schemata WHERE schema_name = '||quote_literal(lower(sn)) into naming;
- sname=naming.schema_name;
- if sname is NOT NULL THEN -- found schema (with lower caps)
- EXECUTE 'select table_name from information_schema.tables where
- table_type='||quote_literal('BASE TABLE')||' and
- table_schema='||quote_literal(sname)||' and
- table_name='||quote_literal(tn) INTO naming;
- tname=naming.table_name;
- IF tname is NULL THEN
- EXECUTE 'select table_name from information_schema.tables where
- table_type='||quote_literal('BASE TABLE')||' and
- table_schema='||quote_literal(sname)||' and
- table_name='||quote_literal(lower(tn))||'order by table_name' INTO naming;
- tname=naming.table_name;
- END IF;
- END IF;
- END IF;
-
+ EXECUTE 'select table_name from information_schema.tables where
+ table_type='||quote_literal('BASE TABLE')||' and
+ table_schema='||quote_literal(sname)||' and
+ table_name='||quote_literal(tn) INTO naming;
+ tname=naming.table_name;
+ IF tname is NULL THEN
+ EXECUTE 'select table_name from information_schema.tables where
+ table_type='||quote_literal('BASE TABLE')||' and
+ table_schema='||quote_literal(sname)||' and
+ table_name='||quote_literal(lower(tn))||'order by table_name' INTO naming;
+ tname=naming.table_name;
+ END IF;
+ END IF;
+ IF sname is NULL or tname is NULL THEN --schema not found or table in schema was not found
+ EXECUTE 'SELECT schema_name FROM information_schema.schemata WHERE schema_name = '||quote_literal(lower(sn)) into naming;
+ sname=naming.schema_name;
+ if sname is NOT NULL THEN -- found schema (with lower caps)
+ EXECUTE 'select table_name from information_schema.tables where
+ table_type='||quote_literal('BASE TABLE')||' and
+ table_schema='||quote_literal(sname)||' and
+ table_name='||quote_literal(tn) INTO naming;
+ tname=naming.table_name;
+ IF tname is NULL THEN
+ EXECUTE 'select table_name from information_schema.tables where
+ table_type='||quote_literal('BASE TABLE')||' and
+ table_schema='||quote_literal(sname)||' and
+ table_name='||quote_literal(lower(tn))||'order by table_name' INTO naming;
+ tname=naming.table_name;
+ END IF;
+ END IF;
+ END IF;
+ err = case when sname IS NULL OR tname IS NULL then true else false end;
+ perform _pgr_onError(err, reportErrs, fnName, 'Table ' || tab ||' not found',' Check your table name', 'Table '|| tab || ' found');
+
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
-COMMENT ON FUNCTION pgr_getTableName(text) IS 'args: tab -gets the schema (sname) and the table (tname) form the table tab';
+
/*
-.. function:: pgr_getColumnName(tab,col)
-
- Examples:
- * select pgr_getColumnName('tab','col');
- * column text;
- excecute 'select pgr_getColumnName('||quote_literal('tab')||','||quote_literal('col')||')' INTO column;
+.. function:: _pgr_getColumnName(sname,tname,col,reportErrs default 1) returns text
+.. function:: _pgr_getColumnName(tab,col,reportErrs default 1) returns text
+ Returns:
+ cname registered column "col" in table "tab" or "sname.tname" considers Caps and when not found considers lowercases
+ NULL when "tab"/"sname"/"tname" is not found or when "col" is not in table "tab"/"sname.tname"
+ unless otherwise indicated raises notices on errors
- Returns cname of column "col" in table "tab" considers Caps and when not found considers lowercases
- NULL when "tab" is not found or when "col" is not in table "tab"
+ Examples:
+ * select _pgr_getColumnName('tab','col');
+ * select _pgr_getColumnName('myschema','mytable','col');
+ excecute 'select _pgr_getColumnName('||quote_literal('tab')||','||quote_literal('col')||')' INTO column;
+ excecute 'select _pgr_getColumnName('||quote_literal(sname)||','||quote_literal(sname)||','||quote_literal('col')||')' INTO column;
Author: Vicky Vergara <vicky_vergara at hotmail.com>>
HISTORY
Created: 2013/08/19 for handling schemas
+ Modified: 2014/JUL/28 added overloadig
*/
-CREATE OR REPLACE FUNCTION pgr_getColumnName(tab text, col text)
+
+
+CREATE OR REPLACE FUNCTION _pgr_getColumnName(sname text, tname text, col text, IN reportErrs int default 1, IN fnName text default '_pgr_getColumnName')
+RETURNS text AS
+$BODY$
+DECLARE
+ cname text;
+ naming record;
+ err boolean;
+BEGIN
+
+ execute 'SELECT column_name FROM information_schema.columns
+ WHERE table_name='||quote_literal(tname)||' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(col) into cname;
+
+ IF cname is null THEN
+ execute 'SELECT column_name FROM information_schema.columns
+ WHERE table_name='||quote_literal(tname)||' and table_schema='||quote_literal(sname)||' and column_name='||quote_literal(lower(col)) into cname;
+ END if;
+
+ err = cname is null;
+
+ perform _pgr_onError(err, reportErrs, fnName, 'Column '|| col ||' not found', ' Check your column name','Column '|| col || ' found');
+ RETURN cname;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+
+
+CREATE OR REPLACE FUNCTION _pgr_getColumnName(tab text, col text, IN reportErrs int default 1, IN fnName text default '_pgr_getColumnName')
RETURNS text AS
$BODY$
DECLARE
@@ -114,47 +160,27 @@ DECLARE
tname text;
cname text;
naming record;
+ err boolean;
BEGIN
- select * into naming from pgr_getTableName(tab) ;
+ select * into naming from _pgr_getTableName(tab,reportErrs, fnName) ;
sname=naming.sname;
tname=naming.tname;
-
- IF sname IS NULL or tname IS NULL THEN
- RETURN NULL;
- ELSE
- SELECT column_name INTO cname
- FROM information_schema.columns
- WHERE table_name=tname and table_schema=sname and column_name=col;
-
- IF FOUND THEN
- RETURN cname;
- ELSE
- SELECT column_name INTO cname
- FROM information_schema.columns
- WHERE table_name=tname and table_schema=sname and column_name=lower(col);
- IF FOUND THEN
- RETURN cname;
- ELSE
- RETURN NULL;
- END IF;
- END IF;
- END IF;
+
+ select * into cname from _pgr_getColumnName(sname,tname,col,reportErrs, fnName);
+ RETURN cname;
END;
+
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
-COMMENT ON FUNCTION pgr_getColumnName(text,text) IS 'args: tab,col -gets the registered column name of "col" in table "tab"';
-
-
-
/*
-.. function:: pgr_isColumnInTable(tab, col)
+.. function:: _pgr_isColumnInTable(tab, col)
- Examples:
- * select pgr_isColumnName('tab','col');
+ Examples:
+ * select _pgr_isColumnName('tab','col');
* flag boolean;
- excecute 'select pgr_getColumnName('||quote_literal('tab')||','||quote_literal('col')||')' INTO flag;
+ excecute 'select _pgr_getColumnName('||quote_literal('tab')||','||quote_literal('col')||')' INTO flag;
Returns true if column "col" exists in table "tab"
false when "tab" doesn't exist or when "col" is not in table "tab"
@@ -166,82 +192,62 @@ COMMENT ON FUNCTION pgr_getColumnName(text,text) IS 'args: tab,col -gets the re
HISTORY
Modified: 2013/08/19 for handling schemas
*/
-CREATE OR REPLACE FUNCTION pgr_isColumnInTable(tab text, col text)
+CREATE OR REPLACE FUNCTION _pgr_isColumnInTable(tab text, col text)
RETURNS boolean AS
$BODY$
DECLARE
cname text;
BEGIN
- select * from pgr_getColumnName(tab,col) into cname;
-
- IF cname IS NULL THEN
- RETURN false;
- ELSE
- RETURN true;
- END IF;
+ select * from _pgr_getColumnName(tab,col,0, '_pgr_isColumnInTable') into cname;
+ return cname is not null;
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
-COMMENT ON FUNCTION pgr_isColumnInTable(text,text) IS 'args: tab,col -returns true when the column "col" is in table "tab"';
/*
-.. function:: pgr_isColumnIndexed(tab, col)
+.. function:: _pgr_isColumnIndexed(tab, col)
- Examples:
- * select pgr_isColumnIndexed('tab','col');
+ Examples:
+ * select _pgr_isColumnIndexed('tab','col');
* flag boolean;
- excecute 'select pgr_getColumnIndexed('||quote_literal('tab')||','||quote_literal('col')||')' INTO flag;
+ excecute 'select _pgr_getColumnIndexed('||quote_literal('tab')||','||quote_literal('col')||')' INTO flag;
Author: Stephen Woodbridge <woodbri at imaptools.com>
Modified by: Vicky Vergara <vicky_vergara at hotmail.com>>
Returns true when column "col" in table "tab" is indexed.
- false when table "tab" is not found or
+ false when table "tab" is not found or
when column "col" is nor found in table "tab" or
- when column "col" is not indexed
-
+ when column "col" is not indexed
*/
-CREATE OR REPLACE FUNCTION public.pgr_isColumnIndexed(tab text, col text)
+
+CREATE OR REPLACE FUNCTION _pgr_isColumnIndexed(sname text, tname text, cname text,
+ IN reportErrs int default 1, IN fnName text default '_pgr_isColumnIndexed')
RETURNS boolean AS
$BODY$
DECLARE
naming record;
rec record;
- sname text;
- tname text;
- cname text;
pkey text;
BEGIN
- SELECT * into naming FROM pgr_getTableName(tab);
- sname=naming.sname;
- tname=naming.tname;
- IF sname IS NULL OR tname IS NULL THEN
- RETURN FALSE;
- END IF;
- SELECT pgr_getColumnName(tab,col) INTO cname;
- IF cname IS NULL THEN
- RETURN FALSE;
- END IF;
- SELECT
+ SELECT
pg_attribute.attname into pkey
- -- format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
- FROM pg_index, pg_class, pg_attribute
- WHERE
- pg_class.oid = pgr_quote_ident(sname||'.'||tname)::regclass AND
+ -- format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
+ FROM pg_index, pg_class, pg_attribute
+ WHERE
+ pg_class.oid = _pgr_quote_ident(sname||'.'||tname)::regclass AND
indrelid = pg_class.oid AND
- pg_attribute.attrelid = pg_class.oid AND
+ pg_attribute.attrelid = pg_class.oid AND
pg_attribute.attnum = any(pg_index.indkey)
AND indisprimary;
-
+
IF pkey=cname then
- RETURN TRUE;
+ RETURN TRUE;
END IF;
-
-
- SELECT a.index_name,
+ SELECT a.index_name,
b.attname,
b.attnum,
a.indisunique,
@@ -249,56 +255,80 @@ BEGIN
INTO rec
FROM ( SELECT a.indrelid,
a.indisunique,
- a.indisprimary,
- c.relname index_name,
- unnest(a.indkey) index_num
+ a.indisprimary,
+ c.relname index_name,
+ unnest(a.indkey) index_num
FROM pg_index a,
- pg_class b,
+ pg_class b,
pg_class c,
- pg_namespace d
+ pg_namespace d
WHERE b.relname=tname
AND b.relnamespace=d.oid
- AND d.nspname=sname
- AND b.oid=a.indrelid
- AND a.indexrelid=c.oid
- ) a,
- pg_attribute b
- WHERE a.indrelid = b.attrelid
- AND a.index_num = b.attnum
+ AND d.nspname=sname
+ AND b.oid=a.indrelid
+ AND a.indexrelid=c.oid
+ ) a,
+ pg_attribute b
+ WHERE a.indrelid = b.attrelid
+ AND a.index_num = b.attnum
AND b.attname = cname
- ORDER BY a.index_name,
+ ORDER BY a.index_name,
a.index_num;
- IF FOUND THEN
- RETURN true;
- ELSE
- RETURN false;
- END IF;
+ RETURN FOUND;
+ EXCEPTION WHEN OTHERS THEN
+ perform _pgr_onError( true, reportErrs, fnName,
+ 'Error when checking for the postgres system attributes', SQLERR);
+ RETURN FALSE;
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
-COMMENT ON FUNCTION pgr_isColumnIndexed(text,text) IS 'args: tab,col -returns true if column "col" in table "tab" is indexed';
-
-
-
+CREATE OR REPLACE FUNCTION _pgr_isColumnIndexed(tab text, col text,
+ IN reportErrs int default 1, IN fnName text default '_pgr_isColumnIndexed')
+RETURNS boolean AS
+$BODY$
+DECLARE
+ naming record;
+ rec record;
+ sname text;
+ tname text;
+ cname text;
+ pkey text;
+ value boolean;
+BEGIN
+ SELECT * into naming FROM _pgr_getTableName(tab, 0, fnName);
+ sname=naming.sname;
+ tname=naming.tname;
+ IF sname IS NULL OR tname IS NULL THEN
+ RETURN FALSE;
+ END IF;
+ SELECT * into cname from _pgr_getColumnName(sname, tname, col, 0, fnName) ;
+ IF cname IS NULL THEN
+ RETURN FALSE;
+ END IF;
+ select * into value from _pgr_isColumnIndexed(sname, tname, cname, reportErrs, fnName);
+ return value;
+END
+$BODY$
+ LANGUAGE plpgsql VOLATILE STRICT;
-create or replace function pgr_quote_ident(idname text)
- returns text as
-$body$
/*
-.. function:: pgr_quote_ident(text)
+.. function:: _pgr_quote_ident(text)
Author: Stephen Woodbridge <woodbri at imaptools.com>
- Function to split a string on '.' characters and then quote the
+ Function to split a string on '.' characters and then quote the
components as postgres identifiers and then join them back together
with '.' characters. multile '.' will get collapsed into a single
- '.' so 'schema...table' till get returned as 'schema."table"' and
+ '.' so 'schema...table' till get returned as 'schema."table"' and
'Schema.table' becomes '"Schema'.'table"'
*/
+create or replace function _pgr_quote_ident(idname text)
+ returns text as
+$body$
declare
t text[];
pgver text;
@@ -306,12 +336,7 @@ declare
begin
pgver := regexp_replace(version(), E'^PostgreSQL ([^ ]+)[ ,].*$', E'\\1');
-/*
- RAISE NOTICE 'pgr_quote_ident(%), pgver: %, version: %, versionless %',
- tab, pgver, version(), pgr_versionless(pgver, '9.2');
-*/
-
- if pgr_versionless(pgver, '9.2') then
+ if _pgr_versionless(pgver, '9.2') then
select into t array_agg(quote_ident(term)) from
(select nullif(unnest, '') as term
from unnest(string_to_array(idname, '.'))) as foo;
@@ -323,21 +348,20 @@ begin
end;
$body$
language plpgsql immutable;
-COMMENT ON function pgr_quote_ident(text) IS 'args: idname - quote_ident to all parts of the identifier "idname"';
-
-CREATE OR REPLACE FUNCTION pgr_versionless(v1 text, v2 text)
- RETURNS boolean AS
-$BODY$
/*
* function for comparing version strings.
- * Ex: select pgr_version_less(postgis_lib_version(), '2.1');
+ * Ex: select _pgr_version_less(postgis_lib_version(), '2.1');
Author: Stephen Woodbridge <woodbri at imaptools.com>
*
* needed because postgis 2.1 deprecates some function names and
* we need to detect the version at runtime
*/
+CREATE OR REPLACE FUNCTION _pgr_versionless(v1 text, v2 text)
+ RETURNS boolean AS
+$BODY$
+
declare
v1a text[];
@@ -346,7 +370,7 @@ declare
nv2 integer;
ne1 integer;
ne2 integer;
-
+
begin
-- separate components into an array, like:
-- '2.1.0-beta3dev' => {2,1,0,beta3dev}
@@ -372,8 +396,8 @@ begin
nv1 := v1a[1]::integer * 10000 +
coalesce(v1a[2], '0')::integer * 1000 +
coalesce(v1a[3], '0')::integer * 100 + ne1;
- nv2 := v2a[1]::integer * 10000 +
- coalesce(v2a[2], '0')::integer * 1000 +
+ nv2 := v2a[1]::integer * 10000 +
+ coalesce(v2a[2], '0')::integer * 1000 +
coalesce(v2a[3], '0')::integer * 100 + ne2;
--raise notice 'nv1: %, nv2: %, ne1: %, ne2: %', nv1, nv2, ne1, ne2;
@@ -383,10 +407,8 @@ end;
$BODY$
LANGUAGE plpgsql IMMUTABLE STRICT
COST 1;
-COMMENT ON function pgr_versionless(text,text) IS 'args: v1,v2 - returns true when v1 < v2';
-
-create or replace function pgr_startPoint(g geometry)
+create or replace function _pgr_startPoint(g geometry)
returns geometry as
$body$
declare
@@ -400,11 +422,10 @@ begin
end;
$body$
language plpgsql IMMUTABLE;
-COMMENT ON function pgr_startPoint(geometry) IS 'args: g - returns start point of the geometry "g" even if its multi';
-create or replace function pgr_endPoint(g geometry)
+create or replace function _pgr_endPoint(g geometry)
returns geometry as
$body$
declare
@@ -418,5 +439,4 @@ begin
end;
$body$
language plpgsql IMMUTABLE;
-COMMENT ON function pgr_endPoint(geometry) IS 'args: g - returns end point of the geometry "g" even if its multi';
diff --git a/src/common/sql/pgrouting_version.sql b/src/common/sql/pgrouting_version.sql
index 33f8244..667abe5 100644
--- a/src/common/sql/pgrouting_version.sql
+++ b/src/common/sql/pgrouting_version.sql
@@ -1,3 +1,10 @@
+-- -------------------------------------------------------------------
+-- pgrouting_utilities.sql
+-- AuthorL Stephen Woodbridge <woodbri at imaptools.com>
+-- Copyright 2013 Stephen Woodbridge
+-- This file is release unde an MIT-X license.
+-- -------------------------------------------------------------------
+
CREATE OR REPLACE FUNCTION pgr_version()
RETURNS TABLE(
"version" varchar,
diff --git a/src/common/sql/utilities_pgr.sql b/src/common/sql/utilities_pgr.sql
new file mode 100644
index 0000000..bf98491
--- /dev/null
+++ b/src/common/sql/utilities_pgr.sql
@@ -0,0 +1,341 @@
+/*PGR
+ utilities_pgr.sql
+
+ Copyright (c) 2015 Celia Virginia Vergara Castillo
+ vicky_vergara at hotmail.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.
+
+*/
+
+
+/************************************************************************
+.. function:: _pgr_onError(errCond,reportErrs,functionname,msgerr,hinto,msgok)
+
+ If the error condition is is true, i.e., there is an error,
+ it will raise a message based on the reportErrs:
+ 0: debug_ raise debug_
+ 1: report raise notice
+ 2: abort throw a raise_exception
+ Examples:
+
+ * preforn _pgr_onError( idname=gname, 2, 'pgr_createToplogy',
+ 'Two columns share the same name');
+ * preforn _pgr_onError( idname=gname, 2, 'pgr_createToplogy',
+ 'Two columns share the same name', 'Idname and gname must be different');
+ * preforn _pgr_onError( idname=gname, 2, 'pgr_createToplogy',
+ 'Two columns share the same name', 'Idname and gname must be different',
+ 'Column names are OK');
+
+
+ Author: Vicky Vergara <vicky_vergara at hotmail.com>>
+
+ HISTORY
+ Created: 2014/JUl/28 handling the errors, and have a more visual output
+
+************************************************************************/
+
+CREATE OR REPLACE FUNCTION _pgr_onError(
+ IN errCond boolean, -- true there is an error
+ IN reportErrs int, -- 0, 1 or 2
+ IN fnName text, -- function name that generates the error
+ IN msgerr text, -- error message
+ IN hinto text default 'No hint', -- hint help
+ IN msgok text default 'OK') -- message if everything is ok
+ RETURNS void AS
+$BODY$
+BEGIN
+ if errCond=true then
+ if reportErrs=0 then
+ raise debug '----> PGR DEBUG in %: %',fnName,msgerr USING HINT = ' ---->'|| hinto;
+ else
+ if reportErrs = 2 then
+ raise notice '----> PGR ERROR in %: %',fnName,msgerr USING HINT = ' ---->'|| hinto;
+ raise raise_exception;
+ else
+ raise notice '----> PGR NOTICE in %: %',fnName,msgerr USING HINT = ' ---->'|| hinto;
+ end if;
+ end if;
+ else
+ raise debug 'PGR ----> %: %',fnName,msgok;
+ end if;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+/************************************************************************
+.. function:: _pgr_msg(msgKind, fnName, msg)
+
+ It will raise a message based on the msgKind:
+ 0: debug_ raise debug_
+ 1: notice raise notice
+ anything else: report raise notice
+
+ Examples:
+
+ * preforn _pgr_msg( 1, 'pgr_createToplogy', 'Starting a long process... ');
+ * preforn _pgr_msg( 1, 'pgr_createToplogy');
+
+
+ Author: Vicky Vergara <vicky_vergara at hotmail.com>>
+
+ HISTORY
+ Created: 2014/JUl/28 handling the errors, and have a more visual output
+
+************************************************************************/
+
+CREATE OR REPLACE FUNCTION _pgr_msg(IN msgKind int, IN fnName text, IN msg text default '---->OK')
+ RETURNS void AS
+$BODY$
+BEGIN
+ if msgKind = 0 then
+ raise debug '----> PGR DEBUG in %: %',fnName,msg;
+ else
+ raise notice '----> PGR NOTICE in %: %',fnName,msg;
+ end if;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+
+/************************************************************************
+.. function:: _pgr_getColumnType(sname,tname,col,reportErrs,fnName) returns text
+.. function:: _pgr_getColumnType(tab,col,reportErrs,fname) returns text
+
+ Returns:
+ type the types of the registered column "col" in table "tab" or "sname.tname"
+ NULL when "tab"/"sname"/"tname" is not found or when "col" is not in table "tab"/"sname.tname"
+ unless otherwise indicated raises debug_ on errors
+
+ Examples:
+ * select _pgr_getColumnType('tab','col');
+ * select _pgr_getColumnType('myschema','mytable','col');
+ excecute 'select _pgr_getColumnType('||quote_literal('tab')||','||quote_literal('col')||')' INTO column;
+ excecute 'select _pgr_getColumnType('||quote_literal(sname)||','||quote_literal(sname)||','||quote_literal('col')||')' INTO column;
+
+ Author: Vicky Vergara <vicky_vergara at hotmail.com>>
+
+ HISTORY
+ Created: 2014/JUL/28
+************************************************************************/
+
+CREATE OR REPLACE FUNCTION _pgr_getColumnType(sname text, tname text, cname text,
+ IN reportErrs int default 0, IN fnName text default '_pgr_getColumnType')
+RETURNS text AS
+$BODY$
+DECLARE
+ ctype text;
+ naming record;
+ err boolean;
+BEGIN
+
+ EXECUTE 'select data_type from information_schema.columns '
+ || 'where table_name = '||quote_literal(tname)
+ || ' and table_schema=' || quote_literal(sname)
+ || ' and column_name='||quote_literal(cname)
+ into ctype;
+ err = ctype is null;
+ perform _pgr_onError(err, reportErrs, fnName,
+ 'Type of Column '|| cname ||' not found',
+ 'Check your column name',
+ 'OK: Type of Column '|| cname || ' is ' || ctype);
+ RETURN ctype;
+END;
+
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+
+CREATE OR REPLACE FUNCTION _pgr_getColumnType(tab text, col text,
+ IN reportErrs int default 0, IN fnName text default '_pgr_getColumnType')
+RETURNS text AS
+$BODY$
+DECLARE
+ sname text;
+ tname text;
+ cname text;
+ ctype text;
+ naming record;
+ err boolean;
+BEGIN
+
+ select * into naming from _pgr_getTableName(tab,reportErrs, fnName) ;
+ sname=naming.sname;
+ tname=naming.tname;
+ select * into cname from _pgr_getColumnName(tab,col,reportErrs, fnName) ;
+ select * into ctype from _pgr_getColumnType(sname,tname,cname,reportErrs, fnName);
+ RETURN ctype;
+END;
+
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
+
+
+
+
+/************************************************************************
+.. function:: _pgr_createIndex(tab, col,indextype)
+ _pgr_createIndex(sname,tname,colname,indextypes)
+
+ if the column is not indexed it creates a 'gist' index otherwise a 'btree' index
+ Examples:
+ * select _pgr_createIndex('tab','col','btree');
+ * select _pgr_createIndex('myschema','mytable','col','gist');
+ * perform 'select _pgr_createIndex('||quote_literal('tab')||','||quote_literal('col')||','||quote_literal('btree'))' ;
+ * perform 'select _pgr_createIndex('||quote_literal('myschema')||','||quote_literal('mytable')||','||quote_literal('col')||','||quote_literal('gist')')' ;
+ Precondition:
+ sname.tname.colname is a valid column on table tname in schema sname
+ indext is the indexType btree or gist
+ Postcondition:
+ sname.tname.colname its indexed using the indextype
+
+
+ Author: Vicky Vergara <vicky_vergara at hotmail.com>>
+
+ HISTORY
+ Created: 2014/JUL/28
+************************************************************************/
+
+CREATE OR REPLACE FUNCTION _pgr_createIndex(
+ sname text, tname text, colname text, indext text,
+ IN reportErrs int default 1, IN fnName text default '_pgr_createIndex')
+RETURNS void AS
+$BODY$
+DECLARE
+ debuglevel text;
+ naming record;
+ tabname text;
+ query text;
+ msgKind int;
+BEGIN
+ msgKind = 0; -- debug_
+
+ execute 'show client_min_messages' into debuglevel;
+ tabname=_pgr_quote_ident(sname||'.'||tname);
+ perform _pgr_msg(msgKind, fnName, 'Checking ' || colname || ' column in ' || tabname || ' is indexed');
+ IF (_pgr_isColumnIndexed(sname,tname,colname, 0, fnName)) then
+ perform _pgr_msg(msgKind, fnName);
+ else
+ if indext = 'gist' then
+ query = 'create index '||_pgr_quote_ident(tname||'_'||colname||'_idx')||'
+ on '||tabname||' using gist('||quote_ident(colname)||')';
+ else
+ query = 'create index '||_pgr_quote_ident(tname||'_'||colname||'_idx')||'
+ on '||tabname||' using btree('||quote_ident(colname)||')';
+ end if;
+ perform _pgr_msg(msgKind, fnName, 'Adding index ' || tabname || '_' || colname || '_idx');
+ perform _pgr_msg(msgKind, fnName, ' Using ' || query);
+ set client_min_messages to warning;
+ BEGIN
+ execute query;
+ EXCEPTION WHEN others THEN
+ perform _pgr_onError( true, reportErrs, fnName,
+ 'Could not create index on:' || cname, SQLERRM);
+ END;
+ execute 'set client_min_messages to '|| debuglevel;
+ perform _pgr_msg(msgKind, fnName);
+ END IF;
+END;
+
+$BODY$
+ LANGUAGE plpgsql VOLATILE STRICT;
+
+
+CREATE OR REPLACE FUNCTION _pgr_createIndex(tabname text, colname text, indext text,
+ IN reportErrs int default 1, IN fnName text default '_pgr_createIndex')
+RETURNS void AS
+$BODY$
+DECLARE
+ naming record;
+ sname text;
+ tname text;
+
+BEGIN
+ select * from _pgr_getTableName(tabname, 2, fnName) into naming;
+ sname=naming.sname;
+ tname=naming.tname;
+ execute _pgr_createIndex(sname, tname, colname, indext, reportErrs, fnName);
+END;
+
+$BODY$
+ LANGUAGE plpgsql VOLATILE STRICT;
+
+
+/************************************************************************
+.. function:: _pgr_checkVertTab(vertname,columnsArr,reportErrs) returns record of sname,vname
+
+ Returns:
+ sname,vname registered schemaname, vertices table name
+
+ if the table is not found will stop any further checking.
+ if a column is missing, then its added as integer --- (id also as integer but is bigserial when the vertices table is created with the pgr functions)
+
+ Examples:
+ * execute 'select * from _pgr_checkVertTab('||quote_literal(vertname) ||', ''{"id","cnt","chk"}''::text[])' into naming;
+ * execute 'select * from _pgr_checkVertTab('||quote_literal(vertname) ||', ''{"id","ein","eout"}''::text[])' into naming;
+
+ Author: Vicky Vergara <vicky_vergara at hotmail.com>>
+
+ HISTORY
+ Created: 2014/JUL/27
+************************************************************************/
+CREATE OR REPLACE FUNCTION _pgr_checkVertTab(vertname text, columnsArr text[],
+ IN reportErrs int default 1, IN fnName text default '_pgr_checkVertTab',
+ OUT sname text,OUT vname text)
+RETURNS record AS
+$BODY$
+DECLARE
+ cname text;
+ colname text;
+ naming record;
+ debuglevel text;
+ err boolean;
+ msgKind int;
+
+BEGIN
+ msgKind = 0; -- debug_
+ execute 'show client_min_messages' into debuglevel;
+
+ perform _pgr_msg(msgKind, fnName, 'Checking table ' || vertname || ' exists');
+ select * from _pgr_getTableName(vertname, 0, fnName) into naming;
+ sname=naming.sname;
+ vname=naming.tname;
+ err = sname is NULL or vname is NULL;
+ perform _pgr_onError( err, 2, fnName,
+ 'Vertex Table: ' || vertname || ' not found',
+ 'Please create ' || vertname || ' using _pgr_createTopology() or pgr_createVerticesTable()',
+ 'Vertex Table: ' || vertname || ' found');
+
+
+ perform _pgr_msg(msgKind, fnName, 'Checking columns of ' || vertname);
+ FOREACH cname IN ARRAY columnsArr
+ loop
+ select _pgr_getcolumnName(vertname, cname, 0, fnName) into colname;
+ if colname is null then
+ perform _pgr_msg(msgKind, fnName, 'Adding column ' || cname || ' in ' || vertname);
+ set client_min_messages to warning;
+ execute 'ALTER TABLE '||_pgr_quote_ident(vertname)||' ADD COLUMN '||cname|| ' integer';
+ execute 'set client_min_messages to '|| debuglevel;
+ perform _pgr_msg(msgKind, fnName);
+ end if;
+ end loop;
+ perform _pgr_msg(msgKind, fnName, 'Finished checking columns of ' || vertname);
+
+ perform _pgr_createIndex(vertname , 'id' , 'btree', reportErrs, fnName);
+ END
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
+
diff --git a/src/common/src/CMakeLists.txt b/src/common/src/CMakeLists.txt
index e69de29..1f277ed 100644
--- a/src/common/src/CMakeLists.txt
+++ b/src/common/src/CMakeLists.txt
@@ -0,0 +1,5 @@
+ADD_LIBRARY(common OBJECT
+ postgres_connection.c
+ basePath_SSEC.cpp
+ )
+
diff --git a/src/common/src/baseGraph.hpp b/src/common/src/baseGraph.hpp
new file mode 100644
index 0000000..6fc8e61
--- /dev/null
+++ b/src/common/src/baseGraph.hpp
@@ -0,0 +1,453 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_COMMON_SRC_BASE_GRAPH_HPP_
+#define SRC_COMMON_SRC_BASE_GRAPH_HPP_
+
+#include <boost/config.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/graph_utility.hpp>
+
+#include <deque>
+#include <vector>
+#include <set>
+#include <map>
+#include <limits>
+
+#include "postgres.h"
+#include "./pgr_types.h"
+
+/*! \brief boost::graph simplified to pgRouting needs
+
+This class gives the handling basics of a boost::graph of kind G
+where G:
+ can be an undirected graph or a directed graph.
+
+Usage:
+======
+
+ Given the following types:
+~~~~{.c}
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+~~~~
+
+direct usage:
+---------------
+
+~~~~{.c}
+ Pgr_base_graph < DirectedGraph > digraph(gType, initial_size);
+ Pgr_base_graph < UndirectedGraph > undigraph(gType, initial_size);
+~~~~
+
+usage by inheritance:
+---------------------
+
+~~~~{.c}
+ class my_graph: public Pgr_base_graph {
+ explicit my_graph(graphType gtype, const int initial_size)
+ :Pgr_base_graph< G >(gtype, initial_size) {}
+ // the class: my_graph will have the functionality of this class
+ }
+
+ my_graph < DirectedGraph > digraph(gType, initial_size);
+ my_graph < UndirectedGraph > undigraph(gType, initial_size);
+~~~~
+
+*/
+
+template <class G>
+class Pgr_base_graph {
+ public:
+ /** @name Graph related types
+ Type | boost meaning | pgRouting Meaning
+:---------: | :-------------------- | :----------------------
+ G | boost::adjacency_list | Graph
+ V | vertex_descriptor | Think of it as local ID of a vertex
+ E | edge_descriptor | Think of it as local ID of an edge
+ V_i | vertex_iterator | To cycle the vertices of the Graph
+ E_i | edge_iterator | To cycle the edges of the Graph
+ EO_i | out_edge_iterator | To cycle the out going edges of a vertex
+ EI_i | in_edge_iterator | To cycle the in coming edges of a vertex (only in bidirectional graphs)
+ */
+ //@{
+ typedef typename boost::graph_traits < G >::vertex_descriptor V;
+ typedef typename boost::graph_traits < G >::edge_descriptor E;
+ typedef typename boost::graph_traits < G >::vertex_iterator V_i;
+ typedef typename boost::graph_traits < G >::edge_iterator E_i;
+ typedef typename boost::graph_traits < G >::out_edge_iterator EO_i;
+ typedef typename boost::graph_traits < G >::in_edge_iterator EI_i;
+ //@}
+
+ /** @name Id handling related types
+ Type | Meaning | pgRouting Meaning
+:---------: | :------------- | :----------------------
+ id_to_V | maps id -> V | given an id store the V
+ V_to_id | maps V -> id | given a V store the id
+ LI | Left Iterator | iterates over id_to_V
+ RI | right Iterator | iterates over V_to_id
+ */
+ //@{
+ typedef typename std::map< int64_t, V > id_to_V;
+ typedef typename std::map< V, int64_t > V_to_id;
+ typedef typename id_to_V::const_iterator LI;
+ typedef typename V_to_id::const_iterator RI;
+ //@}
+
+ //! @name The Graph
+ //@{
+ G graph; //!< The graph
+ int64_t numb_vertices; //!< number of vertices
+ graphType m_gType; //!< type (DIRECTED or UNDIRECTED)
+ //@}
+
+ //! @name Id handling
+ //@{
+ id_to_V vertices_map; //!< id -> graph id
+ V_to_id gVertices_map; //!< graph id -> id
+ //@}
+
+ //! @name Graph Modification
+ //@{
+ //! Used for storing the removed_edges
+ std::deque<pgr_edge_t> removed_edges;
+ //@}
+
+ //! @name Used by dijkstra
+ //@{
+ std::vector<V> predecessors;
+ std::vector<float8> distances;
+ std::deque<V> nodesInDistance;
+ //@}
+
+ //! @name The Graph
+ //@{
+ //! \brief Constructor
+ /*!
+ Prepares the _graph_ to be of type _gtype_ with the
+ aproximate number of vertices its coing to have as *initial_size*
+ */
+ explicit Pgr_base_graph< G >(graphType gtype, const int initial_size)
+ : graph(initial_size),
+ numb_vertices(0),
+ m_gType(gtype)
+ {}
+
+ //! \brief Inserts *count* edges of type *pgr_edge_t* into the graph
+ void graph_insert_data(const pgr_edge_t *data_edges, int64_t count) {
+ for (unsigned int i = 0; i < count; ++i) {
+ graph_add_edge(data_edges[i]);
+ }
+ for ( int64_t i = 0; (unsigned int) i < gVertices_map.size(); ++i )
+ graph[i].id = gVertices_map.find(i)->second;
+ }
+
+ //! \brief Disconnects all edges from p_from to p_to
+ /*!
+ - No edge is disconnected if the vertices id's do not exist in the graph
+ - All removed edges are stored for future reinsertion
+ - All parallel edges are disconnected (automatically by boost)
+
+ 
+ 
+
+ @param [IN] *p_from* original vertex id of the starting point of the edge
+ @param [IN] *p_to* original vertex id of the ending point of the edge
+ */
+ void disconnect_edge(int64_t p_from, int64_t p_to) {
+ V g_from;
+ V g_to;
+ pgr_edge_t d_edge;
+ // nothing to do, the vertex doesnt exist
+ if (!get_gVertex(p_from, g_from)) return;
+ if (!get_gVertex(p_to, g_to)) return;
+ EO_i out, out_end;
+ // store the edges that are going to be removed
+ for (boost::tie(out, out_end) = out_edges(g_from, graph);
+ out != out_end; ++out) {
+ if (target(*out, graph) == g_to) {
+ d_edge.id = graph[*out].id;
+ d_edge.source = graph[source(*out, graph)].id;
+ d_edge.target = graph[target(*out, graph)].id;
+ d_edge.cost = graph[*out].cost;
+ d_edge.reverse_cost = -1;
+ removed_edges.push_back(d_edge);
+ }
+ }
+ // the actual removal
+ boost::remove_edge(g_from, g_to, graph);
+ }
+
+
+ //! \brief Disconnects all incomming and outgoing edges from the vertex
+ /*!
+ boost::graph doesn't recommend th to insert/remove vertices, so a vertex removal is
+ simulated by disconnecting the vertex from the graph
+
+ - No edge is disconnected if the vertices id's do not exist in the graph
+ - All removed edges are stored for future reinsertion
+ - All parallel edges are disconnected (automatically by boost)
+
+ 
+ 
+
+ @param [IN] *p_vertex* original vertex id of the starting point of the edge
+ */
+ void disconnect_vertex(int64_t p_vertex) {
+ V g_vertex;
+ pgr_edge_t d_edge;
+ // nothing to do, the vertex doesnt exist
+ if (!get_gVertex(p_vertex, g_vertex)) return;
+ EO_i out, out_end;
+ // store the edges that are going to be removed
+ for (boost::tie(out, out_end) = out_edges(g_vertex, graph);
+ out != out_end; ++out) {
+ d_edge.id = graph[*out].id;
+ d_edge.source = graph[source(*out, graph)].id;
+ d_edge.target = graph[target(*out, graph)].id;
+ d_edge.cost = graph[*out].cost;
+ d_edge.reverse_cost = -1;
+ removed_edges.push_back(d_edge);
+ }
+
+ // special case
+ if (m_gType == DIRECTED) {
+ EI_i in, in_end;
+ for (boost::tie(in, in_end) = in_edges(g_vertex, graph);
+ in != in_end; ++in) {
+ d_edge.id = graph[*in].id;
+ d_edge.source = graph[source(*in, graph)].id;
+ d_edge.target = graph[target(*in, graph)].id;
+ d_edge.cost = graph[*in].cost;
+ d_edge.reverse_cost = -1;
+ removed_edges.push_back(d_edge);
+ }
+ }
+
+ V d_vertex = boost::vertex(vertices_map.find(p_vertex)->second, graph);
+ // delete incomming and outgoing edges from the vertex
+ boost::clear_vertex(d_vertex, graph);
+ }
+
+ //! \brief Reconnects all edges that were removed
+ void restore_graph() {
+ while (removed_edges.size() != 0) {
+ graph_add_edge(removed_edges[0]);
+ removed_edges.pop_front();
+ }
+ }
+ //@}
+
+ //! @name only for stand by program
+ //@{
+ void print_graph() {
+ EO_i out, out_end;
+ V_i vi;
+
+ for (vi = vertices(graph).first; vi != vertices(graph).second; ++vi) {
+ std::cout << (*vi) << " out_edges(" << graph[(*vi)].id << "):";
+ for (boost::tie(out, out_end) = out_edges(*vi, graph);
+ out != out_end; ++out) {
+ std::cout << ' ' << *out << "=(" << graph[source(*out, graph)].id
+ << ", " << graph[target(*out, graph)].id << ") = "
+ << graph[*out].cost <<"\t";
+ }
+ std::cout << std::endl;
+ }
+ std::cout << "\n i, distance, predecesor\n";
+ for (unsigned int i = 0; i < distances.size(); i++) {
+ std::cout << i+1 << ", " << distances[i] << ", " << predecessors[i] << "\n";
+ }
+ }
+ //@}
+
+
+ bool get_gVertex(int64_t vertex_id, V &gVertex) {
+ LI vertex_ptr = vertices_map.find(vertex_id);
+
+ if (vertex_ptr == vertices_map.end())
+ return false;
+
+ gVertex = vertex(vertex_ptr->second, graph);
+ return true;
+ }
+
+
+ public:
+ void get_nodesInDistance(Path &path, V source, float8 distance) {
+ path.clear();
+ int seq = 0;
+ float8 cost;
+ int64_t edge_id;
+ for (V i = 0; i < distances.size(); ++i) {
+ if (distances[i] <= distance ) {
+ cost = distances[i] - distances[predecessors[i]];
+ edge_id = get_edge_id(graph, predecessors[i], i, cost);
+ path.push_back(seq, graph[source].id, graph[source].id, graph[i].id, edge_id, cost, distances[i]);
+ seq++;
+ }
+ }
+ }
+
+ void get_path(std::deque< Path > &paths, std::set< V > sources, V &target) const{
+ // used with multiple sources
+ Path path;
+ for (const auto source: sources) {
+ path.clear();
+ get_path(path, source, target);
+ paths.push_back(path);
+ }
+ }
+
+
+ void get_path(std::deque< Path > &paths, V source, std::set< V > &targets) {
+ // used when multiple goals
+ Path path;
+ typename std::set< V >::iterator s_it;
+ for (s_it = targets.begin(); s_it != targets.end(); ++s_it) {
+ path.clear();
+ get_path(path, source, *s_it);
+ paths.push_back(path);
+ }
+ }
+
+ void get_path(Path &path, V source, V target) {
+ // backup of the target
+ V target_back = target;
+ uint64_t from(graph[source].id);
+ uint64_t to(graph[target].id);
+
+ // no path was found
+ if (target == predecessors[target]) {
+ path.clear();
+ return;
+ }
+
+ // findout how large is the path
+ int64_t result_size = 1;
+ while (target != source) {
+ if (target == predecessors[target]) break;
+ result_size++;
+ target = predecessors[target];
+ }
+
+ // recover the target
+ target = target_back;
+
+ // variables that are going to be stored
+ int64_t vertex_id;
+ int64_t edge_id;
+ float8 cost;
+
+ // working from the last to the beginning
+
+ // initialize the sequence
+ int seq = result_size;
+ // the last stop is the target
+ path.push_front(seq, from, to, graph[target].id, -1, 0, distances[target]);
+
+ while (target != source) {
+ // we are done when the predecesor of the target is the target
+ if (target == predecessors[target]) break;
+ // values to be inserted in the path
+ --seq;
+ cost = distances[target] - distances[predecessors[target]];
+ vertex_id = graph[predecessors[target]].id;
+ edge_id = get_edge_id(graph, predecessors[target], target, cost);
+
+ path.push_front(seq, from, to, vertex_id, edge_id, cost, distances[target] - cost);
+ target = predecessors[target];
+ }
+ return;
+ }
+
+
+
+ private:
+ int64_t
+ get_edge_id(const G &graph, V from, V to, float8 &distance) {
+ E e;
+ EO_i out_i, out_end;
+ V v_source, v_target;
+ float8 minCost = std::numeric_limits<float8>::max();
+ int64_t minEdge = -1;
+ for (boost::tie(out_i, out_end) = boost::out_edges(from, graph);
+ out_i != out_end; ++out_i) {
+ e = *out_i;
+ v_target = target(e, graph);
+ v_source = source(e, graph);
+ if ((from == v_source) && (to == v_target)
+ && (distance == graph[e].cost))
+ return graph[e].id;
+ if ((from == v_source) && (to == v_target)
+ && (minCost > graph[e].cost)) {
+ minCost = graph[e].cost;
+ minEdge = graph[e].id;
+ }
+ }
+ distance = minEdge == -1? 0: minCost;
+ return minEdge;
+ }
+
+
+ private:
+ void
+ graph_add_edge(const pgr_edge_t &edge ) {
+ bool inserted;
+ LI vm_s, vm_t;
+ E e;
+
+ vm_s = vertices_map.find(edge.source);
+ if (vm_s == vertices_map.end()) {
+ vertices_map[edge.source]= numb_vertices;
+ gVertices_map[numb_vertices++] = edge.source;
+ vm_s = vertices_map.find(edge.source);
+ }
+
+ vm_t = vertices_map.find(edge.target);
+ if (vm_t == vertices_map.end()) {
+ vertices_map[edge.target]= numb_vertices;
+ gVertices_map[numb_vertices++] = edge.target;
+ vm_t = vertices_map.find(edge.target);
+ }
+
+ if (edge.cost >= 0) {
+ boost::tie(e, inserted) =
+ boost::add_edge(vm_s->second, vm_t->second, graph);
+ graph[e].cost = edge.cost;
+ graph[e].id = edge.id;
+ }
+
+ if (edge.reverse_cost >= 0) {
+ boost::tie(e, inserted) =
+ boost::add_edge(vm_t->second, vm_s->second, graph);
+ graph[e].cost = edge.reverse_cost;
+ graph[e].id = edge.id;
+ }
+ }
+};
+
+#endif // SRC_COMMON_SRC_BASE_GRAPH_HPP_
diff --git a/src/common/src/basePath_SSEC.cpp b/src/common/src/basePath_SSEC.cpp
new file mode 100644
index 0000000..f76b133
--- /dev/null
+++ b/src/common/src/basePath_SSEC.cpp
@@ -0,0 +1,231 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
+#include "basePath_SSEC.hpp"
+#include <deque>
+#include <iostream>
+#include <algorithm>
+#include "postgres.h"
+#include "./pgr_types.h"
+
+
+ void Path::push_front(pgr_path_element3_t data) {
+ cost += data.cost;
+ path.push_back(data);
+ }
+
+ void Path::push_back(pgr_path_element3_t data) {
+ cost += data.cost;
+ path.push_back(data);
+ }
+
+ pgr_path_element3_t Path::set_data(
+ int d_seq,
+ int64_t d_from,
+ int64_t d_to,
+ int64_t d_vertex,
+ int64_t d_edge,
+ float8 d_cost,
+ float8 d_tot_cost) {
+ pgr_path_element3_t data;
+ data.seq = d_seq;
+ data.from = d_from;
+ data.to = d_to;
+ data.vertex = d_vertex;
+ data.edge = d_edge;
+ data.cost = d_cost;
+ data.tot_cost = d_tot_cost;
+ return data;
+ }
+
+ void Path::push_front(
+ int d_seq,
+ int64_t d_from,
+ int64_t d_to,
+ int64_t d_vertex,
+ int64_t d_edge,
+ float8 d_cost,
+ float8 d_tot_cost) {
+ path.push_front(set_data(d_seq, d_from, d_to, d_vertex, d_edge, d_cost, d_tot_cost));
+ cost += path[0].cost;
+ }
+
+ void Path::push_back(
+ int d_seq,
+ int64_t d_from,
+ int64_t d_to,
+ int64_t d_vertex,
+ int64_t d_edge,
+ float8 d_cost,
+ float8 d_tot_cost) {
+ path.push_back(set_data(d_seq, d_from, d_to, d_vertex, d_edge, d_cost, d_tot_cost));
+ cost += path[path.size() - 1].cost;
+ }
+
+ void Path::clear() {
+ path.clear();
+ cost = 0;
+ }
+
+ void Path::print_path(std::ostream& log) const {
+ log << "seq\tfrom\tto\tvertex\tedge\tcost\ttot_Cost\n";
+ for (unsigned int i = 0; i < path.size(); ++i)
+ log << path[i].seq << "\t"
+ << path[i].from << "\t"
+ << path[i].to << "\t"
+ << path[i].vertex << "\t"
+ << path[i].edge << "\t"
+ << path[i].cost << "\t"
+ << path[i].tot_cost << "\n";
+ }
+
+ void Path::print_path() const {
+ print_path(std::cout);
+ }
+
+
+ Path Path::getSubpath(unsigned int j) const {
+ Path result;
+ if (j == 0) return result;
+ for (auto i = path.begin(); i != path.begin() + j; ++i) result.push_back((*i));
+ return result;
+ }
+
+
+ bool Path::isEqual(const Path &subpath) const {
+ if (subpath.path.empty()) return true;
+ if (subpath.path.size() >= path.size()) return false;
+ std::deque<pgr_path_element3_t>::const_iterator i, j;
+ for (i = path.begin(), j = subpath.path.begin();
+ j != subpath.path.end();
+ ++i, ++j)
+ if ((*i).vertex != (*j).vertex) return false;
+ return true;
+ }
+
+ void Path::appendPath(const Path &o_path) {
+ path.insert(path.end(), o_path.path.begin(), o_path.path.end());
+ cost += o_path.cost;
+ }
+
+ void Path::empty_path(unsigned int d_vertex) {
+ path.push_back(set_data(1, d_vertex, d_vertex, d_vertex, -1, 0, 0));
+ }
+
+ void Path::dpPrint(
+ pgr_path_element3_t **ret_path,
+ int &sequence) const {
+
+ for (unsigned int i = 0; i < path.size(); i++) {
+ (*ret_path)[sequence] = path[i];
+ sequence++;
+ }
+ }
+
+/* used by driving distance */
+ void Path::ddPrint(
+ pgr_path_element3_t **ret_path,
+ int &sequence, int routeId) const {
+
+ for (unsigned int i = 0; i < path.size(); i++) {
+ (*ret_path)[sequence] = path[i];
+ (*ret_path)[sequence].from = (uint64_t)routeId;
+ sequence++;
+ }
+ }
+
+/* used by ksp */
+ void Path::dpPrint(
+ pgr_path_element3_t **ret_path,
+ int &sequence, int routeId) const {
+
+ for (unsigned int i = 0; i < path.size(); i++) {
+ (*ret_path)[sequence] = path[i];
+ (*ret_path)[sequence].seq = i + 1;
+ (*ret_path)[sequence].from = (uint64_t)routeId;
+ (*ret_path)[sequence].tot_cost = (i == 0)? 0: (*ret_path)[sequence-1].tot_cost + path[i-1].cost;
+ sequence++;
+ }
+ }
+
+#if 0
+ friend int collapse_paths(
+ pgr_path_element3_t **ret_path,
+ const std::deque< Path > &paths) {
+ int sequence = 0;
+ for (const Path &path : paths) {
+ if (path.path.size() > 0)
+ path.dpPrint(ret_path, sequence);
+ }
+ return sequence;
+ }
+
+
+
+
+ friend Path equi_cost(const Path &p1, const Path &p2) {
+ Path result(p1);
+ sort(result.path.begin(), result.path.end(),
+ [](const pgr_path_element3_t &e1, const pgr_path_element3_t &e2)->bool {
+ return e1.vertex < e2.vertex;
+ });
+
+ for (auto const &e : p2.path) {
+ auto pos = find_if(result.path.begin(), result.path.end(),
+ [&e](const pgr_path_element3_t &e1)->bool {
+ return e.vertex == e1.vertex;
+ });
+ if (pos != result.path.end()) {
+ if (pos->cost > e.cost) {
+ (*pos) = e;
+ }
+ } else {
+ result.push_back(e);
+ }
+ }
+ return result;
+ }
+
+ friend Path equi_cost(const std::deque< Path > &paths) {
+ Path result;
+ for (const auto &p1 : paths) {
+ result = equi_cost(result, p1);
+ }
+ return result;
+ }
+
+ friend int count_tuples(const std::deque< Path > &paths) {
+ int count(0);
+ for (const Path &e : paths) {
+ count += e.path.size();
+ }
+ return count;
+ }
+
+};
+
+#endif // 0
diff --git a/src/common/src/basePath_SSEC.hpp b/src/common/src/basePath_SSEC.hpp
new file mode 100644
index 0000000..c8a3cd2
--- /dev/null
+++ b/src/common/src/basePath_SSEC.hpp
@@ -0,0 +1,154 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_COMMON_SRC_BASE_PATH_SSCE_H_
+#define SRC_COMMON_SRC_BASE_PATH_SSCE_H_
+
+#include <deque>
+#include <iostream>
+#include <algorithm>
+// #include <fstream>
+#include "postgres.h"
+#include "./pgr_types.h"
+
+class Path {
+ public:
+ std::deque< pgr_path_element3_t > path;
+ float8 cost;
+
+ Path(): cost(0) {}
+ size_t size() const { return path.size();}
+
+ void push_front(pgr_path_element3_t data) ;
+
+ void push_back(pgr_path_element3_t data) ;
+
+ pgr_path_element3_t set_data(
+ int d_seq,
+ int64_t d_from,
+ int64_t d_to,
+ int64_t d_vertex,
+ int64_t d_edge,
+ float8 d_cost,
+ float8 d_tot_cost);
+
+ void push_front(
+ int d_seq,
+ int64_t d_from,
+ int64_t d_to,
+ int64_t d_vertex,
+ int64_t d_edge,
+ float8 d_cost,
+ float8 d_tot_cost);
+
+ void push_back(
+ int d_seq,
+ int64_t d_from,
+ int64_t d_to,
+ int64_t d_vertex,
+ int64_t d_edge,
+ float8 d_cost,
+ float8 d_tot_cost);
+
+ void clear();
+
+ void print_path(std::ostream& log) const;
+ void print_path() const;
+
+ Path getSubpath(unsigned int j) const;
+
+
+ bool isEqual(const Path &subpath) const;
+ void appendPath(const Path &o_path);
+ void empty_path(unsigned int d_vertex);
+
+ void dpPrint(
+ pgr_path_element3_t **ret_path,
+ int &sequence) const;
+
+
+ void ddPrint(
+ pgr_path_element3_t **ret_path,
+ int &sequence, int routeId) const;
+
+ void dpPrint(
+ pgr_path_element3_t **ret_path,
+ int &sequence, int routeId) const;
+
+
+
+ friend int collapse_paths(
+ pgr_path_element3_t **ret_path,
+ const std::deque< Path > &paths) {
+ int sequence = 0;
+ for (const Path &path : paths) {
+ if (path.path.size() > 0)
+ path.dpPrint(ret_path, sequence);
+ }
+ return sequence;
+ }
+
+
+
+
+ friend Path equi_cost(const Path &p1, const Path &p2) {
+ Path result(p1);
+ sort(result.path.begin(), result.path.end(),
+ [](const pgr_path_element3_t &e1, const pgr_path_element3_t &e2)->bool {
+ return e1.vertex < e2.vertex;
+ });
+
+ for (auto const &e : p2.path) {
+ auto pos = find_if(result.path.begin(), result.path.end(),
+ [&e](const pgr_path_element3_t &e1)->bool {
+ return e.vertex == e1.vertex;
+ });
+ if (pos != result.path.end()) {
+ if (pos->cost > e.cost) {
+ (*pos) = e;
+ }
+ } else {
+ result.push_back(e);
+ }
+ }
+ return result;
+ }
+
+ friend Path equi_cost(const std::deque< Path > &paths) {
+ Path result;
+ for (const auto &p1 : paths) {
+ result = equi_cost(result, p1);
+ }
+ return result;
+ }
+
+ friend int count_tuples(const std::deque< Path > &paths) {
+ int count(0);
+ for (const Path &e : paths) {
+ count += e.path.size();
+ }
+ return count;
+ }
+
+};
+
+
+#endif // SRC_COMMON_SRC_BASE_PATH_SSCE_H_
diff --git a/src/common/src/pgr_assert.cpp b/src/common/src/pgr_assert.cpp
new file mode 100644
index 0000000..0b3efe2
--- /dev/null
+++ b/src/common/src/pgr_assert.cpp
@@ -0,0 +1,33 @@
+/*PGR*********************************************************************
+ *
+ * file pgr_assert.cpp
+ *
+ * Copyright 2014 Stephen Woodbridge <woodbri at imaptools.com>
+ * Copyright 2014 Vicky Vergara <vicky_vergara at hotmail.com>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the MIT License. Please file LICENSE for details.
+ *
+ ********************************************************************PGR*/
+#include "./pgr_assert.h"
+#include <exception>
+
+#ifdef assert
+#undef assert
+#endif
+
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+#define __TOSTRING(x) __STRING(x)
+
+
+const char *AssertFailedException::what() const throw() {
+ return str;
+}
+
+AssertFailedException::AssertFailedException(const char *_str) : str(
+ _str ) {}
+
+
diff --git a/src/common/src/pgr_assert.h b/src/common/src/pgr_assert.h
new file mode 100644
index 0000000..cf704b8
--- /dev/null
+++ b/src/common/src/pgr_assert.h
@@ -0,0 +1,85 @@
+/*PGR*********************************************************************
+ *
+ * file pgr_assert.h
+ *
+ * Copyright 2014 Stephen Woodbridge <woodbri at imaptools.com>
+ * Copyright 2014 Vicky Vergara <vicky_vergara at hotmail.com>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the MIT License. Please file LICENSE for details.
+ *
+ ********************************************************************PGR*/
+
+/*! \file vrp_assert.h
+ * \brief An assert functionality that uses C++ throw().
+ *
+ * This file provides an alternative to assert functionality that will
+ * convert all assert() into C++ throw using an AssertFailedException class.
+ * This allows us to catch these errors and do appropriate clean up and
+ * re-throw if needed so we can catch errors in the postgresql environment
+ * so we do not crash the backend server.
+ */
+#ifndef SRC_COMMON_SRC_PGR_ASSERT_H_
+#define SRC_COMMON_SRC_PGR_ASSERT_H_
+
+#include <exception>
+
+#ifdef assert
+#undef assert
+#endif
+
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+#define __TOSTRING(x) __STRING(x)
+
+/*! \def assert(expr)
+ * \brief Uses the standard assert syntax.
+ *
+ * When an assertion fails it will throw \ref AssertFailedException and what()
+ * will return a string like "AssertFailedException(2+2 == 5) at t.cpp:11"
+ *
+ * Here is an example of using it:
+ * \code
+ #include <iostream>
+ #include "vrp_assert.h"
+
+ int main() {
+
+ try {
+ assert(2+2 == 4);
+ assert(2+2 == 5);
+ }
+ catch (AssertFailedException &e) {
+ std::cout << e.what() << "\n";
+ }
+ catch (std::exception& e) {
+ std::cout << e.what() << "\n";
+ }
+ catch(...) {
+ std::cout << "Caught unknown exception!\n";
+ }
+ return 0;
+ }
+\endcode
+ */
+#define assert(expr) \
+ ((expr) \
+ ? static_cast<void>(0) \
+ : throw AssertFailedException("AssertFailedException: " __STRING(expr) " at " __FILE__ ":" __TOSTRING(__LINE__) ))
+
+
+/*! \class AssertFailedException
+ * \brief Extends std::exception and is the exception that we throw if an assert fails.
+ */
+class AssertFailedException : public std::exception {
+ private:
+ const char *str; ///< str Holds the what() string for the exception.
+
+ public:
+ virtual const char *what() const throw();
+ explicit AssertFailedException(const char *_str);
+};
+
+#endif // SRC_COMMON_SRC_PGR_ASSERT_H_
diff --git a/src/common/src/pgr_logger.h b/src/common/src/pgr_logger.h
new file mode 100644
index 0000000..e50fa0d
--- /dev/null
+++ b/src/common/src/pgr_logger.h
@@ -0,0 +1,65 @@
+/*
+ pgr_logger.h
+
+ Author: Stephen Woodbridge
+ Date: 2014-05-04
+ License: MIT-X
+
+ A simple logging mechanism the can be disabled for production
+ and should work in C or C++ code.
+
+ USAGE:
+
+ #define PGR_LOGGERR_ON
+ #undef PGR_LOGGER_ON // turn off logging for production
+
+ // override the default log file "/tmp/pgr_logger.log"
+ #define PGR_LOGGER_FILE "mylogger.log"
+
+ #undef PGR_LOGGER_LOC // dont log filename and line number
+ #define PGR_LOGGER_LOC // log filename and line number with log message
+
+ // include the logger macros and configure based on defines above
+ #include pgr_logger.h
+
+ // log a message to the log file
+ PGR_LOGF(format, args);
+ PGR_LOGF("%s at %d\n", "this is a message", time());
+ PGR_LOG("just print a string to the log");
+
+ This will log something like:
+
+ myfile.cpp:123: this is a message at 1399216875
+ myfile.cpp:124: just print a string to the log
+
+*/
+#ifndef PGR_LOGGER_H
+#define PGR_LOGGER_H
+
+#include <stdio.h>
+
+#if defined(PGR_LOGGER_LOC)
+# undef PGR_LOGGER_LOC_
+# define PGR_LOGGER_LOC_ 1
+#else
+# undef PGR_LOGGER_LOC_
+# define PGR_LOGGER_LOC_ 0
+#endif
+
+#ifndef PGR_LOGGER_FILE
+# define PGR_LOGGER_FILE "/tmp/pgr_logger.log"
+#endif
+
+#ifdef PGR_LOGGER_ON
+# define PGR_LOGF(format, ...) { \
+ FILE *fp = fopen(PGR_LOGGER_FILE, "a+"); \
+ if (PGR_LOGGER_LOC_) fprintf(fp, "%s:%d: ", __FILE__, __LINE__); \
+ fprintf(fp, format, __VA_ARGS__); \
+ fclose(fp); }
+#else // ifndef LOGGER_ON
+# define PGR_LOGF(format, ...)
+#endif // ifndef LOGGER_ON
+
+#define PGR_LOG(str) PGR_LOGF("%s\n", str)
+
+#endif // ifndef PGR_LOGGER_H
diff --git a/src/common/src/pgr_types.h b/src/common/src/pgr_types.h
new file mode 100644
index 0000000..2ecf0e9
--- /dev/null
+++ b/src/common/src/pgr_types.h
@@ -0,0 +1,111 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef PGR_TYPES_H
+#define PGR_TYPES_H
+
+#include "postgres.h"
+
+typedef struct edge_astar
+{
+ int id;
+ int source;
+ int target;
+ float8 cost;
+ float8 reverse_cost;
+ float8 s_x;
+ float8 s_y;
+ float8 t_x;
+ float8 t_y;
+} edge_astar_t;
+
+
+typedef struct path_element
+{
+ int64_t vertex_id;
+ int64_t edge_id;
+ float8 cost;
+} path_element_t;
+
+typedef struct path_element3
+{
+ int seq;
+ int64_t from;
+ int64_t to;
+ int64_t vertex;
+ int64_t edge;
+ float8 cost;
+ float8 tot_cost;
+} pgr_path_element3_t;
+
+typedef struct {
+ int64_t id;
+ int64_t source;
+ int64_t target;
+ float8 cost;
+ float8 reverse_cost;
+} pgr_edge_t;
+
+typedef struct {
+ int seq;
+ int64_t source;
+ int64_t edge;
+ float8 cost;
+} pgr_path_t;
+
+struct boost_vertex_t {
+ int64_t id;
+};
+
+struct boost_edge_t{
+ int64_t id;
+ float8 cost;
+ int64_t source_id;
+ int64_t target_id;
+};
+
+// used in kdijktra
+#if 0
+typedef struct
+{
+ int64_t vertex_id_source;
+ int64_t edge_id_source;
+ int64_t vertex_id_target;
+ int64_t edge_id_target;
+ float8 cost;
+ float8 totcost;
+} dist_fromto_t;
+
+
+typedef struct
+{
+ int64_t vertex_id_source;
+ int64_t edge_id_source;
+ int64_t vertex_id_target;
+ int64_t edge_id_target;
+ float8 cost;
+ char* the_way;
+} path_fromto_t;
+#endif
+
+enum graphType { UNDIRECTED= 0, DIRECTED};
+
+#endif // PGR_TYPES_H
diff --git a/src/common/src/postgres_connection.c b/src/common/src/postgres_connection.c
new file mode 100644
index 0000000..55f8c95
--- /dev/null
+++ b/src/common/src/postgres_connection.c
@@ -0,0 +1,415 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+// #define DEBUG
+#include "postgres.h"
+#include "utils/lsyscache.h"
+#include "catalog/pg_type.h"
+#include "utils/array.h"
+#include "executor/spi.h"
+
+
+#include "pgr_types.h"
+#include "postgres_connection.h"
+
+#define TUPLIMIT 1000
+
+char *
+pgr_text2char(text *in)
+{
+ char *out = palloc(VARSIZE(in));
+
+ memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
+ out[VARSIZE(in) - VARHDRSZ] = '\0';
+ return out;
+}
+
+int pgr_finish(int code, int ret)
+{
+ code = SPI_finish();
+ if (code != SPI_OK_FINISH )
+ {
+ elog(ERROR,"couldn't disconnect from SPI");
+ return -1 ;
+ }
+ return ret;
+}
+
+static int pgr_fetch_column_info(
+ int *colNumber,
+ int *coltype,
+ char *colName) {
+ (*colNumber) = SPI_fnumber(SPI_tuptable->tupdesc, colName);
+ if ((*colNumber) == SPI_ERROR_NOATTRIBUTE) {
+ elog(ERROR, "Fetching column number");
+ return -1;
+ }
+ (*coltype) = SPI_gettypeid(SPI_tuptable->tupdesc, (*colNumber));
+ if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
+ elog(ERROR, "Fetching column type");
+ return -1;
+ }
+ return 0;
+ }
+
+
+int64_t* pgr_get_bigIntArray(int *arrlen, ArrayType *input) {
+ int ndims;
+ // int *lbs;
+ bool *nulls;
+ Oid i_eltype;
+ int16 i_typlen;
+ bool i_typbyval;
+ char i_typalign;
+ Datum *i_data;
+ int i, n;
+ int64_t *data;
+
+ /* get input array element type */
+ i_eltype = ARR_ELEMTYPE(input);
+ get_typlenbyvalalign(i_eltype, &i_typlen, &i_typbyval, &i_typalign);
+
+
+ /* validate input data type */
+ switch(i_eltype){
+ case INT2OID:
+ case INT4OID:
+ case INT8OID:
+ break;
+ default:
+ elog(ERROR, "Expected array of any-integer");
+ return (int64_t*) NULL;
+ break;
+ }
+
+ /* get various pieces of data from the input array */
+ ndims = ARR_NDIM(input);
+ n = (*ARR_DIMS(input));
+ (*arrlen) = n;
+ // lbs = ARR_LBOUND(input);
+
+ if ( (ndims) != 1) {
+ elog(ERROR, "One dimenton expected");
+ }
+
+ /* get src data */
+ deconstruct_array(input, i_eltype, i_typlen, i_typbyval, i_typalign,
+ &i_data, &nulls, &n);
+
+ /* construct a C array */
+ data = (int64_t *) malloc((*arrlen) * sizeof(int64_t));
+ if (!data) {
+ elog(ERROR, "Error: Out of memory!");
+ }
+ PGR_DBG("array size %d", (*arrlen));
+
+ for (i=0; i<(*arrlen); i++) {
+ if (nulls[i]) {
+ data[i] = -1;
+ }
+ else {
+ switch(i_eltype){
+ case INT2OID:
+ data[i] = (int64_t) DatumGetInt16(i_data[i]);
+ break;
+ case INT4OID:
+ data[i] = (int64_t) DatumGetInt32(i_data[i]);
+ break;
+ case INT8OID:
+ data[i] = DatumGetInt64(i_data[i]);
+ break;
+ }
+ }
+ PGR_DBG(" data[%d]=%li", i, data[i]);
+ }
+
+ pfree(nulls);
+ pfree(i_data);
+
+ return (int64_t*)data;
+}
+
+
+/********************
+Functions for pgr_foo with sql:
+ id, source, target, cost, reverse_cost(optional)
+************/
+static int pgr_fetch_edge_columns(
+ int (*edge_columns)[5],
+ int (*edge_types)[5],
+ bool has_rcost) {
+
+ int error;
+ error = pgr_fetch_column_info(&(*edge_columns)[0], &(*edge_types)[0], "id");
+ if (error == -1) return error;
+ error = pgr_fetch_column_info(&(*edge_columns)[1], &(*edge_types)[1], "source");
+ if (error == -1) return error;
+ error = pgr_fetch_column_info(&(*edge_columns)[2], &(*edge_types)[2], "target");
+ if (error == -1) return error;
+ error = pgr_fetch_column_info(&(*edge_columns)[3], &(*edge_types)[3], "cost");
+ if (error == -1) return error;
+ if (has_rcost) {
+ error = pgr_fetch_column_info(&(*edge_columns)[4], &(*edge_types)[4], "reverse_cost");
+ if (error == -1) return error;
+ }
+
+ return 0;
+
+}
+
+static int64_t pgr_SPI_getBigInt(HeapTuple *tuple, TupleDesc *tupdesc, int colNumber, int colType) {
+ Datum binval;
+ bool isnull;
+ int64_t value = 0;
+ binval = SPI_getbinval(*tuple, *tupdesc, colNumber, &isnull);
+ if (isnull) elog(ERROR, "Null value found");
+ switch (colType) {
+ case INT2OID:
+ value = (int64_t) DatumGetInt16(binval);
+ break;
+ case INT4OID:
+ value = (int64_t) DatumGetInt32(binval);
+ break;
+ case INT8OID:
+ value = DatumGetInt64(binval);
+ break;
+ default:
+ elog(ERROR, "BigInt, int or SmallInt expected");
+ }
+ return value;
+}
+
+static float8 pgr_SPI_getFloat8(HeapTuple *tuple, TupleDesc *tupdesc, int colNumber, int colType) {
+ Datum binval;
+ bool isnull;
+ float8 value = 0.0;
+ binval = SPI_getbinval(*tuple, *tupdesc, colNumber, &isnull);
+ if (isnull) elog(ERROR, "Null value found");
+ switch (colType) {
+ case INT2OID:
+ value = (float8) DatumGetInt16(binval);
+ break;
+ case INT4OID:
+ value = (float8) DatumGetInt32(binval);
+ break;
+ case INT8OID:
+ value = (float8) DatumGetInt64(binval);
+ break;
+ case FLOAT4OID:
+ value = (float8) DatumGetFloat4(binval);
+ break;
+ case FLOAT8OID:
+ value = DatumGetFloat8(binval);
+ break;
+ default:
+ elog(ERROR, "BigInt, int, SmallInt, real expected");
+ }
+ return value;
+}
+
+void pgr_fetch_edge(
+ HeapTuple *tuple,
+ TupleDesc *tupdesc,
+ int (*edge_columns)[5],
+ int (*edge_types)[5],
+ pgr_edge_t *target_edge,
+ bool has_rcost) {
+
+ target_edge->id = pgr_SPI_getBigInt(tuple, tupdesc, (*edge_columns)[0], (*edge_types)[0]);
+ target_edge->source = pgr_SPI_getBigInt(tuple, tupdesc, (*edge_columns)[1], (*edge_types)[1]);
+ target_edge->target = pgr_SPI_getBigInt(tuple, tupdesc, (*edge_columns)[2], (*edge_types)[2]);
+ target_edge->cost = pgr_SPI_getFloat8(tuple, tupdesc, (*edge_columns)[3], (*edge_types)[3]);
+
+ if (has_rcost) {
+ target_edge->reverse_cost = pgr_SPI_getFloat8(tuple, tupdesc, (*edge_columns)[4], (*edge_types)[4]);
+ } else {
+ target_edge->reverse_cost = -1.0;
+ }
+ PGR_DBG("id: %li\t source: %li\ttarget: %li\tcost: %f\t,reverse: %f\n",
+ target_edge->id, target_edge->source, target_edge->target, target_edge->cost, target_edge->reverse_cost);
+}
+
+
+
+int pgr_get_data(
+ char *sql,
+ pgr_edge_t **edges,
+ int64_t *totalTuples,
+ bool has_rcost,
+ int64_t start_vertex,
+ int64_t end_vertex) {
+ PGR_DBG("Entering pgr_get_data");
+
+ bool sourceFound = false;
+ bool targetFound = false;
+ if (start_vertex == -1 && end_vertex == -1) {
+ sourceFound = targetFound = true;
+ }
+ int ntuples;
+ int64_t total_tuples;
+
+ int edge_columns[5];
+ int edge_types[5];
+ int i;
+ for (i = 0; i < 5; ++i) edge_columns[i] = -1;
+ for (i = 0; i < 5; ++i) edge_types[i] = -1;
+ int ret = -1;
+
+
+ PGR_DBG("Connecting to SPI");
+ int SPIcode;
+ SPIcode = SPI_connect();
+ if (SPIcode != SPI_OK_CONNECT) {
+ elog(ERROR, "Couldn't open a connection to SPI");
+ return -1;
+ }
+
+ PGR_DBG("Preparing Plan");
+ void *SPIplan;
+ SPIplan = SPI_prepare(sql, 0, NULL);
+ if (SPIplan == NULL) {
+ elog(ERROR, "Couldn't create query plan via SPI");
+ return -1;
+ }
+
+ PGR_DBG("Opening Portal");
+ Portal SPIportal;
+ if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) {
+ elog(ERROR, "SPI_cursor_open('%s') returns NULL", sql);
+ return -1;
+ }
+
+
+ PGR_DBG("Starting Cycle");
+ bool moredata = TRUE;
+ (*totalTuples) = total_tuples = 0;
+ while (moredata == TRUE) {
+ SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
+
+ /* on the first tuple get the column numbers */
+ if (edge_columns[0] == -1) {
+ PGR_DBG("Fetching column numbers");
+ if (pgr_fetch_edge_columns(&edge_columns, &edge_types,
+ has_rcost) == -1)
+ return pgr_finish(SPIcode, ret);
+ PGR_DBG("Finished fetching column numbers");
+ }
+
+ ntuples = SPI_processed;
+ total_tuples += ntuples;
+
+ PGR_DBG("Getting Memory");
+ if ((*edges) == NULL)
+ (*edges) = (pgr_edge_t *)palloc(total_tuples * sizeof(pgr_edge_t));
+ else
+ (*edges) = (pgr_edge_t *)repalloc((*edges), total_tuples * sizeof(pgr_edge_t));
+ PGR_DBG("Got Memory");
+
+ if ((*edges) == NULL) {
+ elog(ERROR, "Out of memory");
+ return pgr_finish(SPIcode, ret);
+ }
+
+ if (ntuples > 0) {
+ int t;
+ SPITupleTable *tuptable = SPI_tuptable;
+ TupleDesc tupdesc = SPI_tuptable->tupdesc;
+ PGR_DBG("processing %d", ntuples);
+ for (t = 0; t < ntuples; t++) {
+ HeapTuple tuple = tuptable->vals[t];
+ pgr_fetch_edge(&tuple, &tupdesc, &edge_columns, &edge_types,
+ &(*edges)[total_tuples - ntuples + t], has_rcost);
+
+ if (!sourceFound
+ && (((*edges)[total_tuples - ntuples + t].source == start_vertex)
+ || ((*edges)[total_tuples - ntuples + t].target == start_vertex))) {
+ sourceFound = true;
+ }
+ if (!targetFound
+ && (((*edges)[total_tuples - ntuples + t].source == end_vertex)
+ || ((*edges)[total_tuples - ntuples + t].target == end_vertex))) {
+ targetFound = true;
+ }
+ }
+ SPI_freetuptable(tuptable);
+ } else {
+ moredata = FALSE;
+ }
+ }
+
+
+#if 0
+ if (!sourceFound) {
+ // elog(NOTICE, "Starting Vertex does not exist in the data");
+ return 0;
+ }
+ if (!targetFound) {
+ // elog(NOTICE, "Ending Vertex does not exist in the data");
+ return 0;
+ }
+#endif
+ if (total_tuples == 1) {
+ // for some reason it needs at least a second edge for boost.graph to work
+ // makeing a simple test and asking boost people
+ ++total_tuples;
+ (*edges) = (pgr_edge_t *)repalloc((*edges), total_tuples * sizeof(pgr_edge_t));
+ (*edges)[1].source = -1;
+ (*edges)[1].target = -1;
+ (*edges)[1].cost = 10000;
+ (*edges)[1].id = (*edges)[0].id + 1;
+ (*edges)[1].reverse_cost = -1;
+ }
+
+ (*totalTuples) = total_tuples;
+ return 0;
+}
+
+pgr_path_element3_t* pgr_get_memory3(int size, pgr_path_element3_t *path){
+ if(path ==0 ){
+ path=malloc(size * sizeof(pgr_path_element3_t));
+ } else {
+ path=realloc(path,size * sizeof(pgr_path_element3_t));
+ }
+ return path;
+}
+
+
+pgr_path_element3_t* noPathFound3(int64_t fill_value, int *count, pgr_path_element3_t *no_path) {
+#if 0
+ (*count) = 1;
+ no_path = pgr_get_memory3(1, no_path);
+ no_path[0].seq = 0;
+ no_path[0].from = fill_value;
+ no_path[0].to = fill_value;
+ no_path[0].vertex = fill_value;
+ no_path[0].edge = -1;
+ no_path[0].cost = 0;
+ no_path[0].tot_cost = 0;
+ return no_path;
+#else
+ count = 0;
+ return NULL;
+#endif
+}
+
+
+
+
diff --git a/src/common/src/postgres_connection.h b/src/common/src/postgres_connection.h
new file mode 100644
index 0000000..5163d88
--- /dev/null
+++ b/src/common/src/postgres_connection.h
@@ -0,0 +1,83 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_COMMON_SRC_POSTGRES_CONNECTION_H_
+#define SRC_COMMON_SRC_POSTGRES_CONNECTION_H_
+
+#include "postgres.h"
+#include "executor/spi.h"
+#include "utils/array.h"
+
+
+#include "./pgr_types.h"
+#include "./postgres_connection.h"
+
+#ifdef DEBUG
+#define PGR_DBG(format, arg...) \
+elog(NOTICE, format , ## arg)
+#else
+#define PGR_DBG(format, arg...) do { ; } while (0)
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ char * pgr_text2char(text *in);
+ int pgr_finish(int code, int ret);
+ int64_t* pgr_get_bigIntArray(int *arrlen, ArrayType *input);
+/*
+ int pgr_fetch_edge_columns(SPITupleTable *tuptable, int (*edge_columns)[5],
+ bool has_reverse_cost);
+ void pgr_fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc,
+ int (*edge_columns)[5], pgr_edge_t *target_edge,
+ bool has_rcost);
+*/
+
+ /*!
+ Signature 1:
+ bigint id,
+ bigint source,
+ bigint target,
+ float cost
+ float reverse_cost
+ */
+ int pgr_get_data(
+ char *sql, //!< \param [IN] sql from where we get the data
+ pgr_edge_t **edges, //!< \param [OUT] edges retrieved edges
+ int64_t *total_tuples, //!< \param [OUT] total_tuples Total edges retrived
+ bool has_rcost, //!< \param [IN] has_rcost flag for reverse_cost
+ int64_t start_vertex, //!< \param [IN] start_vertex index to look for
+ int64_t end_vertex); //!< \param [IN] end_vertex index to look for
+
+
+ // output corresponding to costResult3Big
+ pgr_path_element3_t* pgr_get_memory3(int size, pgr_path_element3_t *path);
+ // pgr_path_element3_t * noPathFound3(int64_t start_id);
+ pgr_path_element3_t* noPathFound3(int64_t fill_value, int *count, pgr_path_element3_t *no_path);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SRC_COMMON_SRC_POSTGRES_CONNECTION_H_
diff --git a/src/common/src/signalhandler.cpp b/src/common/src/signalhandler.cpp
new file mode 100644
index 0000000..373fe64
--- /dev/null
+++ b/src/common/src/signalhandler.cpp
@@ -0,0 +1,60 @@
+/*PGR*********************************************************************
+ *
+ * file signalhandler.cpp
+ *
+ * Copyright 2014 Stephen Woodbridge <woodbri at imaptools.com>
+ * Copyright 2014 Vicky Vergara <vicky_vergara at hotmail.com>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the MIT License. Please file LICENSE for details.
+ *
+ ********************************************************************PGR*/
+#include "./signalhandler.h"
+
+SignalHandler *
+SignalHandler::instance() {
+ if (!instance_) instance_ = new SignalHandler;
+
+ assert(instance_ != NULL);
+ return instance_;
+}
+
+
+EventHandler *
+SignalHandler::registerHandler(int signum, EventHandler *eh) {
+ // Copy the <old_eh> from the <signum> slot in
+ // the <signalHandlers_> table.
+ EventHandler *old_eh = signalHandlers_[signum];
+
+ // Store <eh> into the <signum> slot in the
+ // <signalHandlers_> table.
+ SignalHandler::signalHandlers_[signum] = eh;
+
+ // Register the <dispatcher> to handle this
+ // <signum>.
+ struct sigaction sa;
+ sa.sa_handler = SignalHandler::dispatcher;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction(signum, &sa, 0);
+
+ return old_eh;
+}
+
+void SignalHandler::removeHandler(int signum) {
+ // EventHandler *old_eh = signalHandlers_[signum];
+ signalHandlers_[signum] = static_cast<EventHandler *>(0);
+}
+
+
+void SignalHandler::dispatcher(int signum) {
+ // Perform a sanity check...
+ if (SignalHandler::signalHandlers_[signum] != 0)
+ // Dispatch the handler's hook method.
+ SignalHandler::signalHandlers_[signum]->handleSignal(signum);
+}
+
+// these allocate actual storage
+SignalHandler *SignalHandler::instance_ = NULL;
+EventHandler *SignalHandler::signalHandlers_[NSIG];
+
diff --git a/src/common/src/signalhandler.h b/src/common/src/signalhandler.h
new file mode 100644
index 0000000..a788e3e
--- /dev/null
+++ b/src/common/src/signalhandler.h
@@ -0,0 +1,129 @@
+/*PGR*********************************************************************
+ *
+ * file signalhandler.h
+ *
+ * Copyright 2014 Stephen Woodbridge <woodbri at imaptools.com>
+ * Copyright 2014 Vicky Vergara <vicky_vergara at hotmail.com>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the MIT License. Please file LICENSE for details.
+ *
+ ********************************************************************PGR*/
+#ifndef SRC_COMMON_SRC_SIGNALHANDLER_H_
+#define SRC_COMMON_SRC_SIGNALHANDLER_H_
+
+#include <stddef.h> // defines NULL
+#include <csignal>
+#include <exception>
+
+#include "./pgr_assert.h"
+
+class UserQuitException: public std::exception {
+ private:
+ const char *str; ///< str Holds the what() string for the exception.
+
+ public:
+ virtual const char *what() const throw() {
+ return str;
+ }
+
+ explicit UserQuitException(const char *_str): str(_str) {}
+};
+
+
+class EventHandler {
+ public:
+ // Hook method for the signal hook method.
+ virtual void handleSignal(int signum) = 0;
+
+ // ... other hook methods for other types of
+ // events such as timers, I/O, and
+ // synchronization objects.
+};
+
+
+class SignalHandler {
+ public:
+ // Entry point.
+ static SignalHandler *instance(void);
+
+ // Register an event handler <eh> for <signum>
+ // and return a pointer to any existing <EventHandler>
+ // that was previously registered to handle <signum>.
+ EventHandler *registerHandler(int signum, EventHandler *eh);
+
+ // Remove the <EventHandler> for <signum>
+ // by setting the slot in the <signalHandlers_>
+ // table to NULL.
+ void removeHandler(int signum);
+
+ private:
+ // Ensure we're a Singleton.
+ SignalHandler(void) {}
+
+ // Singleton pointer.
+ static SignalHandler *instance_;
+
+ // Entry point adapter installed into <sigaction>
+ // (must be a static method or a stand-alone
+ // extern "C" function).
+ static void dispatcher(int signum);
+
+ // Table of pointers to concrete <EventHandler>s
+ // registered by applications. NSIG is the number of
+ // signals defined in </usr/include/sys/signal.h>.
+ static EventHandler *signalHandlers_[NSIG];
+};
+
+
+// ---------------------------------------------------------
+// -- some concrete signal handlers
+// ---------------------------------------------------------
+
+class SIGINT_Handler: public EventHandler {
+ public:
+ SIGINT_Handler(void): graceful_quit_(0) {}
+
+ // Hook method.
+ virtual void handleSignal(int signum) {
+ if (signum == SIGINT) this->graceful_quit_ = 1;
+ }
+
+ // Accessor.
+ sig_atomic_t gracefulQuit(void) { return this->graceful_quit_;}
+
+ private:
+ sig_atomic_t graceful_quit_;
+};
+
+
+class SIGQUIT_Handler: public EventHandler {
+ public:
+ SIGQUIT_Handler(void): abortive_quit_(0) {}
+
+ // Hook method.
+ virtual void handleSignal(int signum) {
+ if (signum == SIGQUIT) this->abortive_quit_ = 1;
+ }
+
+ // Accessor.
+ sig_atomic_t abortiveQuit(void) { return this->abortive_quit_;}
+
+ private:
+ sig_atomic_t abortive_quit_;
+};
+
+
+#define REG_SIGINT SIGINT_Handler sigint_handler; \
+ SignalHandler::instance()->registerHandler(SIGINT, &sigint_handler);
+
+#define REG_SIGQUIT SIGQUIT_Handler sigquit_handler; \
+ SignalHandler::instance()->registerHandler(SIGQUIT, &sigquit_handler);
+
+#define THROW_ON_SIGINT do { \
+ if ( sigint_handler.gracefulQuit() == 1 ) \
+ throw(UserQuitException("Abort on User Request!")); \
+ } while (0);
+
+#endif // SRC_COMMON_SRC_SIGNALHANDLER_H_
+
diff --git a/src/common/test/common-any-01.rest b/src/common/test/common-any-01.result
similarity index 97%
rename from src/common/test/common-any-01.rest
rename to src/common/test/common-any-01.result
index 8510616..7e0af17 100644
--- a/src/common/test/common-any-01.rest
+++ b/src/common/test/common-any-01.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
NOTICE: Rows with NULL geometry or NULL id: 0
diff --git a/src/common/test/common-any-01.test b/src/common/test/common-any-01.test.sql
similarity index 100%
rename from src/common/test/common-any-01.test
rename to src/common/test/common-any-01.test.sql
diff --git a/src/common/test/common-any-02.data b/src/common/test/common-any-02.data
new file mode 100644
index 0000000..3da158f
--- /dev/null
+++ b/src/common/test/common-any-02.data
@@ -0,0 +1,132 @@
+--
+-- PostgreSQL database dump
+--
+
+SET statement_timeout = 0;
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = on;
+SET check_function_bodies = false;
+SET client_min_messages = warning;
+
+SET default_tablespace = '';
+
+SET default_with_oids = false;
+
+--
+-- Name: edge_table; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
+--
+
+DROP TABLE IF EXISTS edge_table CASCADE;
+
+CREATE TABLE edge_table (
+ id integer NOT NULL,
+ dir character varying,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ the_geom geometry,
+ sgid integer,
+ tgid integer
+);
+
+
+ALTER TABLE edge_table OWNER TO postgres;
+
+--
+-- Name: edge_table_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
+--
+
+CREATE SEQUENCE edge_table_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE edge_table_id_seq OWNER TO postgres;
+
+--
+-- Name: edge_table_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
+--
+
+ALTER SEQUENCE edge_table_id_seq OWNED BY edge_table.id;
+
+
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY edge_table ALTER COLUMN id SET DEFAULT nextval('edge_table_id_seq'::regclass);
+
+
+--
+-- Data for Name: edge_table; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY edge_table (id, dir, source, target, cost, reverse_cost, x1, y1, x2, y2, the_geom, sgid, tgid) FROM stdin;
+1 B 1 2 1 1 2 0 2 1 010200000002000000000000000000004000000000000000000000000000000040000000000000F03F 2 4
+2 TF 2 3 -1 1 2 1 3 1 0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F 4 4
+3 TF 3 4 -1 1 3 1 4 1 0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F 4 4
+7 B 8 5 1 1 1 2 2 2 010200000002000000000000000000F03F000000000000004000000000000000400000000000000040 4 4
+4 B 2 5 1 1 2 1 2 2 0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040 4 4
+5 FT 3 6 1 -1 3 1 3 2 0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040 4 4
+6 B 7 8 1 1 0 2 1 2 01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040 1 4
+16 B 4 9 1 1 4 1 4 2 0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040 4 4
+12 FT 10 11 1 -1 2 3 3 3 0102000000020000000000000000000040000000000000084000000000000008400000000000000840 3 3
+11 FT 6 11 1 -1 3 2 3 3 0102000000020000000000000000000840000000000000004000000000000008400000000000000840 4 3
+13 FT 11 12 1 -1 3 3 4 3 0102000000020000000000000000000840000000000000084000000000000010400000000000000840 3 3
+15 B 9 12 1 1 4 2 4 3 0102000000020000000000000000001040000000000000004000000000000010400000000000000840 4 3
+14 B 10 13 1 1 2 3 2 4 0102000000020000000000000000000040000000000000084000000000000000400000000000001040 3 3
+17 B 14 15 1 1 0.5 3.5 1.99999999999899991 3.5 010200000002000000000000000000E03F0000000000000C4068EEFFFFFFFFFF3F0000000000000C40 3 3
+18 B 16 17 1 1 3.5 2.29999999999999982 3.5 4 0102000000020000000000000000000C4066666666666602400000000000000C400000000000001040 4 3
+8 B 5 6 1 1 2 2 3 2 0102000000020000000000000000000040000000000000004000000000000008400000000000000040 4 4
+9 B 6 9 1 1 3 2 4 2 0102000000020000000000000000000840000000000000004000000000000010400000000000000040 4 4
+10 B 5 10 1 1 2 2 2 3 0102000000020000000000000000000040000000000000004000000000000000400000000000000840 4 3
+\.
+
+
+--
+-- Name: edge_table_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
+--
+
+SELECT pg_catalog.setval('edge_table_id_seq', 18, true);
+
+
+--
+-- Name: edge_table_id_idx; Type: INDEX; Schema: public; Owner: postgres; Tablespace:
+--
+
+CREATE INDEX edge_table_id_idx ON edge_table USING btree (id);
+
+
+--
+-- Name: edge_table_source_idx; Type: INDEX; Schema: public; Owner: postgres; Tablespace:
+--
+
+CREATE INDEX edge_table_source_idx ON edge_table USING btree (source);
+
+
+--
+-- Name: edge_table_target_idx; Type: INDEX; Schema: public; Owner: postgres; Tablespace:
+--
+
+CREATE INDEX edge_table_target_idx ON edge_table USING btree (target);
+
+
+--
+-- Name: edge_table_the_geom_gidx; Type: INDEX; Schema: public; Owner: postgres; Tablespace:
+--
+
+CREATE INDEX edge_table_the_geom_gidx ON edge_table USING gist (the_geom);
+
+
+--
+-- PostgreSQL database dump complete
+--
+
diff --git a/src/common/test/common-any-02.rest b/src/common/test/common-any-02.result
similarity index 96%
rename from src/common/test/common-any-02.rest
rename to src/common/test/common-any-02.result
index 2914bc4..7bbeb48 100644
--- a/src/common/test/common-any-02.rest
+++ b/src/common/test/common-any-02.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -9,7 +9,7 @@
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
diff --git a/src/common/test/common-any-02.test b/src/common/test/common-any-02.test.sql
similarity index 100%
rename from src/common/test/common-any-02.test
rename to src/common/test/common-any-02.test.sql
diff --git a/src/common/test/common-any-03.rest b/src/common/test/common-any-03.result
similarity index 94%
rename from src/common/test/common-any-03.rest
rename to src/common/test/common-any-03.result
index 47a4cbb..9f27f38 100644
--- a/src/common/test/common-any-03.rest
+++ b/src/common/test/common-any-03.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edges2',1e-05,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
NOTICE: Rows with NULL geometry or NULL id: 0
diff --git a/src/common/test/common-any-03.test b/src/common/test/common-any-03.test.sql
similarity index 100%
rename from src/common/test/common-any-03.test
rename to src/common/test/common-any-03.test.sql
diff --git a/src/common/test/common-any-04.rest b/src/common/test/common-any-04.result
similarity index 98%
rename from src/common/test/common-any-04.rest
rename to src/common/test/common-any-04.result
index 604876e..4d83406 100644
--- a/src/common/test/common-any-04.rest
+++ b/src/common/test/common-any-04.result
@@ -1,8 +1,8 @@
8
NOTICE: PROCESSING:
NOTICE: pgr_nodeNetwork('unnoded',1e-06,'the_geom','id','noded')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Processing, pelase wait .....
+ NOTICE: Performing checks, please wait .....
+ NOTICE: Processing, please wait .....
NOTICE: Splitted Edges: 8
NOTICE: Untouched Edges: 0
NOTICE: Total original Edges: 8
@@ -14,7 +14,7 @@
OK
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('unnoded_noded',1e-06,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 40 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -23,7 +23,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('unnoded_noded',1e-06,'the_geom','id','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
@@ -111,7 +111,7 @@ OK
public.noded2.the_geom SRID:0 TYPE:LINESTRING DIMS:2
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('noded2',1e-06,'the_geom','gid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 40 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -120,7 +120,7 @@ public.noded2.the_geom SRID:0 TYPE:LINESTRING DIMS:2
OK
NOTICE: PROCESSING:
NOTICE: pgr_analyzeGraph('noded2',1e-06,'the_geom','gid','source','target','true')
- NOTICE: Performing checks, pelase wait...
+ NOTICE: Performing checks, please wait...
NOTICE: Analyzing for dead ends. Please wait...
NOTICE: Analyzing for gaps. Please wait...
NOTICE: Analyzing for isolated edges. Please wait...
diff --git a/src/common/test/common-any-04.test b/src/common/test/common-any-04.test.sql
similarity index 100%
rename from src/common/test/common-any-04.test
rename to src/common/test/common-any-04.test.sql
diff --git a/src/common/test/common-any-05.rest b/src/common/test/common-any-05.result
similarity index 97%
rename from src/common/test/common-any-05.rest
rename to src/common/test/common-any-05.result
index 710d8d4..0e9f7e6 100644
--- a/src/common/test/common-any-05.rest
+++ b/src/common/test/common-any-05.result
@@ -2,7 +2,7 @@ public.noded3.the_geom SRID:0 TYPE:MULTILINESTRING DIMS:2
---------------------------------
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('noded3',1e-06,'the_geom','gid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 40 edges
NOTICE: Rows with NULL geometry or NULL id: 0
diff --git a/src/common/test/common-any-05.test b/src/common/test/common-any-05.test.sql
similarity index 100%
rename from src/common/test/common-any-05.test
rename to src/common/test/common-any-05.test.sql
diff --git a/src/common/test/createTopology-any-01.rest b/src/common/test/createTopology-any-01.rest
deleted file mode 100644
index a82ddcb..0000000
--- a/src/common/test/createTopology-any-01.rest
+++ /dev/null
@@ -1,501 +0,0 @@
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'The_Geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'The_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'The_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','Source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 14 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','eid<15 and eid>5')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 9 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges22',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: -------> edges22 not found
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Geometry column "geom" not found in public.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','gid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: id column "gid" not found in public.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','sourc','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "sourc" not found in public.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','source','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source and target columns have the same name "source" in public.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','the_geom','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "the_geom" is not of integer type
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','the_geom','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: target column "the_geom" is not of integer type
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public."Edges2" is: public."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 22 edges
- NOTICE: Rows with NULL geometry or NULL id: 1
- NOTICE: Vertices table for table public."Edges2" is: public."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 21 edges
- NOTICE: Rows with NULL geometry or NULL id: 2
- NOTICE: Vertices table for table public."Edges2" is: public."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.Edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 21 edges
- NOTICE: Rows with NULL geometry or NULL id: 2
- NOTICE: Vertices table for table public."Edges2" is: public."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Public.edges2',1e-06,'The_Geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'The_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('PUBLIC.Edges2',1e-06,'The_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 21 edges
- NOTICE: Rows with NULL geometry or NULL id: 2
- NOTICE: Vertices table for table public."Edges2" is: public."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','Source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 14 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 14 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges22',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: -------> public.edges22 not found
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Geometry column "geom" not found in public.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','gid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: id column "gid" not found in public.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.Edges2',1e-06,'the_geom','eid','sourc','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "sourc" not found in public.Edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','source','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source and target columns have the same name "source" in public.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','the_geom','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "the_geom" is not of integer type
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('public.edges2',1e-06,'the_geom','eid','source','the_geom','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: target column "the_geom" is not of integer type
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 21 edges
- NOTICE: Rows with NULL geometry or NULL id: 2
- NOTICE: Vertices table for table myschema."Edges2" is: myschema."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'The_Geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'The_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'The_geom','Eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 21 edges
- NOTICE: Rows with NULL geometry or NULL id: 2
- NOTICE: Vertices table for table myschema."Edges2" is: myschema."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','Source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 14 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 14 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges22',1e-06,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: -------> edges22 not found
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Geometry column "geom" not found in myschema.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','gid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: id column "gid" not found in myschema.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','sourc','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "sourc" not found in myschema.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','source','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source and target columns have the same name "source" in myschema.edges2
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','the_geom','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "the_geom" is not of integer type
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','the_geom','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: target column "the_geom" is not of integer type
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 14 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target','eid<15 and eid>5')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 8 edges
- NOTICE: Rows with NULL geometry or NULL id: 0
- NOTICE: Vertices table for table myschema."Edges2" is: myschema."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target',' the_geom && (select st_buffer(the_geom,0.0001) as buffer from "Edges2" where eid=6)')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: Creating Topology, Please wait...
- NOTICE: -------------> TOPOLOGY CREATED FOR 3 edges
- NOTICE: Rows with NULL geometry or NULL id: 1
- NOTICE: Vertices table for table myschema."Edges2" is: myschema."Edges2_vertices_pgr"
- NOTICE: ----------------------------------------------
-OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('edges2',1e-06,'the_geom','eid','source','target','eid<')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Condition is not correct, please execute the following query to test your condition
- NOTICE: select * from myschema.edges2 WHERE true AND (eid<) limit 1
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target','eid<15 and ed>5')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Condition is not correct, please execute the following query to test your condition
- NOTICE: select * from myschema."Edges2" WHERE true AND (eid<15 and ed>5) limit 1
-FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createTopology('Edges2',1e-06,'the_geom','eid','source','target',' the_geom && (select st_buffer(the_geom,0.0001 as buffer from "Edges2" where eid=6)')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Condition is not correct, please execute the following query to test your condition
- NOTICE: select * from myschema."Edges2" WHERE true AND ( the_geom && (select st_buffer(the_geom,0.0001 as buffer from "Edges2" where eid=6)) limit 1
-FAIL
diff --git a/src/common/test/createTopology-any-01.result b/src/common/test/createTopology-any-01.result
new file mode 100644
index 0000000..db6cdbd
--- /dev/null
+++ b/src/common/test/createTopology-any-01.result
@@ -0,0 +1,66 @@
+1|t
+2|t
+3|t
+4|t
+5|t
+6|t
+7|t
+8|t
+9|t
+10|t
+11|t
+12|t
+13|t
+14|t
+15|t
+16|t
+17|t
+18|t
+19|t
+20|t
+21|t
+22|t
+23|t
+24|t
+25|t
+26|t
+27|t
+28|t
+29|t
+30|t
+30|t
+31|t
+32|t
+33|t
+34|t
+35|t
+36|t
+37|t
+38|t
+39|t
+40|t
+41|t
+42|t
+43|t
+44|t
+45|t
+46|t
+47|t
+48|t
+49|t
+50|t
+51|t
+52|t
+53|t
+54|t
+55|t
+56|t
+57|t
+58|t
+59|t
+60|t
+61|t
+62|t
+63|t
+64|t
+65|t
diff --git a/src/common/test/createTopology-any-01.test b/src/common/test/createTopology-any-01.test
deleted file mode 100644
index f09b310..0000000
--- a/src/common/test/createTopology-any-01.test
+++ /dev/null
@@ -1,133 +0,0 @@
-set client_min_messages to warning;
-
-SET search_path TO public;
-drop table if exists "Edges2";
-drop table if exists "Edges2_vertices_pgr";
-drop schema if exists "myschema" cascade;
-
-set client_min_messages to notice;
-
--- The following should be OK
-
-select pgr_createTopology('edges2', 0.000001, id:='eid');
-select pgr_createTopology('Edges2', 0.000001, 'the_geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'The_Geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'Eid');
-select pgr_createTopology('edges2', 0.000001, 'The_geom', 'Eid');
-select pgr_createTopology('Edges2', 0.000001, 'The_geom', 'Eid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','Source');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source','target');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',rows_where:='eid<15');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',source:='source');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='target',rows_where:='eid<15 and eid>5');
-
--- the following tests should FAIL
-
-select pgr_createTopology('edges22', 0.000001, 'the_geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'gid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','sourc');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='source');
-select pgr_createTopology('edges2', 0.000001, id:='eid',source:='the_geom');
-select pgr_createTopology('edges2', 0.000001, id:='eid',target:='the_geom');
-
--- Testing with table with a similar name
-
-select * into "Edges2" from edges2;
-
--- The following should be OK
-
-select pgr_createTopology('Edges2', 0.000001,id:='eid');
-update "Edges2" set the_geom=NULL where eid=5;
-select pgr_createTopology('Edges2', 0.000001,id:='eid');
-update "Edges2" set eid=NULL where eid=7;
-select pgr_createTopology('Edges2', 0.000001,id:='eid');
-
-create schema myschema;
-SET search_path TO myschema,public;
-
--- reaching tables when located in another schema
--- the following should be OK
-
-select pgr_createTopology('public.edges2', 0.000001, id:='eid');
-select pgr_createTopology('public.Edges2', 0.000001, 'the_geom', 'eid');
-select pgr_createTopology('Public.edges2', 0.000001, 'The_Geom', 'eid');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'Eid');
-select pgr_createTopology('public.edges2', 0.000001, 'The_geom', 'Eid');
-select pgr_createTopology('PUBLIC.Edges2', 0.000001, 'The_geom', 'Eid');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid','source');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid','Source');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid','source','target');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',rows_where:='eid<15');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',source:='source');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',target:='target',rows_where:='eid<15');
-
--- the following tests should fail
-
-select pgr_createTopology('public.edges22', 0.000001, 'the_geom', 'eid');
-select pgr_createTopology('public.edges2', 0.000001, 'geom', 'eid');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'gid');
-select pgr_createTopology('public.Edges2', 0.000001, 'the_geom', 'eid','sourc');
-select pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',target:='source');
-select pgr_createTopology('public.edges2', 0.000001, id:='eid',source:='the_geom');
-select pgr_createTopology('public.edges2', 0.000001, id:='eid',target:='the_geom');
-
--- creating tables with similar names in myschema
-
-select * into edges2 from public.edges2;
-select * into "Edges2" from public."Edges2";
-
--- The following should be OK
-
-select pgr_createTopology('edges2', 0.000001, id:='eid');
-select pgr_createTopology('Edges2', 0.000001, 'the_geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'The_Geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'Eid');
-select pgr_createTopology('edges2', 0.000001, 'The_geom', 'Eid');
-select pgr_createTopology('Edges2', 0.000001, 'The_geom', 'Eid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','Source');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source','target');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',rows_where:='eid<15');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',source:='source');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='target',rows_where:='eid<15');
-
--- the following tests should FAIL
-
-select pgr_createTopology('edges22', 0.000001, 'the_geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'geom', 'eid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'gid');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','sourc');
-select pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='source');
-select pgr_createTopology('edges2', 0.000001, id:='eid',source:='the_geom');
-select pgr_createTopology('edges2', 0.000001, id:='eid',target:='the_geom');
-
---Test of the rows_where clause
-
-
--- The following should be OK
-select pgr_createTopology('edges2', 0.000001, id:= 'eid',rows_where:='eid<15');
-select pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:='eid<15 and eid>5');
-select pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:=' the_geom && (select st_buffer(the_geom,0.0001) as buffer from "Edges2" where eid=6)') ;
-
--- The following should FAIL (working on myschema)
-
-select pgr_createTopology('edges2', 0.000001, id:= 'eid',rows_where:='eid<');
-select pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:='eid<15 and ed>5');
-select pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:=' the_geom && (select st_buffer(the_geom,0.0001 as buffer from "Edges2" where eid=6)') ;
-
--- BIG TABLE TEST TAKES TIME
---create table bigtable ( id bigserial PRIMARY KEY, source smallint,target smallint);
---SELECT AddGeometryColumn( 'bigtable', 'the_geom', 0, 'LINESTRING',2);
---insert into bigtable (the_geom) ( select ST_MakeLine(ST_MakePoint(random()*1000,random()*1000), ST_MakePoint(random()*1000,random()*1000))
---from (SELECT * FROM generate_series(1,20000) AS id) AS x) ;
---select pgr_createTopology('bigtable', 0.000001);
-
-
-set client_min_messages to warning;
-
-SET search_path TO public;
-drop table if exists "Edges2";
-drop table if exists "Edges2_vertices_pgr";
-drop schema if exists "myschema" cascade;
diff --git a/src/common/test/createTopology-any-01.test.sql b/src/common/test/createTopology-any-01.test.sql
new file mode 100644
index 0000000..17a6350
--- /dev/null
+++ b/src/common/test/createTopology-any-01.test.sql
@@ -0,0 +1,133 @@
+\set VERBOSITY 'terse'
+
+set client_min_messages to warning;
+SET search_path TO public;
+drop table if exists "Edges2";
+drop table if exists "Edges2_vertices_pgr";
+drop schema if exists "myschema" cascade;
+
+
+-- The following should be OK
+
+select 1, pgr_createTopology('edges2', 0.000001, id:='eid') = 'OK';
+select 2, pgr_createTopology('Edges2', 0.000001, 'the_geom', 'eid') = 'OK';
+select 3, pgr_createTopology('edges2', 0.000001, 'The_Geom', 'eid') = 'OK';
+select 4, pgr_createTopology('edges2', 0.000001, 'the_geom', 'Eid') = 'OK';
+select 5, pgr_createTopology('edges2', 0.000001, 'The_geom', 'Eid') = 'OK';
+select 6, pgr_createTopology('Edges2', 0.000001, 'The_geom', 'Eid') = 'OK';
+select 7, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source') = 'OK';
+select 8, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','Source') = 'OK';
+select 9, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source','target') = 'OK';
+select 10, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',rows_where:='eid<15') = 'OK';
+select 11, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',source:='source') = 'OK';
+select 12, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='target',rows_where:='eid<15 and eid>5') = 'OK';
+
+-- the following tests should FAIL
+
+select 13, pgr_createTopology('edges22', 0.000001, 'the_geom', 'eid') = 'FAIL';
+select 14, pgr_createTopology('edges2', 0.000001, 'geom', 'eid') = 'FAIL';
+select 15, pgr_createTopology('edges2', 0.000001, 'the_geom', 'gid') = 'FAIL';
+select 16, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','sourc') = 'FAIL';
+select 17, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='source') = 'FAIL';
+select 18, pgr_createTopology('edges2', 0.000001, id:='eid',source:='the_geom') = 'FAIL';
+select 19, pgr_createTopology('edges2', 0.000001, id:='eid',target:='the_geom') = 'FAIL';
+
+-- Testing with table with a similar name
+
+select * into "Edges2" from edges2;
+
+-- The following should be OK
+
+select 20, pgr_createTopology('Edges2', 0.000001,id:='eid') = 'OK';
+update "Edges2" set the_geom=NULL where eid=5;
+select 21, pgr_createTopology('Edges2', 0.000001,id:='eid') = 'OK';
+update "Edges2" set eid=NULL where eid=7;
+select 22, pgr_createTopology('Edges2', 0.000001,id:='eid') = 'OK';
+
+create schema myschema;
+SET search_path TO myschema,public;
+
+-- reaching tables when located in another schema
+-- the following should be OK
+
+select 23, pgr_createTopology('public.edges2', 0.000001, id:='eid') = 'OK';
+select 24, pgr_createTopology('public.Edges2', 0.000001, 'the_geom', 'eid') = 'OK';
+select 25, pgr_createTopology('Public.edges2', 0.000001, 'The_Geom', 'eid') = 'OK';
+select 26, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'Eid') = 'OK';
+select 27, pgr_createTopology('public.edges2', 0.000001, 'The_geom', 'Eid') = 'OK';
+select 28, pgr_createTopology('PUBLIC.Edges2', 0.000001, 'The_geom', 'Eid') = 'OK';
+select 29, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid','source') = 'OK';
+select 30, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid','Source') = 'OK';
+select 30, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid','source','target') = 'OK';
+select 31, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',rows_where:='eid<15') = 'OK';
+select 32, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',source:='source') = 'OK';
+select 33, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',target:='target',rows_where:='eid<15') = 'OK';
+
+-- the following tests should fail
+
+select 34, pgr_createTopology('public.edges22', 0.000001, 'the_geom', 'eid') = 'FAIL';
+select 35, pgr_createTopology('public.edges2', 0.000001, 'geom', 'eid') = 'FAIL';
+select 36, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'gid') = 'FAIL';
+select 37, pgr_createTopology('public.Edges2', 0.000001, 'the_geom', 'eid','sourc') = 'FAIL';
+select 38, pgr_createTopology('public.edges2', 0.000001, 'the_geom', 'eid',target:='source') = 'FAIL';
+select 39, pgr_createTopology('public.edges2', 0.000001, id:='eid',source:='the_geom') = 'FAIL';
+select 40, pgr_createTopology('public.edges2', 0.000001, id:='eid',target:='the_geom') = 'FAIL';
+
+-- creating tables with similar names in myschema
+
+select * into edges2 from public.edges2;
+select * into "Edges2" from public."Edges2";
+
+-- The following should be OK
+
+select 41, pgr_createTopology('edges2', 0.000001, id:='eid') = 'OK';
+select 42, pgr_createTopology('Edges2', 0.000001, 'the_geom', 'eid') = 'OK';
+select 43, pgr_createTopology('edges2', 0.000001, 'The_Geom', 'eid') = 'OK';
+select 44, pgr_createTopology('edges2', 0.000001, 'the_geom', 'Eid') = 'OK';
+select 45, pgr_createTopology('edges2', 0.000001, 'The_geom', 'Eid') = 'OK';
+select 46, pgr_createTopology('Edges2', 0.000001, 'The_geom', 'Eid') = 'OK';
+select 47, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source') = 'OK';
+select 48, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','Source') = 'OK';
+select 49, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','source','target') = 'OK';
+select 50, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',rows_where:='eid<15') = 'OK';
+select 51, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',source:='source') = 'OK';
+select 52, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='target',rows_where:='eid<15') = 'OK';
+
+-- the following tests should FAIL
+
+select 53, pgr_createTopology('edges22', 0.000001, 'the_geom', 'eid') = 'FAIL';
+select 54, pgr_createTopology('edges2', 0.000001, 'geom', 'eid') = 'FAIL';
+select 55, pgr_createTopology('edges2', 0.000001, 'the_geom', 'gid') = 'FAIL';
+select 56, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid','sourc') = 'FAIL';
+select 57, pgr_createTopology('edges2', 0.000001, 'the_geom', 'eid',target:='source') = 'FAIL';
+select 58, pgr_createTopology('edges2', 0.000001, id:='eid',source:='the_geom') = 'FAIL';
+select 59, pgr_createTopology('edges2', 0.000001, id:='eid',target:='the_geom') = 'FAIL';
+
+--Test of the rows_where clause
+
+
+-- The following should be OK
+select 60, pgr_createTopology('edges2', 0.000001, id:= 'eid',rows_where:='eid<15') = 'OK';
+select 61, pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:='eid<15 and eid>5') = 'OK';
+select 62, pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:=' the_geom && (select st_buffer(the_geom,0.0001) as buffer from "Edges2" where eid=6)') = 'OK';
+
+-- The following should FAIL (working on myschema)
+
+select 63, pgr_createTopology('edges2', 0.000001, id:= 'eid',rows_where:='eid<') = 'FAIL';
+select 64, pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:='eid<15 and ed>5') = 'FAIL';
+select 65, pgr_createTopology('Edges2', 0.000001, id:= 'eid',rows_where:=' the_geom && (select st_buffer(the_geom,0.0001 as buffer from "Edges2" where eid=6)') = 'FAIL';
+
+-- BIG TABLE TEST TAKES TIME
+--create table bigtable ( id bigserial PRIMARY KEY, source smallint,target smallint);
+--SELECT AddGeometryColumn( 'bigtable', 'the_geom', 0, 'LINESTRING',2);
+--insert into bigtable (the_geom) ( select ST_MakeLine(ST_MakePoint(random()*1000,random()*1000), ST_MakePoint(random()*1000,random()*1000))
+--from (SELECT * FROM generate_series(1,20000) AS id) AS x) ;
+--select 66, pgr_createTopology('bigtable', 0.000001);
+
+
+set client_min_messages to warning;
+
+SET search_path TO public;
+drop table if exists "Edges2";
+drop table if exists "Edges2_vertices_pgr";
+drop schema if exists "myschema" cascade;
diff --git a/src/common/test/createVerticesTable-any-01.rest b/src/common/test/createVerticesTable-any-01.result
similarity index 74%
rename from src/common/test/createVerticesTable-any-01.rest
rename to src/common/test/createVerticesTable-any-01.result
index d90e842..259d236 100644
--- a/src/common/test/createVerticesTable-any-01.rest
+++ b/src/common/test/createVerticesTable-any-01.result
@@ -1,6 +1,6 @@
NOTICE: PROCESSING:
NOTICE: pgr_createTopology('edges2',1e-05,'the_geom','eid','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Creating Topology, Please wait...
NOTICE: -------------> TOPOLOGY CREATED FOR 23 edges
NOTICE: Rows with NULL geometry or NULL id: 0
@@ -10,7 +10,7 @@ OK
NOTICE: table "edges2_vertex_pgr" does not exist, skipping
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -21,7 +21,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -32,7 +32,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','The_Geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -43,7 +43,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -54,7 +54,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','The_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -65,7 +65,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','The_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -76,7 +76,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -87,7 +87,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','Source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -98,7 +98,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -109,7 +109,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 13 VERTICES
NOTICE: FOR 16 EDGES
@@ -120,7 +120,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -131,7 +131,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','eid<15 and eid>5')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 10 EDGES
@@ -140,44 +140,16 @@ OK
NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
NOTICE: ----------------------------------------------
OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges22','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: -------> edges22 not found
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Geometry column "geom" not found in public.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','gid','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "gid" not found in public.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','sourc','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "sourc" not found in public.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','source','source','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source and target columns have the same name "source" in public.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','the_geom','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "the_geom" is not of integer type
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','source','the_geom','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: target column "the_geom" is not of integer type
FAIL
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -188,7 +160,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 24 EDGES
@@ -199,7 +171,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 24 EDGES
@@ -210,7 +182,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -221,7 +193,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.Edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 24 EDGES
@@ -232,7 +204,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Public.edges2','The_Geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -243,7 +215,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','The_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -254,7 +226,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('PUBLIC.Edges2','The_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 24 EDGES
@@ -265,7 +237,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -276,7 +248,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','the_geom','Source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -287,7 +259,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -298,7 +270,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 13 VERTICES
NOTICE: FOR 16 EDGES
@@ -309,7 +281,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -320,7 +292,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating public.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 13 VERTICES
NOTICE: FOR 16 EDGES
@@ -329,44 +301,16 @@ OK
NOTICE: Vertices table for table public.edges2 is: public.edges2_vertices_pgr
NOTICE: ----------------------------------------------
OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('public.edges22','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: -------> public.edges22 not found
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('public.edges2','geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Geometry column "geom" not found in public.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('public.edges2','the_geom','gid','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "gid" not found in public.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('public.Edges2','the_geom','sourc','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "sourc" not found in public.Edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','source','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source and target columns have the same name "source" in public.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('public.edges2','the_geom','the_geom','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "the_geom" is not of integer type
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('public.edges2','the_geom','source','the_geom','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: target column "the_geom" is not of integer type
FAIL
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -377,7 +321,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 24 EDGES
@@ -388,7 +332,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','The_Geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -399,7 +343,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','The_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -410,7 +354,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','The_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 24 EDGES
@@ -421,7 +365,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -432,7 +376,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','Source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -443,7 +387,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -454,7 +398,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 13 VERTICES
NOTICE: FOR 16 EDGES
@@ -465,7 +409,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 20 VERTICES
NOTICE: FOR 23 EDGES
@@ -476,7 +420,7 @@ OK
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 13 VERTICES
NOTICE: FOR 16 EDGES
@@ -485,44 +429,16 @@ OK
NOTICE: Vertices table for table myschema.edges2 is: myschema.edges2_vertices_pgr
NOTICE: ----------------------------------------------
OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges22','the_geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: -------> edges22 not found
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','geom','source','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Geometry column "geom" not found in myschema.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','gid','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "gid" not found in myschema.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','sourc','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "sourc" not found in myschema.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','source','source','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source and target columns have the same name "source" in myschema.edges2
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','the_geom','target','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: source column "the_geom" is not of integer type
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','source','the_geom','true')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: target column "the_geom" is not of integer type
FAIL
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','eid<15')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 13 VERTICES
NOTICE: FOR 16 EDGES
@@ -533,7 +449,7 @@ FAIL
OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target','eid<15 and eid>5')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 9 VERTICES
NOTICE: FOR 10 EDGES
@@ -545,7 +461,7 @@ OK
NOTICE: PROCESSING:
NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target',' the_geom && (select st_buffer(the_geom,0.0001) as buffer from "Edges2"
where eid=6)')
- NOTICE: Performing checks, pelase wait .....
+ NOTICE: Performing checks, please wait .....
NOTICE: Populating myschema.Edges2_vertices_pgr, please wait...
NOTICE: -----> VERTICES TABLE CREATED WITH 5 VERTICES
NOTICE: FOR 4 EDGES
@@ -554,21 +470,6 @@ where eid=6)')
NOTICE: Vertices table for table myschema."Edges2" is: myschema."Edges2_vertices_pgr"
NOTICE: ----------------------------------------------
OK
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('edges2','the_geom','source','target','eid<')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Condition is not correct, please execute the following query to test your condition
- NOTICE: select * from myschema.edges2 WHERE true AND (eid<) limit 1
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target','eid<15 and ed>5')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Condition is not correct, please execute the following query to test your condition
- NOTICE: select * from myschema."Edges2" WHERE true AND (eid<15 and ed>5) limit 1
FAIL
- NOTICE: PROCESSING:
- NOTICE: pgr_createVerticesTable('Edges2','the_geom','source','target',' the_geom && (select st_buffer(the_geom,0.0001 as buffer from "Edges2" where eid=6)')
- NOTICE: Performing checks, pelase wait .....
- NOTICE: ERROR: Condition is not correct, please execute the following query to test your condition
- NOTICE: select * from myschema."Edges2" WHERE true AND ( the_geom && (select st_buffer(the_geom,0.0001 as buffer from "Edges2" where eid=6)) limit 1
FAIL
diff --git a/src/common/test/createVerticesTable-any-01.test b/src/common/test/createVerticesTable-any-01.test.sql
similarity index 97%
rename from src/common/test/createVerticesTable-any-01.test
rename to src/common/test/createVerticesTable-any-01.test.sql
index 8a8fef1..e5522a3 100644
--- a/src/common/test/createVerticesTable-any-01.test
+++ b/src/common/test/createVerticesTable-any-01.test.sql
@@ -25,6 +25,7 @@ select pgr_createVerticesTable('edges2', 'the_geom',source:='source');
select pgr_createVerticesTable('edges2', 'the_geom',target:='target',rows_where:='eid<15 and eid>5');
-- the following tests should FAIL
+set client_min_messages to warning;
select pgr_createVerticesTable('edges22', 'the_geom');
select pgr_createVerticesTable('edges2', 'geom');
@@ -39,6 +40,7 @@ select pgr_createVerticesTable('edges2', target:='the_geom');
select * into "Edges2" from edges2;
-- The following should be OK
+set client_min_messages to notice;
select pgr_createVerticesTable('Edges2');
update "Edges2" set the_geom=NULL where eid=5;
@@ -65,6 +67,7 @@ select pgr_createVerticesTable('public.edges2', 'the_geom',source:='source');
select pgr_createVerticesTable('public.edges2', 'the_geom',target:='target',rows_where:='eid<15');
-- the following tests should fail
+set client_min_messages to warning;
select pgr_createVerticesTable('public.edges22', 'the_geom');
select pgr_createVerticesTable('public.edges2', 'geom');
@@ -80,6 +83,7 @@ select * into edges2 from public.edges2;
select * into "Edges2" from public."Edges2";
-- The following should be OK
+set client_min_messages to notice;
select pgr_createVerticesTable('edges2');
select pgr_createVerticesTable('Edges2', 'the_geom');
@@ -94,6 +98,7 @@ select pgr_createVerticesTable('edges2', 'the_geom',source:='source');
select pgr_createVerticesTable('edges2', 'the_geom',target:='target',rows_where:='eid<15');
-- the following tests should FAIL
+set client_min_messages to warning;
select pgr_createVerticesTable('edges22', 'the_geom');
select pgr_createVerticesTable('edges2', 'geom');
@@ -107,12 +112,14 @@ select pgr_createVerticesTable('edges2', target:='the_geom');
-- The following should be OK
+set client_min_messages to notice;
select pgr_createVerticesTable('edges2', rows_where:='eid<15');
select pgr_createVerticesTable('Edges2', rows_where:='eid<15 and eid>5');
select pgr_createVerticesTable('Edges2', rows_where:=' the_geom && (select st_buffer(the_geom,0.0001) as buffer from "Edges2"
where eid=6)') ;
-- The following should FAIL (working on myschema)
+set client_min_messages to warning;
select pgr_createVerticesTable('edges2',rows_where:='eid<');
select pgr_createVerticesTable('Edges2', rows_where:='eid<15 and ed>5');
diff --git a/src/common/test/gettablename-any-01.rest b/src/common/test/gettablename-any-01.rest
deleted file mode 100644
index e07c93e..0000000
--- a/src/common/test/gettablename-any-01.rest
+++ /dev/null
@@ -1,151 +0,0 @@
-public|streets
-public|Streets
-public|streets
-public|
-s1|streets
-s1|Streets
-s1|streets
-s1|
-s2|
-s2|Streets
-S2|streets
-s3|Streets
-s3|sTreets
-s3|StrEets
-s3|
-s3|
-s3|
-s1|streets
-s1|Streets
-s1|streets
-s1|
-s1|streets
-s1|Streets
-s1|streets
-s1|
-s2|
-s2|Streets
-S2|streets
-s3|Streets
-s3|sTreets
-s3|StrEets
-s3|
-s3|
-s3|
-|
------TRUE----------------------------
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
------FALSE----------------------------
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
------TRUE----------------------------
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
-t
------FALSE----------------------------
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
-f
diff --git a/src/common/test/gettablename-any-01.result b/src/common/test/gettablename-any-01.result
new file mode 100644
index 0000000..9c48584
--- /dev/null
+++ b/src/common/test/gettablename-any-01.result
@@ -0,0 +1,35 @@
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
diff --git a/src/common/test/gettablename-any-01.test b/src/common/test/gettablename-any-01.test
deleted file mode 100644
index 5d1bb47..0000000
--- a/src/common/test/gettablename-any-01.test
+++ /dev/null
@@ -1,206 +0,0 @@
-set client_min_messages to warning;
-
-SET search_path TO "$user", public;
-
-create schema s1;
-create schema s2;
-create schema "S2";
-create schema s3;
-create table streets (id serial PRIMARY KEY,source integer,target integer);
-create table "Streets" (ID serial PRIMARY KEY,SOURCE integer,TARGET integer);
-create table s1.streets ("ID" serial PRIMARY KEY,sour integer,targ integer);
-create table s1."Streets" ("ID" serial PRIMARY KEY,"SOURCE" integer,"Target" integer);
-create table s2."Streets" (id serial ,source integer,target integer);
-create table "S2".streets (id serial ,source integer,target integer);
-create table s3."Streets" (id serial ,source integer,target integer);
-create table s3."sTreets" (id serial ,source integer,target integer);
-create table s3."StrEets" (id serial ,source integer,target integer);
-
-set client_min_messages to notice;
-
-select * from pgr_getTableName('StreEts'); --public.streets
-select * from pgr_getTableName('Streets'); --public.Streets
-select * from pgr_getTableName('streEts'); --public.streets
-select * from pgr_getTableName('streEts1'); --public.<null>
-
-select * from pgr_getTableName('s1.StreEts'); --s1.streets
-select * from pgr_getTableName('s1.Streets'); --s1.Streets
-select * from pgr_getTableName('S1.streEts'); --s1.streets
-select * from pgr_getTableName('S1.streEts1'); --s1.<null>
-
-select * from pgr_getTableName('s2.StreEts'); --s2.<null>
-select * from pgr_getTableName('s2.Streets'); --s2.Streets
-select * from pgr_getTableName('S2.streEts'); --S2.streets
-
-
-select * from pgr_getTableName('s3.Streets'); --s3.Streets
-select * from pgr_getTableName('s3.sTreets'); --s3.sTreets
-select * from pgr_getTableName('s3.StrEets'); --s3.StrEets
-select * from pgr_getTableName('s3.streets'); --s3.<null>
-select * from pgr_getTableName('s3.streetS'); --s3.<null>
-select * from pgr_getTableName('S3.streEts1'); --s3.<null>
-
-SET search_path TO s1,public;
-
-select * from pgr_getTableName('StreEts'); --s1.streets
-select * from pgr_getTableName('Streets'); --s1.Streets
-select * from pgr_getTableName('streEts'); --s1.streets
-select * from pgr_getTableName('streEts1'); --s1.<null>
-
-select * from pgr_getTableName('s1.StreEts'); --s1.streets
-select * from pgr_getTableName('s1.Streets'); --s1.Streets
-select * from pgr_getTableName('S1.streEts'); --s1.streets
-select * from pgr_getTableName('S1.streEts1'); --s1.<null>
-
-select * from pgr_getTableName('s2.StreEts'); --s2.<null>
-select * from pgr_getTableName('s2.Streets'); --s2.Streets
-select * from pgr_getTableName('S2.streEts'); --S2.streets
-
-
-select * from pgr_getTableName('s3.Streets'); --s3.Streets
-select * from pgr_getTableName('s3.sTreets'); --s3.sTreets
-select * from pgr_getTableName('s3.StrEets'); --s3.StrEets
-select * from pgr_getTableName('s3.streets'); --s3.<null>
-select * from pgr_getTableName('s3.streetS'); --s3.<null>
-select * from pgr_getTableName('S3.streEts1'); --s3.<null>
-
-select * from pgr_getTableName('S4.streEts1'); --<null>.<null>
-
-SET search_path TO "$user", public;
-
-\echo '-----TRUE----------------------------'
-
-select pgr_isColumnInTable('streets','id'); --t
-select pgr_isColumnInTable('streets','source'); --t
-select pgr_isColumnInTable('streets','target'); --t
-select pgr_isColumnInTable('streets','ID'); --t
-select pgr_isColumnInTable('streets','Source'); --t
-select pgr_isColumnInTable('streets','Target'); --t
-select pgr_isColumnInTable('Streets','id'); --t
-select pgr_isColumnInTable('Streets','source'); --t
-select pgr_isColumnInTable('Streets','target'); --t
-select pgr_isColumnInTable('Streets','ID'); --t
-select pgr_isColumnInTable('Streets','SOURCE'); --t
-select pgr_isColumnInTable('Streets','Target'); --t
-select pgr_isColumnInTable('s1.streets','ID'); --t
-select pgr_isColumnInTable('s1.streets','Targ'); --t
-select pgr_isColumnInTable('s1.Streets','ID'); --t
-select pgr_isColumnInTable('s1.Streets','SOURCE'); --t
-select pgr_isColumnInTable('s1.Streets','Target'); --t
-select pgr_isColumnIndexed('streets','id'); --t
-select pgr_isColumnIndexed('streets','ID'); --t
-select pgr_isColumnIndexed('Streets','id'); --t
-select pgr_isColumnIndexed('Streets','ID'); --t
-select pgr_isColumnIndexed('s1.streets','ID'); --t
-select pgr_isColumnIndexed('s1.Streets','ID'); --t
-
-\echo '-----FALSE----------------------------'
-select pgr_isColumnInTable('streets','Targ'); --f
-select pgr_isColumnInTable('Streets','Targ'); --f
-select pgr_isColumnInTable('s1.STREETS','id'); --f
-select pgr_isColumnInTable('s1.STREETS','source'); --f
-select pgr_isColumnInTable('s1.stReets','target'); --f
-select pgr_isColumnInTable('s1.streets','SOURCE'); --f
-select pgr_isColumnInTable('s1.streets','Target'); --f
-select pgr_isColumnInTable('s1.Streets','id'); --f
-select pgr_isColumnInTable('s1.Streets','source'); --f
-select pgr_isColumnInTable('s1.Streets','target'); --f
-select pgr_isColumnInTable('s1.Streets','Targ'); --f
-select pgr_isColumnIndexed('streets','source'); --f
-select pgr_isColumnIndexed('streets','target'); --f
-select pgr_isColumnIndexed('streets','Source'); --f
-select pgr_isColumnIndexed('streets','Target'); --f
-select pgr_isColumnIndexed('streets','Targ'); --f
-select pgr_isColumnIndexed('Streets','source'); --f
-select pgr_isColumnIndexed('Streets','target'); --f
-select pgr_isColumnIndexed('Streets','SOURCE'); --f
-select pgr_isColumnIndexed('Streets','Target'); --f
-select pgr_isColumnIndexed('Streets','Targ'); --f
-select pgr_isColumnIndexed('s1.STREETS','id'); --f
-select pgr_isColumnIndexed('s1.STREETS','source'); --f
-select pgr_isColumnIndexed('s1.stReets','target'); --f
-select pgr_isColumnIndexed('s1.streets','SOURCE'); --f
-select pgr_isColumnIndexed('s1.streets','Target'); --f
-select pgr_isColumnIndexed('s1.streets','Targ'); --f
-select pgr_isColumnIndexed('s1.Streets','id'); --f
-select pgr_isColumnIndexed('s1.Streets','source'); --f
-select pgr_isColumnIndexed('s1.Streets','target'); --f
-select pgr_isColumnIndexed('s1.Streets','SOURCE'); --f
-select pgr_isColumnIndexed('s1.Streets','Target'); --f
-select pgr_isColumnIndexed('s1.Streets','Targ'); --f
-
-
-SET search_path TO s1,public;
-
-\echo '-----TRUE----------------------------'
-select pgr_isColumnInTable('streets','ID'); --t
-select pgr_isColumnInTable('streets','Targ'); --t
-select pgr_isColumnInTable('Streets','ID'); --t
-select pgr_isColumnInTable('Streets','SOURCE'); --t
-select pgr_isColumnInTable('Streets','Target'); --t
-select pgr_isColumnInTable('s1.streets','ID'); --t
-select pgr_isColumnInTable('s1.streets','Targ'); --t
-select pgr_isColumnInTable('s1.Streets','ID'); --t
-select pgr_isColumnInTable('s1.Streets','SOURCE'); --t
-select pgr_isColumnInTable('s1.Streets','Target'); --t
-select pgr_isColumnIndexed('streets','ID'); --t
-select pgr_isColumnIndexed('Streets','ID'); --t
-select pgr_isColumnIndexed('s1.streets','ID'); --t
-select pgr_isColumnIndexed('s1.Streets','ID'); --t
-
-\echo '-----FALSE----------------------------'
-select pgr_isColumnInTable('streets','id'); --f
-select pgr_isColumnInTable('streets','source'); --f
-select pgr_isColumnInTable('streets','target'); --f
-select pgr_isColumnInTable('streets','Source'); --f
-select pgr_isColumnInTable('streets','Target'); --f
-select pgr_isColumnInTable('Streets','id'); --f
-select pgr_isColumnInTable('Streets','source'); --f
-select pgr_isColumnInTable('Streets','target'); --f
-select pgr_isColumnInTable('Streets','Targ'); --f
-select pgr_isColumnInTable('s1.STREETS','id'); --f
-select pgr_isColumnInTable('s1.STREETS','source'); --f
-select pgr_isColumnInTable('s1.stReets','target'); --f
-select pgr_isColumnInTable('s1.streets','SOURCE'); --f
-select pgr_isColumnInTable('s1.streets','Target'); --f
-select pgr_isColumnInTable('s1.Streets','id'); --f
-select pgr_isColumnInTable('s1.Streets','source'); --f
-select pgr_isColumnInTable('s1.Streets','target'); --f
-select pgr_isColumnInTable('s1.Streets','Targ'); --f
-select pgr_isColumnIndexed('streets','id'); --f
-select pgr_isColumnIndexed('streets','source'); --f
-select pgr_isColumnIndexed('streets','target'); --f
-select pgr_isColumnIndexed('streets','Source'); --f
-select pgr_isColumnIndexed('streets','Target'); --f
-select pgr_isColumnIndexed('streets','Targ'); --f
-select pgr_isColumnIndexed('Streets','id'); --f
-select pgr_isColumnIndexed('Streets','source'); --f
-select pgr_isColumnIndexed('Streets','target'); --f
-select pgr_isColumnIndexed('Streets','SOURCE'); --f
-select pgr_isColumnIndexed('Streets','Target'); --f
-select pgr_isColumnIndexed('Streets','Targ'); --f
-select pgr_isColumnIndexed('s1.STREETS','id'); --f
-select pgr_isColumnIndexed('s1.STREETS','source'); --f
-select pgr_isColumnIndexed('s1.stReets','target'); --f
-select pgr_isColumnIndexed('s1.streets','SOURCE'); --f
-select pgr_isColumnIndexed('s1.streets','Target'); --f
-select pgr_isColumnIndexed('s1.streets','Targ'); --f
-select pgr_isColumnIndexed('s1.Streets','id'); --f
-select pgr_isColumnIndexed('s1.Streets','source'); --f
-select pgr_isColumnIndexed('s1.Streets','target'); --f
-select pgr_isColumnIndexed('s1.Streets','SOURCE'); --f
-select pgr_isColumnIndexed('s1.Streets','Target'); --f
-select pgr_isColumnIndexed('s1.Streets','Targ'); --f
-
-set client_min_messages to warning;
-
-SET search_path TO "$user", public;
-
-drop table if exists streets;
-drop table if exists "Streets";
-drop schema if exists s1 cascade;
-drop schema if exists s2 cascade;
-drop schema if exists "S2" cascade;
-drop schema if exists s3 cascade;
-
-
diff --git a/src/common/test/gettablename-any-01.test.sql b/src/common/test/gettablename-any-01.test.sql
new file mode 100644
index 0000000..ea7b3da
--- /dev/null
+++ b/src/common/test/gettablename-any-01.test.sql
@@ -0,0 +1,83 @@
+set client_min_messages to warning;
+
+SET search_path TO "$user", public;
+
+create schema s1;
+create schema s2;
+create schema "S2";
+create schema s3;
+create table streets (id serial PRIMARY KEY,source integer,target integer);
+create table "Streets" (ID serial PRIMARY KEY,SOURCE integer,TARGET integer);
+create table s1.streets ("ID" serial PRIMARY KEY,sour integer,targ integer);
+create table s1."Streets" ("ID" serial PRIMARY KEY,"SOURCE" integer,"Target" integer);
+create table s2."Streets" (id serial ,source integer,target integer);
+create table "S2".streets (id serial ,source integer,target integer);
+create table s3."Streets" (id serial ,source integer,target integer);
+create table s3."sTreets" (id serial ,source integer,target integer);
+create table s3."StrEets" (id serial ,source integer,target integer);
+
+set client_min_messages to warning;
+
+select sname = 'public' and tname = 'streets' from _pgr_getTableName('StreEts'); --public.streets
+select sname = 'public' and tname = 'Streets' from _pgr_getTableName('Streets'); --public.Streets
+select sname = 'public' and tname = 'streets' from _pgr_getTableName('streEts'); --public.streets
+select sname = 'public' and tname is null from _pgr_getTableName('streEts1'); --public.<null>
+
+select sname = 's1' and tname = 'streets' from _pgr_getTableName('s1.StreEts'); --s1.streets
+select sname = 's1' and tname = 'Streets' from _pgr_getTableName('s1.Streets'); --s1.Streets
+select sname = 's1' and tname = 'streets' from _pgr_getTableName('S1.streEts'); --s1.streets
+select sname = 's1' and tname is null from _pgr_getTableName('S1.streEts1'); --s1.<null>
+
+select sname = 's2' and tname is null from _pgr_getTableName('s2.StreEts'); --s2.<null>
+select sname = 's2' and tname = 'Streets' from _pgr_getTableName('s2.Streets'); --s2.Streets
+select sname = 'S2' and tname = 'streets' from _pgr_getTableName('S2.streEts'); --S2.streets
+
+
+select sname = 's3' and tname = 'Streets' from _pgr_getTableName('s3.Streets'); --s3.Streets
+select sname = 's3' and tname = 'sTreets' from _pgr_getTableName('s3.sTreets'); --s3.sTreets
+select sname = 's3' and tname = 'StrEets' from _pgr_getTableName('s3.StrEets'); --s3.StrEets
+
+select sname = 's3' and tname is null from _pgr_getTableName('s3.streets'); --s3.<null>
+select sname = 's3' and tname is null from _pgr_getTableName('s3.streetS'); --s3.<null>
+select sname = 's3' and tname is null from _pgr_getTableName('S3.streEts1'); --s3.<null>
+
+SET search_path TO s1,public;
+
+select sname = 's1' and tname = 'streets' from _pgr_getTableName('StreEts'); --s1.streets
+select sname = 's1' and tname = 'Streets' from _pgr_getTableName('Streets'); --s1.Streets
+select sname = 's1' and tname = 'streets' from _pgr_getTableName('streEts'); --s1.streets
+select sname = 's1' and tname is null from _pgr_getTableName('streEts1'); --s1.<null>
+
+select sname = 's1' and tname = 'streets' from _pgr_getTableName('s1.StreEts'); --s1.streets
+select sname = 's1' and tname = 'Streets' from _pgr_getTableName('s1.Streets'); --s1.Streets
+select sname = 's1' and tname = 'streets' from _pgr_getTableName('S1.streEts'); --s1.streets
+select sname = 's1' and tname is null from _pgr_getTableName('S1.streEts1'); --s1.<null>
+
+select sname = 's2' and tname is null from _pgr_getTableName('s2.StreEts'); --s2.<null>
+select sname = 's2' and tname = 'Streets' from _pgr_getTableName('s2.Streets'); --s2.Streets
+select sname = 'S2' and tname = 'streets' from _pgr_getTableName('S2.streEts'); --S2.streets
+
+
+select sname = 's3' and tname = 'Streets' from _pgr_getTableName('s3.Streets'); --s3.Streets
+select sname = 's3' and tname = 'sTreets' from _pgr_getTableName('s3.sTreets'); --s3.sTreets
+select sname = 's3' and tname = 'StrEets' from _pgr_getTableName('s3.StrEets'); --s3.StrEets
+select sname = 's3' and tname is null from _pgr_getTableName('s3.streets'); --s3.<null>
+select sname = 's3' and tname is null from _pgr_getTableName('s3.streetS'); --s3.<null>
+select sname = 's3' and tname is null from _pgr_getTableName('S3.streEts1'); --s3.<null>
+
+select sname is null and tname is null from _pgr_getTableName('S4.streEts1'); --<null>.<null>
+
+SET search_path TO "$user", public;
+
+set client_min_messages to warning;
+
+SET search_path TO "$user", public;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop schema if exists s2 cascade;
+drop schema if exists "S2" cascade;
+drop schema if exists s3 cascade;
+
+
diff --git a/src/common/test/incrementalCreateTopology_any_01.result b/src/common/test/incrementalCreateTopology_any_01.result
new file mode 100644
index 0000000..fd28b94
--- /dev/null
+++ b/src/common/test/incrementalCreateTopology_any_01.result
@@ -0,0 +1,146 @@
+8
+1|B|||1|1|2|0|2|1|010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2|TF|||-1|1|2|1|3|1|0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3|TF|||-1|1|3|1|4|1|0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4|B|||1|1|2|1|2|2|0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5|FT|||1|-1|3|1|3|2|0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6|B|||1|1|0|2|1|2|01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7|B|||1|1|1|2|2|2|010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8|B|||1|1|2|2|3|2|0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+ NOTICE: PROCESSING:
+ NOTICE: pgr_createTopology('edge_table',0.0001,'the_geom','id','source','target','true')
+ NOTICE: Performing checks, please wait .....
+ NOTICE: Creating Topology, Please wait...
+ NOTICE: -------------> TOPOLOGY CREATED FOR 8 edges
+ NOTICE: Rows with NULL geometry or NULL id: 0
+ NOTICE: Vertices table for table public.edge_table is: public.edge_table_vertices_pgr
+ NOTICE: ----------------------------------------------
+OK
+18
+1|B|1|2|1|1|2|0|2|1|010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2|TF|2|3|-1|1|2|1|3|1|0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3|TF|3|4|-1|1|3|1|4|1|0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4|B|2|5|1|1|2|1|2|2|0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5|FT|3|6|1|-1|3|1|3|2|0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6|B|7|8|1|1|0|2|1|2|01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7|B|8|5|1|1|1|2|2|2|010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8|B|5|6|1|1|2|2|3|2|0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9|B|||1|1|3|2|4|2|0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10|B|||1|1|2|2|2|3|0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11|FT|||1|-1|3|2|3|3|0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12|FT|||1|-1|2|3|3|3|0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13|FT|||1|-1|3|3|4|3|0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14|B|||1|1|2|3|2|4|0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15|B|||1|1|4|2|4|3|0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16|B|||1|1|4|1|4|2|0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+17|B|||1|1|0.5|3.5|1.999999999999|3.5|010200000002000000000000000000E03F0000000000000C4068EEFFFFFFFFFF3F0000000000000C40
+18|B|||1|1|3.5|2.3|3.5|4|0102000000020000000000000000000C4066666666666602400000000000000C400000000000001040
+0
+ NOTICE: PROCESSING:
+ NOTICE: pgr_createTopology('edge_table',0.0001,'the_geom','id','source','target','true')
+ NOTICE: Performing checks, please wait .....
+ NOTICE: Creating Topology, Please wait...
+ NOTICE: -------------> TOPOLOGY CREATED FOR 10 edges
+ NOTICE: Rows with NULL geometry or NULL id: 0
+ NOTICE: Vertices table for table public.edge_table is: public.edge_table_vertices_pgr
+ NOTICE: ----------------------------------------------
+OK
+1|B|1|2|1|1|2|0|2|1|010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2|TF|2|3|-1|1|2|1|3|1|0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3|TF|3|4|-1|1|3|1|4|1|0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4|B|2|5|1|1|2|1|2|2|0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5|FT|3|6|1|-1|3|1|3|2|0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6|B|7|8|1|1|0|2|1|2|01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7|B|8|5|1|1|1|2|2|2|010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8|B|5|6|1|1|2|2|3|2|0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9|B|6|9|1|1|3|2|4|2|0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10|B|5|10|1|1|2|2|2|3|0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11|FT|6|11|1|-1|3|2|3|3|0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12|FT|10|11|1|-1|2|3|3|3|0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13|FT|11|12|1|-1|3|3|4|3|0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14|B|10|13|1|1|2|3|2|4|0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15|B|9|12|1|1|4|2|4|3|0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16|B|4|9|1|1|4|1|4|2|0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+17|B|14|15|1|1|0.5|3.5|1.999999999999|3.5|010200000002000000000000000000E03F0000000000000C4068EEFFFFFFFFFF3F0000000000000C40
+18|B|16|17|1|1|3.5|2.3|3.5|4|0102000000020000000000000000000C4066666666666602400000000000000C400000000000001040
+ NOTICE: PROCESSING:
+ NOTICE: pgr_createTopology('edge_table',0.0001,'the_geom','id','source','target','dir='B'')
+ NOTICE: Performing checks, please wait .....
+ NOTICE: Creating Topology, Please wait...
+ NOTICE: -------------> TOPOLOGY CREATED FOR 12 edges
+ NOTICE: Rows with NULL geometry or NULL id: 0
+ NOTICE: Vertices table for table public.edge_table is: public.edge_table_vertices_pgr
+ NOTICE: ----------------------------------------------
+OK
+1|B|10|11|1|1|2|0|2|1|010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2|TF|||-1|1|2|1|3|1|0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3|TF|||-1|1|3|1|4|1|0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4|B|11|3|1|1|2|1|2|2|0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5|FT|||1|-1|3|1|3|2|0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6|B|12|13|1|1|0|2|1|2|01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7|B|13|3|1|1|1|2|2|2|010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8|B|3|1|1|1|2|2|3|2|0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9|B|1|2|1|1|3|2|4|2|0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10|B|3|4|1|1|2|2|2|3|0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11|FT|||1|-1|3|2|3|3|0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12|FT|||1|-1|2|3|3|3|0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13|FT|||1|-1|3|3|4|3|0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14|B|4|5|1|1|2|3|2|4|0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15|B|2|6|1|1|4|2|4|3|0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16|B|7|2|1|1|4|1|4|2|0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+17|B|8|9|1|1|0.5|3.5|1.999999999999|3.5|010200000002000000000000000000E03F0000000000000C4068EEFFFFFFFFFF3F0000000000000C40
+18|B|14|15|1|1|3.5|2.3|3.5|4|0102000000020000000000000000000C4066666666666602400000000000000C400000000000001040
+ NOTICE: PROCESSING:
+ NOTICE: pgr_createTopology('edge_table',0.0001,'the_geom','id','source','target','true')
+ NOTICE: Performing checks, please wait .....
+ NOTICE: Creating Topology, Please wait...
+ NOTICE: -------------> TOPOLOGY CREATED FOR 6 edges
+ NOTICE: Rows with NULL geometry or NULL id: 0
+ NOTICE: Vertices table for table public.edge_table is: public.edge_table_vertices_pgr
+ NOTICE: ----------------------------------------------
+OK
+1|B|10|11|1|1|2|0|2|1|010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2|TF|11|17|-1|1|2|1|3|1|0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3|TF|17|7|-1|1|3|1|4|1|0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4|B|11|3|1|1|2|1|2|2|0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5|FT|17|1|1|-1|3|1|3|2|0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6|B|12|13|1|1|0|2|1|2|01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7|B|13|3|1|1|1|2|2|2|010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8|B|3|1|1|1|2|2|3|2|0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9|B|1|2|1|1|3|2|4|2|0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10|B|3|4|1|1|2|2|2|3|0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11|FT|1|16|1|-1|3|2|3|3|0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12|FT|4|16|1|-1|2|3|3|3|0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13|FT|16|6|1|-1|3|3|4|3|0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14|B|4|5|1|1|2|3|2|4|0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15|B|2|6|1|1|4|2|4|3|0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16|B|7|2|1|1|4|1|4|2|0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+17|B|8|9|1|1|0.5|3.5|1.999999999999|3.5|010200000002000000000000000000E03F0000000000000C4068EEFFFFFFFFFF3F0000000000000C40
+18|B|14|15|1|1|3.5|2.3|3.5|4|0102000000020000000000000000000C4066666666666602400000000000000C400000000000001040
+ NOTICE: PROCESSING:
+ NOTICE: pgr_createTopology('edge_table',0.0001,'the_geom','id','source','target','dir='B'')
+ NOTICE: Performing checks, please wait .....
+ NOTICE: Creating Topology, Please wait...
+ NOTICE: -------------> TOPOLOGY CREATED FOR 12 edges
+ NOTICE: Rows with NULL geometry or NULL id: 0
+ NOTICE: Vertices table for table public.edge_table is: public.edge_table_vertices_pgr
+ NOTICE: ----------------------------------------------
+OK
+1|B|10|11|1|1|2|0|2|1|010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2|TF|11|17|-1|1|2|1|3|1|0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3|TF|17|7|-1|1|3|1|4|1|0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4|B|11|3|1|1|2|1|2|2|0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5|FT|17|1|1|-1|3|1|3|2|0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6|B|12|13|1|1|0|2|1|2|01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7|B|13|3|1|1|1|2|2|2|010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8|B|3|1|1|1|2|2|3|2|0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9|B|1|2|1|1|3|2|4|2|0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10|B|3|4|1|1|2|2|2|3|0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11|FT|1|16|1|-1|3|2|3|3|0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12|FT|4|16|1|-1|2|3|3|3|0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13|FT|16|6|1|-1|3|3|4|3|0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14|B|4|5|1|1|2|3|2|4|0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15|B|2|6|1|1|4|2|4|3|0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16|B|7|2|1|1|4|1|4|2|0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+17|B|8|9|1|1|0.5|3.5|1.999999999999|3.5|010200000002000000000000000000E03F0000000000000C4068EEFFFFFFFFFF3F0000000000000C40
+18|B|14|15|1|1|3.5|2.3|3.5|4|0102000000020000000000000000000C4066666666666602400000000000000C400000000000001040
diff --git a/doc/test/sampledata.test b/src/common/test/incrementalCreateTopology_any_01.test.sql
similarity index 56%
rename from doc/test/sampledata.test
rename to src/common/test/incrementalCreateTopology_any_01.test.sql
index a5e899c..77fa245 100644
--- a/doc/test/sampledata.test
+++ b/src/common/test/incrementalCreateTopology_any_01.test.sql
@@ -1,10 +1,6 @@
-
-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------
--- SAMPLE DATA
-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------
-
+set client_min_messages to warning;
+drop table if exists edge_table;
+drop table if exists edge_table_vertices_pgr ;
CREATE TABLE edge_table (
id serial,
dir character varying,
@@ -19,6 +15,8 @@ CREATE TABLE edge_table (
the_geom geometry
);
+set client_min_messages to warning;
+
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,0, 2,1);
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES (-1, 1, 2,1, 3,1);
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES (-1, 1, 3,1, 4,1);
@@ -27,6 +25,19 @@ INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,1, 3,
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 0,2, 1,2);
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 1,2, 2,2);
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,2, 3,2);
+
+UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
+ dir = CASE WHEN (cost>0 and reverse_cost>0) THEN 'B' -- both ways
+ WHEN (cost>0 and reverse_cost<0) THEN 'FT' -- direction of the LINESSTRING
+ WHEN (cost<0 and reverse_cost>0) THEN 'TF' -- reverse direction of the LINESTRING
+ ELSE '' END; -- unknown
+
+set client_min_messages to notice;
+select count(*) from edge_table;
+select * from edge_table order by id;
+select * from pgr_createTopology('edge_table',0.0001);
+
+set client_min_messages to warning;
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 3,2, 4,2);
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,2, 2,3);
INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,2, 3,3);
@@ -44,14 +55,21 @@ UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
WHEN (cost<0 and reverse_cost>0) THEN 'TF' -- reverse direction of the LINESTRING
ELSE '' END; -- unknown
-select pgr_createTopology('edge_table',0.001);
+set client_min_messages to notice;
+select count(*) from edge_table;
+select * from edge_table order by id;
+select count(*) from public.edge_table WHERE (the_geom IS NOT NULL AND id IS NOT NULL)=false AND (true) and (source is null and target is null);
-CREATE TABLE vertex_table (
- id serial,
- x double precision,
- y double precision
-);
+-- 10 edges must be updated the rest is untouched
+select * from pgr_createTopology('edge_table',0.0001,clean:=false);
+select * from edge_table order by id;
+-- 12 edges have 'B' the rest is wiped
+select * from pgr_createTopology('edge_table',0.0001,rows_where:='dir=''B''',clean:=true);
+select * from edge_table order by id;
+-- 6 edges must be processed, the rest is untouched
+select * from pgr_createTopology('edge_table',0.0001,clean:=false);
+select * from edge_table order by id;
-INSERT INTO vertex_table VALUES
- (1,2,0), (2,2,1), (3,3,1), (4,4,1), (5,0,2), (6,1,2), (7,2,2),
- (8,3,2), (9,4,2), (10,2,3), (11,3,3), (12,4,3), (13,2,4);
+--12 edges have 'B' the rest is untouched
+select * from pgr_createTopology('edge_table',0.0001,rows_where:='dir=''B''',clean:=false);
+select * from edge_table order by id;
diff --git a/src/common/test/isColumnInTable-any.result b/src/common/test/isColumnInTable-any.result
new file mode 100644
index 0000000..26a00c1
--- /dev/null
+++ b/src/common/test/isColumnInTable-any.result
@@ -0,0 +1,56 @@
+1|t
+2|t
+3|t
+4|t
+5|t
+6|t
+7|t
+8|t
+9|t
+10|t
+11|t
+12|t
+13|t
+14|t
+15|t
+16|t
+17|t
+18|t
+19|t
+20|t
+21|t
+22|t
+23|t
+24|t
+25|t
+26|t
+27|t
+28|t
+29|t
+30|t
+31|t
+32|t
+33|t
+34|t
+35|t
+36|t
+37|t
+38|t
+39|t
+40|t
+41|t
+42|t
+43|t
+44|t
+45|t
+46|t
+47|t
+48|t
+49|t
+50|t
+51|t
+52|t
+53|t
+54|t
+55|t
+56|t
diff --git a/src/common/test/isColumnInTable-any.test.sql b/src/common/test/isColumnInTable-any.test.sql
new file mode 100644
index 0000000..3e34e14
--- /dev/null
+++ b/src/common/test/isColumnInTable-any.test.sql
@@ -0,0 +1,103 @@
+set client_min_messages to warning;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop schema if exists s2 cascade;
+drop schema if exists "S2" cascade;
+drop schema if exists s3 cascade;
+
+create schema s1;
+create schema s2;
+create schema "S2";
+create schema s3;
+create table streets (id serial PRIMARY KEY,source integer,target integer);
+create table "Streets" (ID serial PRIMARY KEY,SOURCE integer,TARGET integer);
+create table s1.streets ("ID" serial PRIMARY KEY,sour integer,targ integer);
+create table s1."Streets" ("ID" serial PRIMARY KEY,"SOURCE" integer,"Target" integer);
+create table s2."Streets" (id serial ,source integer,target integer);
+create table "S2".streets (id serial ,source integer,target integer);
+create table s3."Streets" (id serial ,source integer,target integer);
+create table s3."sTreets" (id serial ,source integer,target integer);
+create table s3."StrEets" (id serial ,source integer,target integer);
+
+set client_min_messages to warning;
+
+
+select 1, _pgr_isColumnInTable('streets','id') = true;
+select 2, _pgr_isColumnInTable('streets','source') = true;
+select 3, _pgr_isColumnInTable('streets','target') = true;
+select 4, _pgr_isColumnInTable('streets','ID') = true;
+select 5, _pgr_isColumnInTable('streets','Source') = true;
+select 6, _pgr_isColumnInTable('streets','Target') = true;
+select 7, _pgr_isColumnInTable('Streets','id') = true;
+select 8, _pgr_isColumnInTable('Streets','source') = true;
+select 9, _pgr_isColumnInTable('Streets','target') = true;
+select 10, _pgr_isColumnInTable('Streets','ID') = true;
+select 11, _pgr_isColumnInTable('Streets','SOURCE') = true;
+select 12, _pgr_isColumnInTable('Streets','Target') = true;
+select 13, _pgr_isColumnInTable('s1.streets','ID') = true;
+select 14, _pgr_isColumnInTable('s1.streets','Targ') = true;
+select 15, _pgr_isColumnInTable('s1.Streets','ID') = true;
+select 16, _pgr_isColumnInTable('s1.Streets','SOURCE') = true;
+select 17, _pgr_isColumnInTable('s1.Streets','Target') = true;
+
+
+select 18, _pgr_isColumnInTable('streets','Targ') = false;
+select 19, _pgr_isColumnInTable('Streets','Targ') = false;
+select 20, _pgr_isColumnInTable('s1.STREETS','id') = false;
+select 21, _pgr_isColumnInTable('s1.STREETS','source') = false;
+select 22, _pgr_isColumnInTable('s1.stReets','target') = false;
+select 23, _pgr_isColumnInTable('s1.streets','SOURCE') = false;
+select 24, _pgr_isColumnInTable('s1.streets','Target') = false;
+select 25, _pgr_isColumnInTable('s1.Streets','id') = false;
+select 26, _pgr_isColumnInTable('s1.Streets','source') = false;
+select 27, _pgr_isColumnInTable('s1.Streets','target') = false;
+select 28, _pgr_isColumnInTable('s1.Streets','Targ') = false;
+
+
+SET search_path TO s1,public;
+
+select 29, _pgr_isColumnInTable('streets','ID') = true;
+select 30, _pgr_isColumnInTable('streets','Targ') = true;
+select 31, _pgr_isColumnInTable('Streets','ID') = true;
+select 32, _pgr_isColumnInTable('Streets','SOURCE') = true;
+select 33, _pgr_isColumnInTable('Streets','Target') = true;
+select 34, _pgr_isColumnInTable('s1.streets','ID') = true;
+select 35, _pgr_isColumnInTable('s1.streets','Targ') = true;
+select 36, _pgr_isColumnInTable('s1.Streets','ID') = true;
+select 37, _pgr_isColumnInTable('s1.Streets','SOURCE') = true;
+select 38, _pgr_isColumnInTable('s1.Streets','Target') = true;
+
+
+select 39, _pgr_isColumnInTable('streets','id') = false;
+select 40, _pgr_isColumnInTable('streets','source') = false;
+select 41, _pgr_isColumnInTable('streets','target') = false;
+select 42, _pgr_isColumnInTable('streets','Source') = false;
+select 43, _pgr_isColumnInTable('streets','Target') = false;
+select 44, _pgr_isColumnInTable('Streets','id') = false;
+select 45, _pgr_isColumnInTable('Streets','source') = false;
+select 46, _pgr_isColumnInTable('Streets','target') = false;
+select 47, _pgr_isColumnInTable('Streets','Targ') = false;
+select 48, _pgr_isColumnInTable('s1.STREETS','id') = false;
+select 49, _pgr_isColumnInTable('s1.STREETS','source') = false;
+select 50, _pgr_isColumnInTable('s1.stReets','target') = false;
+select 51, _pgr_isColumnInTable('s1.streets','SOURCE') = false;
+select 52, _pgr_isColumnInTable('s1.streets','Target') = false;
+select 53, _pgr_isColumnInTable('s1.Streets','id') = false;
+select 54, _pgr_isColumnInTable('s1.Streets','source') = false;
+select 55, _pgr_isColumnInTable('s1.Streets','target') = false;
+select 56, _pgr_isColumnInTable('s1.Streets','Targ') = false;
+
+set client_min_messages to warning;
+
+SET search_path TO public, "$user";
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop schema if exists s2 cascade;
+drop schema if exists "S2" cascade;
+drop schema if exists s3 cascade;
+
+
diff --git a/src/common/test/isColumnIndexed-any.result b/src/common/test/isColumnIndexed-any.result
new file mode 100644
index 0000000..9edf057
--- /dev/null
+++ b/src/common/test/isColumnIndexed-any.result
@@ -0,0 +1,56 @@
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
+t
diff --git a/src/common/test/isColumnIndexed-any.test.sql b/src/common/test/isColumnIndexed-any.test.sql
new file mode 100644
index 0000000..8e9287a
--- /dev/null
+++ b/src/common/test/isColumnIndexed-any.test.sql
@@ -0,0 +1,103 @@
+set client_min_messages to warning;
+
+SET search_path TO "$user", public;
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop schema if exists s2 cascade;
+drop schema if exists "S2" cascade;
+drop schema if exists s3 cascade;
+
+create schema s1;
+create schema s2;
+create schema "S2";
+create schema s3;
+create table streets (id serial PRIMARY KEY,source integer,target integer);
+create table "Streets" (ID serial PRIMARY KEY,SOURCE integer,TARGET integer);
+create table s1.streets ("ID" serial PRIMARY KEY,sour integer,targ integer);
+create table s1."Streets" ("ID" serial PRIMARY KEY,"SOURCE" integer,"Target" integer);
+create table s2."Streets" (id serial ,source integer,target integer);
+create table "S2".streets (id serial ,source integer,target integer);
+create table s3."Streets" (id serial ,source integer,target integer);
+create table s3."sTreets" (id serial ,source integer,target integer);
+create table s3."StrEets" (id serial ,source integer,target integer);
+
+set client_min_messages to warning;
+
+
+
+select _pgr_isColumnIndexed('streets','id') = true;
+select _pgr_isColumnIndexed('streets','ID') = true;
+select _pgr_isColumnIndexed('Streets','id') = true;
+select _pgr_isColumnIndexed('Streets','ID') = true;
+select _pgr_isColumnIndexed('s1.streets','ID') = true;
+select _pgr_isColumnIndexed('s1.Streets','ID') = true;
+
+select _pgr_isColumnIndexed('streets','source') = false;
+select _pgr_isColumnIndexed('streets','target') = false;
+select _pgr_isColumnIndexed('streets','Source') = false;
+select _pgr_isColumnIndexed('streets','Target') = false;
+select _pgr_isColumnIndexed('streets','Targ') = false;
+select _pgr_isColumnIndexed('Streets','source') = false;
+select _pgr_isColumnIndexed('Streets','target') = false;
+select _pgr_isColumnIndexed('Streets','SOURCE') = false;
+select _pgr_isColumnIndexed('Streets','Target') = false;
+select _pgr_isColumnIndexed('Streets','Targ') = false;
+select _pgr_isColumnIndexed('s1.STREETS','id') = false;
+select _pgr_isColumnIndexed('s1.STREETS','source') = false;
+select _pgr_isColumnIndexed('s1.stReets','target') = false;
+select _pgr_isColumnIndexed('s1.streets','SOURCE') = false;
+select _pgr_isColumnIndexed('s1.streets','Target') = false;
+select _pgr_isColumnIndexed('s1.streets','Targ') = false;
+select _pgr_isColumnIndexed('s1.Streets','id') = false;
+select _pgr_isColumnIndexed('s1.Streets','source') = false;
+select _pgr_isColumnIndexed('s1.Streets','target') = false;
+select _pgr_isColumnIndexed('s1.Streets','SOURCE') = false;
+select _pgr_isColumnIndexed('s1.Streets','Target') = false;
+select _pgr_isColumnIndexed('s1.Streets','Targ') = false;
+
+
+SET search_path TO s1,public;
+
+select _pgr_isColumnIndexed('streets','ID') = true;
+select _pgr_isColumnIndexed('Streets','ID') = true;
+select _pgr_isColumnIndexed('s1.streets','ID') = true;
+select _pgr_isColumnIndexed('s1.Streets','ID') = true;
+
+select _pgr_isColumnIndexed('streets','id') = false;
+select _pgr_isColumnIndexed('streets','source') = false;
+select _pgr_isColumnIndexed('streets','target') = false;
+select _pgr_isColumnIndexed('streets','Source') = false;
+select _pgr_isColumnIndexed('streets','Target') = false;
+select _pgr_isColumnIndexed('streets','Targ') = false;
+select _pgr_isColumnIndexed('Streets','id') = false;
+select _pgr_isColumnIndexed('Streets','source') = false;
+select _pgr_isColumnIndexed('Streets','target') = false;
+select _pgr_isColumnIndexed('Streets','SOURCE') = false;
+select _pgr_isColumnIndexed('Streets','Target') = false;
+select _pgr_isColumnIndexed('Streets','Targ') = false;
+select _pgr_isColumnIndexed('s1.STREETS','id') = false;
+select _pgr_isColumnIndexed('s1.STREETS','source') = false;
+select _pgr_isColumnIndexed('s1.stReets','target') = false;
+select _pgr_isColumnIndexed('s1.streets','SOURCE') = false;
+select _pgr_isColumnIndexed('s1.streets','Target') = false;
+select _pgr_isColumnIndexed('s1.streets','Targ') = false;
+select _pgr_isColumnIndexed('s1.Streets','id') = false;
+select _pgr_isColumnIndexed('s1.Streets','source') = false;
+select _pgr_isColumnIndexed('s1.Streets','target') = false;
+select _pgr_isColumnIndexed('s1.Streets','SOURCE') = false;
+select _pgr_isColumnIndexed('s1.Streets','Target') = false;
+select _pgr_isColumnIndexed('s1.Streets','Targ') = false;
+
+set client_min_messages to warning;
+
+SET search_path TO "$user", public;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop schema if exists s2 cascade;
+drop schema if exists "S2" cascade;
+drop schema if exists s3 cascade;
+
+
diff --git a/src/common/test/makeTests.sh b/src/common/test/makeTests.sh
index 306f72e..3e0c9cd 100644
--- a/src/common/test/makeTests.sh
+++ b/src/common/test/makeTests.sh
@@ -34,4 +34,16 @@ sed s/psql:routweb-any-01.test:[0-9]*:// <routweb-any-01.aaa >routweb-any-01.res
psql -U postgres -h localhost -A -t -q -f topoweb-any-01.test pgr_test &> topoweb-any-01.aaa
sed s/psql:topoweb-any-01.test:[0-9]*:// <topoweb-any-01.aaa >topoweb-any-01.rest
+psql -U postgres -h localhost -A -t -q -f pgr_getColumnName_any_01.test pgr_test &> pgr_getColumnName_any_01.test.aaa
+sed s/psql:pgr_getColumnName_any_01.test:[0-9]*:// <pgr_getColumnName_any_01.test.aaa >pgr_getColumnName_any_01.rest
+
+psql -U postgres -h localhost -A -t -q -f pgr_getColumnType_any_01.test pgr_test &> pgr_getColumnType_any_01.aaa
+sed s/psql:pgr_getColumnType_any_01.test:[0-9]*:// <pgr_getColumnType_any_01.aaa >pgr_getColumnType_any_01.rest
+
+psql -U postgres -h localhost -A -t -q -f pgr_checkVertTab_any_01.test pgr_test &> pgr_checkVertTab_any_01.aaa
+sed s/psql:pgr_checkVertTab_any_01.test:[0-9]*:// <pgr_checkVertTab_any_01.aaa >pgr_checkVertTab_any_01.rest
+
+psql -U postgres -h localhost -A -t -q -f incrementalCreateTopology_any_01.test pgr_test &> incrementalCreateTopology_any_01.aaa
+sed s/psql:incrementalCreateTopology_any_01.test:[0-9]*:// <incrementalCreateTopology_any_01.aaa >incrementalCreateTopology_any_01.rest
+
rm *.aaa
diff --git a/src/common/test/no_underscored-2x.result b/src/common/test/no_underscored-2x.result
new file mode 100644
index 0000000..718f67e
--- /dev/null
+++ b/src/common/test/no_underscored-2x.result
@@ -0,0 +1,36 @@
+ NOTICE: pgr_getTableName: This function will no longer be soported
+1|t
+ NOTICE: pgr_getTableName: This function will no longer be soported
+2|t
+ NOTICE: pgr_getColumnName: This function will no longer be soported
+3|t
+ NOTICE: pgr_getColumnName: This function will no longer be soported
+4|t
+ NOTICE: pgr_getColumnName: This function will no longer be soported
+5|t
+ NOTICE: pgr_getColumnName: This function will no longer be soported
+6|t
+ NOTICE: pgr_isColumnInTable: This function will no longer be soported
+7|t
+ NOTICE: pgr_isColumnInTable: This function will no longer be soported
+8|f
+ NOTICE: pgr_isColumnInTable: This function will no longer be soported
+9|f
+ NOTICE: pgr_isColumnInTable: This function will no longer be soported
+10|f
+ NOTICE: pgr_isColumnIndexed: This function will no longer be soported
+11|t
+ NOTICE: pgr_isColumnIndexed: This function will no longer be soported
+12|f
+ NOTICE: pgr_versionless: This function will no longer be soported
+13|t
+ NOTICE: pgr_versionless: This function will no longer be soported
+14|t
+ NOTICE: pgr_versionless: This function will no longer be soported
+15|t
+ NOTICE: pgr_isColumnInTable: This function will no longer be soported
+16|t
+ NOTICE: pgr_startPoint: This function will no longer be soported
+17|t
+ NOTICE: pgr_endPoint: This function will no longer be soported
+18|t
diff --git a/src/common/test/no_underscored-2x.test.sql b/src/common/test/no_underscored-2x.test.sql
new file mode 100644
index 0000000..0dbbef0
--- /dev/null
+++ b/src/common/test/no_underscored-2x.test.sql
@@ -0,0 +1,28 @@
+
+set client_min_messages to notice;
+select 1, sname = 'public' and tname = 'edges2' from pgr_getTableName('EDGes2');
+select 2, sname = 'public' and tname is null from pgr_getTableName('EDes2');
+
+select 3, pgr_getColumnName('EDGes2', 'SOuRce') = 'source';
+select 4, pgr_getColumnName('EDes2', 'SOuRce') is null;
+select 5, pgr_getColumnName('EDes2', 'SOuce') is null;
+select 6, pgr_getColumnName('EDes2', 'SOuce') is null;
+
+select 7, pgr_isColumnInTable('EDGes2', 'SOuRce') = true;
+select 8, pgr_isColumnInTable('EDes2', 'SOuRce');
+select 9, pgr_isColumnInTable('EDes2', 'SOuce');
+select 10, pgr_isColumnInTable('EDes2', 'SOuce');
+
+select 11, pgr_isColumnIndexed('EDGes2', 'eid') = true;
+select 12, pgr_isColumnIndexed('EDGes2', 'X1');
+
+select 13, pgr_versionless('2.1.0foobar23', '2.1') = true;
+select 14, pgr_versionless('2.1.0foobar23', '2.1-rc1') = true;
+select 15, pgr_versionless('2.1.0foobar23', '2.1-beta') = true;
+
+select 16, pgr_quote_ident('idname.text') = 'idname.text';
+
+select 17, pgr_startPoint(the_geom) = '010100000000000000000000400000000000000000' from edges2 where eid = 1;
+select 18, pgr_endPoint(the_geom) = '01010000000000000000000040000000000000F03F' from edges2 where eid = 1;
+
+
diff --git a/src/common/test/pgr_checkVertTab_any_01.result b/src/common/test/pgr_checkVertTab_any_01.result
new file mode 100644
index 0000000..9a3ce0a
--- /dev/null
+++ b/src/common/test/pgr_checkVertTab_any_01.result
@@ -0,0 +1,13 @@
+test #1:OK
+test #2:OK
+test #3:OK
+test #4:OK
+test #5:OK
+test #6:OK
+test #7:OK
+test #8:OK
+test #9:OK
+
+
+test #10:OK
+test #11:OK
diff --git a/src/common/test/pgr_checkVertTab_any_01.test.sql b/src/common/test/pgr_checkVertTab_any_01.test.sql
new file mode 100644
index 0000000..4e55a7b
--- /dev/null
+++ b/src/common/test/pgr_checkVertTab_any_01.test.sql
@@ -0,0 +1,96 @@
+
+set client_min_messages to warning;
+SET search_path TO "$user", public;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop function if exists make_tests_return_text(text,text,int);
+
+
+create schema s1;
+create table streets (id serial PRIMARY KEY,source integer,target integer);
+create table "Streets" (GID serial PRIMARY KEY,SOURCE integer,TARGET integer);
+create table s1.streets ("ID" serial PRIMARY KEY,sour integer,targ integer);
+create table s1."Streets" ("ID" serial PRIMARY KEY,"SOURCE" integer,"Target" integer);
+
+create or replace function make_tests_return_tab(query text,result text,testnumber int default 0)
+RETURNS text AS
+$BODY$
+DECLARE
+ returnvalue text;
+ naming record;
+ err boolean;
+BEGIN
+ if (result is null) then result='NULL'; end if;
+ execute query into naming;
+ returnvalue=naming.sname||'.'||naming.vname;
+ if (returnvalue is null) then returnvalue='NULL'; end if;
+ if (returnvalue=result) then
+ return 'test #'|| testnumber || ':OK';
+ else
+ return 'test #'|| testnumber || ':got '||returnvalue;
+ end if;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE ;
+
+create or replace function make_tests_return_text(query text,result text,testnumber int default 0)
+RETURNS text AS
+$BODY$
+DECLARE
+ returnvalue text;
+ naming record;
+ err boolean;
+BEGIN
+ if (result is null) then result='NULL'; end if;
+ execute query into returnvalue;
+ if (returnvalue is null) then returnvalue='NULL'; end if;
+ if (returnvalue=result) then
+ return 'test #'|| testnumber || ':OK';
+ else
+ return 'test #'|| testnumber || ':got '||returnvalue;
+ end if;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE ;
+
+create or replace function make_tests_return_text(query text,result boolean,testnumber int default 0)
+RETURNS text AS
+$BODY$
+DECLARE
+ returnvalue boolean;
+ naming record;
+ err boolean;
+BEGIN
+ if (result is null) then result='NULL'; end if;
+ execute query into returnvalue;
+ if (returnvalue is null) then returnvalue='NULL'; end if;
+
+ if (returnvalue=result) then
+ return 'test #'|| testnumber || ':OK';
+ else
+ return 'test #'|| testnumber || ':got '||returnvalue;
+ end if;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE ;
+
+
+set client_min_messages to notice;
+
+select * from make_tests_return_text('select * from _pgr_isColumnInTable (''streets'',''id'')', true,1);
+select * from make_tests_return_text('select * from _pgr_isColumnInTable (''streets'',''cnt'')', false,2);
+select * from make_tests_return_text('select * from _pgr_isColumnInTable (''streets'',''chk'')', false,3);
+select * from make_tests_return_tab('select * from _pgr_checkVertTab(''streets'', ''{"id","cnt","chk"}''::text[])','public.streets',4);
+select * from make_tests_return_text('select * from _pgr_isColumnInTable (''streets'',''cnt'')', true,5);
+select * from make_tests_return_text('select * from _pgr_isColumnInTable (''streets'',''cnt'')', true,6);
+select * from make_tests_return_text('select * from _pgr_isColumnInTable (''streets'',''chk'')', true,7);
+
+select * from make_tests_return_text('select * from _pgr_isColumnIndexed (''streets'',''cnt'')', false,8);
+select * from make_tests_return_text('select * from _pgr_isColumnIndexed (''streets'',''chk'')', false,9);
+select * from _pgr_createIndex ('streets','chk','foo');
+select * from _pgr_createIndex ('streets','cnt','btree');
+select * from make_tests_return_text('select * from _pgr_isColumnIndexed (''streets'',''cnt'')', true,10);
+select * from make_tests_return_text('select * from _pgr_isColumnIndexed (''streets'',''chk'')', true,11);
+
diff --git a/src/common/test/pgr_getColumnName_any_01.result b/src/common/test/pgr_getColumnName_any_01.result
new file mode 100644
index 0000000..fa34a14
--- /dev/null
+++ b/src/common/test/pgr_getColumnName_any_01.result
@@ -0,0 +1,32 @@
+test #1:OK
+test #2:OK
+test #3:OK
+test #4:OK
+test #5:OK
+test #6:OK
+test #7:OK
+test #8:OK
+test #9:OK
+test #10:OK
+test #11:OK
+test #12:OK
+test #13:OK
+test #14:OK
+test #15:OK
+test #16:OK
+test #17:OK
+test #18:OK
+test #19:OK
+test #20:OK
+test #21:OK
+test #22:OK
+test #23:OK
+test #24:OK
+test #25:OK
+test #26:OK
+test #27:OK
+test #28:OK
+test #29:OK
+test #30:OK
+test #31:OK
+test #32:OK
diff --git a/src/common/test/pgr_getColumnName_any_01.test.sql b/src/common/test/pgr_getColumnName_any_01.test.sql
new file mode 100644
index 0000000..0e37ebe
--- /dev/null
+++ b/src/common/test/pgr_getColumnName_any_01.test.sql
@@ -0,0 +1,87 @@
+
+set client_min_messages to warning;
+SET search_path TO "$user", public;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop function if exists make_tests_return_text(text,text,int);
+
+
+create schema s1;
+create table streets (id serial PRIMARY KEY,source integer,target integer);
+create table "Streets" (GID serial PRIMARY KEY,SOURCE integer,TARGET integer);
+create table s1.streets ("ID" serial PRIMARY KEY,sour integer,targ integer);
+create table s1."Streets" ("ID" serial PRIMARY KEY,"SOURCE" integer,"Target" integer);
+
+create or replace function make_tests_return_text(query text,result text,testnumber int default 0)
+RETURNS text AS
+$BODY$
+DECLARE
+ returnvalue text;
+ naming record;
+ err boolean;
+BEGIN
+ if (result is null) then result='NULL'; end if;
+ execute query into returnvalue;
+ if (returnvalue is null) then returnvalue='NULL'; end if;
+ if (returnvalue=result) then
+ return 'test #'|| testnumber || ':OK';
+ else
+ return 'test #'|| testnumber || ':got '||returnvalue;
+ end if;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE ;
+set client_min_messages to warning;
+select * from make_tests_return_text('select * from _pgr_getColumnName (''streets'',''id'')', 'id',1);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''streets'',''ID'')', 'id',2);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''Streets'',''gid'')', 'gid',3);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''Streets'',''GID'')', 'gid',4);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''Streets'',''ID'')', NULL,5);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1.streets'',''ID'')', 'ID',6);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1.streets'',''id'')', NULL,7);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1.Streets'',''id'')', NULL,8);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1.Streets'',''ID'')', 'ID',9);
+
+SET search_path TO s1,public;
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public.streets'',''ID'')', 'id',10);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public.Streets'',''GID'')', 'gid',11);
+
+select * from make_tests_return_text('select * from _pgr_getColumnName (''streets'',''ID'')', 'ID',12);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''streets'',''id'')', NULL,13);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''Streets'',''id'')', NULL,14);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''Streets'',''ID'')', 'ID',15);
+
+SET search_path TO "$user", public;
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''streets'',''id'')', 'id',16);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''streets'',''ID'')', 'id',17);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''Streets'',''gid'')', 'gid',18);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''Streets'',''GID'')', 'gid',19);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''Streets'',''ID'')', NULL,20);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''streets'',''ID'')', 'ID',21);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''streets'',''id'')', NULL,22);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''Streets'',''id'')', NULL,23);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''Streets'',''ID'')', 'ID',24);
+
+SET search_path TO s1,public;
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''streets'',''ID'')', 'id',25);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''Streets'',''GID'')', 'gid',26);
+
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''streets'',''ID'')', 'ID',27);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''streets'',''id'')', NULL,28);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''Streets'',''id'')', NULL,29);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''s1'',''Streets'',''ID'')', 'ID',30);
+
+-- becuase this dont test for schema or table names the expected results are NULL
+select * from make_tests_return_text('select * from _pgr_getColumnName (''publIc'',''Streets'',''gid'')', NULL,31);
+select * from make_tests_return_text('select * from _pgr_getColumnName (''public'',''StrEets'',''gid'')', NULL,32);
+
+set client_min_messages to warning;
+
+SET search_path TO "$user", public;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop function make_tests_return_text(text,text,int);
diff --git a/src/common/test/pgr_getColumnType_any_01.result b/src/common/test/pgr_getColumnType_any_01.result
new file mode 100644
index 0000000..56ba077
--- /dev/null
+++ b/src/common/test/pgr_getColumnType_any_01.result
@@ -0,0 +1,21 @@
+test #1:OK
+test #2:OK
+test #3:OK
+test #4:OK
+test #5:OK
+test #6:OK
+test #7:OK
+test #8:OK
+test #9:OK
+test #10:OK
+test #11:OK
+test #12:OK
+test #13:OK
+test #14:OK
+test #12:OK
+test #15:OK
+test #16:OK
+test #17:OK
+test #18:OK
+test #19:OK
+test #20:OK
diff --git a/src/common/test/pgr_getColumnType_any_01.test.sql b/src/common/test/pgr_getColumnType_any_01.test.sql
new file mode 100644
index 0000000..856f5a3
--- /dev/null
+++ b/src/common/test/pgr_getColumnType_any_01.test.sql
@@ -0,0 +1,76 @@
+
+set client_min_messages to warning;
+SET search_path TO "$user", public;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop function if exists make_tests_return_text(text,text,int);
+
+
+create schema s1;
+create table streets (id serial PRIMARY KEY,source double precision,target real);
+create table "Streets" (GID bigserial PRIMARY KEY,SOURCE text,TARGET integer);
+create table s1.streets ("ID" serial PRIMARY KEY,sour double precision,targ real);
+create table s1."Streets" ("ID" serial PRIMARY KEY,"SOURCE" integer,"Target" integer);
+
+create or replace function make_tests_return_text(query text,result text,testnumber int default 0)
+RETURNS text AS
+$BODY$
+DECLARE
+ returnvalue text;
+ naming record;
+ err boolean;
+BEGIN
+ if (result is null) then result='NULL'; end if;
+ execute query into returnvalue;
+ if (returnvalue is null) then returnvalue='NULL'; end if;
+ if (returnvalue=result) then
+ return 'test #'|| testnumber || ':OK';
+ else
+ return 'test #'|| testnumber || ':got '||returnvalue;
+ end if;
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE ;
+set client_min_messages to notice;
+select * from make_tests_return_text('select * from _pgr_getColumnType (''streets'',''id'')', 'integer', 1);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''streets'',''source'')', 'double precision', 2);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''streets'',''target'')', 'real', 3);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''Streets'',''GID'')', 'bigint', 4);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''Streets'',''SOURCE'')', 'text', 5);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''Streets'',''TARGET'')', 'integer', 6);
+
+select * from make_tests_return_text('select * from _pgr_getColumnType (''s1.streets'',''ID'')', 'integer', 7);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''s1.streets'',''sour'')', 'double precision', 8);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''s1.streets'',''targ'')', 'real', 9);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''s1.Streets'',''ID'')', 'integer', 10);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''s1.Streets'',''SOURCE'')','integer', 11);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''s1.Streets'',''Target'')','integer', 12);
+
+SET search_path TO s1,public;
+select * from make_tests_return_text('select * from _pgr_getColumnType (''public.streets'',''ID'')', 'integer',13);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''public.Streets'',''GID'')', 'bigint',14);
+
+select * from make_tests_return_text('select * from _pgr_getColumnType (''streets'',''ID'')', 'integer', 12);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''Streets'',''ID'')', 'integer', 15);
+
+SET search_path TO "$user", public;
+--NULL when table or column doesnt exist
+select * from make_tests_return_text('select * from _pgr_getColumnType (''Streets'',''data'',0)', NULL, 16);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''strats'',''id'',0)', NULL, 17);
+
+-- becuase this dont test for schema or table names the expected results are NULL
+select * from make_tests_return_text('select * from _pgr_getColumnType (''publIc'',''Streets'',''gid'')', NULL, 18);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''public'',''StrEets'',''gid'')', NULL, 19);
+select * from make_tests_return_text('select * from _pgr_getColumnType (''public'',''Streets'',''data'')', NULL, 20);
+
+set client_min_messages to warning;
+
+SET search_path TO "$user", public;
+
+drop table if exists streets;
+drop table if exists "Streets";
+drop schema if exists s1 cascade;
+drop function make_tests_return_text(text,text,int);
+
diff --git a/src/common/test/pgrouting_conversion_tools-any-01.result b/src/common/test/pgrouting_conversion_tools-any-01.result
new file mode 100644
index 0000000..e3abd77
--- /dev/null
+++ b/src/common/test/pgrouting_conversion_tools-any-01.result
@@ -0,0 +1,25 @@
+---- pgr_pointtoedgenode ----
+1
+6
+---- pgr_flipedges ----
+LINESTRING(2 1,2 2)
+LINESTRING(2 2,2 3)
+LINESTRING(2 3,2 2)
+LINESTRING(2 2,3 2)
+LINESTRING(3 2,4 2)
+LINESTRING(4 2,4 1)
+LINESTRING(4 1,3 1)
+LINESTRING(3 1,2 1)
+LINESTRING(2 1,2 0)
+LINESTRING(2 0,2 1)
+---- pgr_texttopoints ----
+POINT(0 0)
+POINT(1 1)
+POINT(1 0)
+POINT(0 1)
+POINT(1 4)
+POINT(1 5)
+POINT(0 4)
+POINT(0 5)
+---- pgr_pointstovids ----
+{1,2,3,5,4,9,10,6}
diff --git a/src/common/test/pgrouting_conversion_tools-any-01.test.sql b/src/common/test/pgrouting_conversion_tools-any-01.test.sql
new file mode 100644
index 0000000..0efa189
--- /dev/null
+++ b/src/common/test/pgrouting_conversion_tools-any-01.test.sql
@@ -0,0 +1,23 @@
+\echo '---- pgr_pointtoedgenode ----'
+select pgr_pointtoedgenode('edge_table', 'POINT(2 0)'::geometry, 0.02);
+select pgr_pointtoedgenode('edge_table', 'POINT(3 2)'::geometry, 0.02);
+
+\echo '---- pgr_flipedges ----'
+select st_astext(e) from (select unnest(pgr_flipedges(ARRAY[
+'LINESTRING(2 1,2 2)'::geometry,
+'LINESTRING(2 2,2 3)'::geometry,
+'LINESTRING(2 2,2 3)'::geometry,
+'LINESTRING(2 2,3 2)'::geometry,
+'LINESTRING(3 2,4 2)'::geometry,
+'LINESTRING(4 1,4 2)'::geometry,
+'LINESTRING(3 1,4 1)'::geometry,
+'LINESTRING(2 1,3 1)'::geometry,
+'LINESTRING(2 0,2 1)'::geometry,
+'LINESTRING(2 0,2 1)'::geometry]::geometry[])) as e) as foo;
+
+\echo '---- pgr_texttopoints ----'
+select st_astext(g) from (select unnest(pgr_texttopoints('0,0;1,1;1,0;0,1;1,4;1,5;0,4;0,5', 0)) as g) as foo;
+
+\echo '---- pgr_pointstovids ----'
+select * from pgr_pointstovids(pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0), 'edge_table');
+
diff --git a/src/common/test/pgrouting_dmatrix_tools-any-01.result b/src/common/test/pgrouting_dmatrix_tools-any-01.result
new file mode 100644
index 0000000..0be4fc4
--- /dev/null
+++ b/src/common/test/pgrouting_dmatrix_tools-any-01.result
@@ -0,0 +1,11 @@
+---- pgr_pointstodmatrix ----
+{{0,1,1.4142135623731,2,2.23606797749979,2.82842712474619,3,2.23606797749979},{1,0,1,1,2,2.23606797749979,2,1.4142135623731},{1.4142135623731,1,0,1.4142135623731,1,1.4142135623731,2.23606797749979,1},{2,1,1.4142135623731,0,2.23606797749979,2,1,1},{2.23606797749979,2,1,2.23606797749979,0,1,2.82842712474619,1.4142135623731},{2.82842712474619,2.23606797749979,1.4142135623731,2,1,0,2.23606797749979,1},{3,2,2.23606797749979,1,2.82842712474619,2.23606797749979,0,1.4142135623731},{2.23606797749 [...]
+---- pgr_vidstodmatrix ----
+0|1
+1|3
+2|7
+3|5
+4|4
+5|2
+6|6
+7|0
diff --git a/src/common/test/pgrouting_dmatrix_tools-any-01.test.sql b/src/common/test/pgrouting_dmatrix_tools-any-01.test.sql
new file mode 100644
index 0000000..e0009f7
--- /dev/null
+++ b/src/common/test/pgrouting_dmatrix_tools-any-01.test.sql
@@ -0,0 +1,16 @@
+\echo '---- pgr_pointstodmatrix ----'
+select * from pgr_pointstodmatrix(pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0));
+
+\echo '---- pgr_vidstodmatrix ----'
+select * from pgr_tsp(
+ (select dmatrix::float8[]
+ from pgr_vidstodmatrix(
+ pgr_pointstovids(
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0),
+ 'edge_table'),
+ pgr_texttopoints('2,0;2,1;3,1;2,2;4,1;4,2;2,3;3,2', 0),
+ 'edge_table')
+ ),
+ 1
+);
+
diff --git a/src/common/test/test.conf b/src/common/test/test.conf
index 93ff2d5..c38fdd3 100644
--- a/src/common/test/test.conf
+++ b/src/common/test/test.conf
@@ -3,19 +3,35 @@
%main::tests = (
'any' => {
'comment' => 'pgr_createTopology, pgr_analyzegraph, and pgr_analyzeOneway tests for any versions.',
- 'data' => ['common-any-00.data', 'common-any-01.data'],
- 'tests' => [qw( versionless-any-01 common-any-01 common-any-02
+ 'data' => ['common-any-00.data', 'common-any-01.data', 'common-any-02.data'],
+ 'tests' => [qw(
+versionless-any-01 common-any-01 common-any-02
common-any-03
common-any-04
+
common-any-05
createTopology-any-01
createVerticesTable-any-01
gettablename-any-01
+pgrouting_conversion_tools-any-01
+
+pgrouting_dmatrix_tools-any-01
+pgr_getColumnName_any_01
+pgr_getColumnType_any_01
+pgr_checkVertTab_any_01
+no_underscored-2x
+isColumnIndexed-any
+isColumnInTable-any
+)],
+
+ 'dummyStorage' => [qw(
+incrementalCreateTopology_any_01
)]
+
},
-# 'vpg-vpgis' => {}, # for version specific tests
-# '8-1' => {}, # for pg 8.x and postgis 1.x
-# '9.2-2.1' => {}, # for pg 9.2 and postgis 2.1
+# 'vpg-vpgis' => {}, # for version specific tests
+# '8-1' => {}, # for pg 8.x and postgis 1.x
+# '9.2-2.1' => {}, # for pg 9.2 and postgis 2.1
);
1;
diff --git a/src/common/test/versionless-any-01.rest b/src/common/test/versionless-any-01.result
similarity index 100%
rename from src/common/test/versionless-any-01.rest
rename to src/common/test/versionless-any-01.result
diff --git a/src/common/test/versionless-any-01.test b/src/common/test/versionless-any-01.test
deleted file mode 100644
index e280e3e..0000000
--- a/src/common/test/versionless-any-01.test
+++ /dev/null
@@ -1,63 +0,0 @@
--- these should all be true
-select pgr_versionless('2.1.0foobar23', '2.1');
-select pgr_versionless('2.1.0foobar23', '2.1-rc1');
-select pgr_versionless('2.1.0foobar23', '2.1-beta');
-select pgr_versionless('2.1.0foobar23', '2.1-alpha');
-select pgr_versionless('2.1.0foobar23', '2.1-dev');
-select pgr_versionless('2.1.0foobar23', '2.1rc1');
-select pgr_versionless('2.1.0foobar23', '2.1beta');
-select pgr_versionless('2.1.0foobar23', '2.1alpha');
-select pgr_versionless('2.1.0foobar23', '2.1dev');
-select pgr_versionless('2.1.0-dev', '2.1');
-select pgr_versionless('2.1.0-dev', '2.1-rc1');
-select pgr_versionless('2.1.0-dev', '2.1-beta');
-select pgr_versionless('2.1.0-dev', '2.1-alpha');
-select pgr_versionless('2.1.0-dev', '2.1rc1');
-select pgr_versionless('2.1.0-dev', '2.1beta');
-select pgr_versionless('2.1.0-dev', '2.1alpha');
-select pgr_versionless('2.1.0-alpha', '2.1');
-select pgr_versionless('2.1.0-alpha', '2.1-rc1');
-select pgr_versionless('2.1.0-alpha', '2.1-beta');
-select pgr_versionless('2.1.0-alpha', '2.1rc1');
-select pgr_versionless('2.1.0-alpha', '2.1beta');
-select pgr_versionless('2.1.0-beta', '2.1');
-select pgr_versionless('2.1.0-beta', '2.1-rc1');
-select pgr_versionless('2.1.0-beta', '2.1rc1');
-select pgr_versionless('2.0.0', '2.1');
-select pgr_versionless('2.1', '2.1.3');
-select pgr_versionless('1.05', '2.0.0');
-select pgr_versionless('1.05', '2.0');
-select pgr_versionless('1.05', '2');
--- these should all be false
-select pgr_versionless('2.1', '2.1.0foobar23');
-select pgr_versionless('2.1-rc1', '2.1.0foobar23');
-select pgr_versionless('2.1-beta', '2.1.0foobar23');
-select pgr_versionless('2.1-alpha', '2.1.0foobar23');
-select pgr_versionless('2.1-dev', '2.1.0foobar23');
-select pgr_versionless('2.1rc1', '2.1.0foobar23');
-select pgr_versionless('2.1beta', '2.1.0foobar23');
-select pgr_versionless('2.1alpha', '2.1.0foobar23');
-select pgr_versionless('2.1dev', '2.1.0foobar23');
-select pgr_versionless('2.1', '2.1.0-dev');
-select pgr_versionless('2.1-rc1', '2.1.0-dev');
-select pgr_versionless('2.1-beta', '2.1.0-dev');
-select pgr_versionless('2.1-alpha', '2.1.0-dev');
-select pgr_versionless('2.1rc1', '2.1.0-dev');
-select pgr_versionless('2.1beta', '2.1.0-dev');
-select pgr_versionless('2.1alpha', '2.1.0-dev');
-select pgr_versionless('2.1', '2.1.0-alpha');
-select pgr_versionless('2.1-rc1', '2.1.0-alpha');
-select pgr_versionless('2.1-beta', '2.1.0-alpha');
-select pgr_versionless('2.1rc1', '2.1.0-alpha');
-select pgr_versionless('2.1beta', '2.1.0-alpha');
-select pgr_versionless('2.1', '2.1.0-beta');
-select pgr_versionless('2.1-rc1', '2.1.0-beta');
-select pgr_versionless('2.1rc1', '2.1.0-beta');
-select pgr_versionless('2.1', '2.0.0');
-select pgr_versionless('2.1.3', '2.1');
-select pgr_versionless('2.0.0', '1.05');
-select pgr_versionless('2.0', '1.05');
-select pgr_versionless('2', '1.05');
-select pgr_versionless('2', '2.0.0foobar');
-select pgr_versionless('2.1', '2.1.0');
-select pgr_versionless('2.1.0beta3dev', '2.1.0beta1dev');
diff --git a/src/common/test/versionless-any-01.test.sql b/src/common/test/versionless-any-01.test.sql
new file mode 100644
index 0000000..fce5de1
--- /dev/null
+++ b/src/common/test/versionless-any-01.test.sql
@@ -0,0 +1,63 @@
+-- these should all be true
+select _pgr_versionless('2.1.0foobar23', '2.1');
+select _pgr_versionless('2.1.0foobar23', '2.1-rc1');
+select _pgr_versionless('2.1.0foobar23', '2.1-beta');
+select _pgr_versionless('2.1.0foobar23', '2.1-alpha');
+select _pgr_versionless('2.1.0foobar23', '2.1-dev');
+select _pgr_versionless('2.1.0foobar23', '2.1rc1');
+select _pgr_versionless('2.1.0foobar23', '2.1beta');
+select _pgr_versionless('2.1.0foobar23', '2.1alpha');
+select _pgr_versionless('2.1.0foobar23', '2.1dev');
+select _pgr_versionless('2.1.0-dev', '2.1');
+select _pgr_versionless('2.1.0-dev', '2.1-rc1');
+select _pgr_versionless('2.1.0-dev', '2.1-beta');
+select _pgr_versionless('2.1.0-dev', '2.1-alpha');
+select _pgr_versionless('2.1.0-dev', '2.1rc1');
+select _pgr_versionless('2.1.0-dev', '2.1beta');
+select _pgr_versionless('2.1.0-dev', '2.1alpha');
+select _pgr_versionless('2.1.0-alpha', '2.1');
+select _pgr_versionless('2.1.0-alpha', '2.1-rc1');
+select _pgr_versionless('2.1.0-alpha', '2.1-beta');
+select _pgr_versionless('2.1.0-alpha', '2.1rc1');
+select _pgr_versionless('2.1.0-alpha', '2.1beta');
+select _pgr_versionless('2.1.0-beta', '2.1');
+select _pgr_versionless('2.1.0-beta', '2.1-rc1');
+select _pgr_versionless('2.1.0-beta', '2.1rc1');
+select _pgr_versionless('2.0.0', '2.1');
+select _pgr_versionless('2.1', '2.1.3');
+select _pgr_versionless('1.05', '2.0.0');
+select _pgr_versionless('1.05', '2.0');
+select _pgr_versionless('1.05', '2');
+-- these should all be false
+select _pgr_versionless('2.1', '2.1.0foobar23');
+select _pgr_versionless('2.1-rc1', '2.1.0foobar23');
+select _pgr_versionless('2.1-beta', '2.1.0foobar23');
+select _pgr_versionless('2.1-alpha', '2.1.0foobar23');
+select _pgr_versionless('2.1-dev', '2.1.0foobar23');
+select _pgr_versionless('2.1rc1', '2.1.0foobar23');
+select _pgr_versionless('2.1beta', '2.1.0foobar23');
+select _pgr_versionless('2.1alpha', '2.1.0foobar23');
+select _pgr_versionless('2.1dev', '2.1.0foobar23');
+select _pgr_versionless('2.1', '2.1.0-dev');
+select _pgr_versionless('2.1-rc1', '2.1.0-dev');
+select _pgr_versionless('2.1-beta', '2.1.0-dev');
+select _pgr_versionless('2.1-alpha', '2.1.0-dev');
+select _pgr_versionless('2.1rc1', '2.1.0-dev');
+select _pgr_versionless('2.1beta', '2.1.0-dev');
+select _pgr_versionless('2.1alpha', '2.1.0-dev');
+select _pgr_versionless('2.1', '2.1.0-alpha');
+select _pgr_versionless('2.1-rc1', '2.1.0-alpha');
+select _pgr_versionless('2.1-beta', '2.1.0-alpha');
+select _pgr_versionless('2.1rc1', '2.1.0-alpha');
+select _pgr_versionless('2.1beta', '2.1.0-alpha');
+select _pgr_versionless('2.1', '2.1.0-beta');
+select _pgr_versionless('2.1-rc1', '2.1.0-beta');
+select _pgr_versionless('2.1rc1', '2.1.0-beta');
+select _pgr_versionless('2.1', '2.0.0');
+select _pgr_versionless('2.1.3', '2.1');
+select _pgr_versionless('2.0.0', '1.05');
+select _pgr_versionless('2.0', '1.05');
+select _pgr_versionless('2', '1.05');
+select _pgr_versionless('2', '2.0.0foobar');
+select _pgr_versionless('2.1', '2.1.0');
+select _pgr_versionless('2.1.0beta3dev', '2.1.0beta1dev');
diff --git a/src/common/tester/Makefile b/src/common/tester/Makefile
new file mode 100644
index 0000000..81cf807
--- /dev/null
+++ b/src/common/tester/Makefile
@@ -0,0 +1,21 @@
+CC=cc
+CPP=c++
+
+all: clean test1 test2 test clean2
+
+test1: test1.c ../src/pgr_logger.h
+ $(CC) -o test1 test1.c
+
+test2: test2.cpp ../src/pgr_logger.h
+ $(CPP) -o test2 test2.cpp
+
+test: clean
+ +./test1
+ +./test2
+ +cat test-log.log
+
+clean:
+ +rm -f test1 test2 test-log.log
+
+clean2:
+ +rm -f test1 test2 test-log.log
diff --git a/src/common/tester/test1.c b/src/common/tester/test1.c
new file mode 100644
index 0000000..30d49cc
--- /dev/null
+++ b/src/common/tester/test1.c
@@ -0,0 +1,16 @@
+
+#define PGR_LOGGER_ON
+#define PGR_LOGGER_LOC
+#define PGR_LOGGER_FILE "test-log.log"
+
+#include "../src/pgr_logger.h"
+
+#include <time.h>
+
+int main () {
+ PGR_LOG("message 1");
+ PGR_LOGF("%s at epoch %d\n", "message 2", (int)time(NULL));
+ PGR_LOG("message 3");
+
+ return 0;
+}
diff --git a/src/common/tester/test2.cpp b/src/common/tester/test2.cpp
new file mode 100644
index 0000000..30d49cc
--- /dev/null
+++ b/src/common/tester/test2.cpp
@@ -0,0 +1,16 @@
+
+#define PGR_LOGGER_ON
+#define PGR_LOGGER_LOC
+#define PGR_LOGGER_FILE "test-log.log"
+
+#include "../src/pgr_logger.h"
+
+#include <time.h>
+
+int main () {
+ PGR_LOG("message 1");
+ PGR_LOGF("%s at epoch %d\n", "message 2", (int)time(NULL));
+ PGR_LOG("message 3");
+
+ return 0;
+}
diff --git a/src/dijkstra/doc/index.rst b/src/dijkstra/doc/dijkstra_v2.rst
similarity index 56%
copy from src/dijkstra/doc/index.rst
copy to src/dijkstra/doc/dijkstra_v2.rst
index e05eca7..205fa25 100644
--- a/src/dijkstra/doc/index.rst
+++ b/src/dijkstra/doc/dijkstra_v2.rst
@@ -7,21 +7,20 @@
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
-.. _pgr_dijkstra:
+.. _pgr_dijkstra_v2:
-pgr_dijkstra - Shortest Path Dijkstra
+pgr_dijkstra (V 2.0)- Shortest Path Dijkstra
===============================================================================
-.. index::
- single: pgr_dijkstra(text,integer,integer,boolean,boolean)
- module: dijkstra
-
Name
-------------------------------------------------------------------------------
``pgr_dijkstra`` — Returns the shortest path using Dijkstra algorithm.
+.. index::
+ single: dijkstra(sql, source, target, directed, has_rcost) -- deprecated
+
Synopsis
-------------------------------------------------------------------------------
@@ -32,6 +31,12 @@ Dijkstra's algorithm, conceived by Dutch computer scientist Edsger Dijkstra in 1
pgr_costResult[] pgr_dijkstra(text sql, integer source, integer target,
boolean directed, boolean has_rcost);
+.. warning:: This signature is being deprecated in version 2.1, Please use it
+ without the ``has_rcost`` flag instead:
+
+ ``pgr_dijkstra(sql, source, target, directed)``
+
+ See :ref:`pgr_dijkstra_v3`
Description
-------------------------------------------------------------------------------
@@ -67,49 +72,86 @@ Returns set of :ref:`type_cost_result`:
* Renamed in version 2.0.0
-Examples
+Examples: Directed
-------------------------------------------------------------------------------
* Without ``reverse_cost``
.. code-block:: sql
- SELECT seq, id1 AS node, id2 AS edge, cost
- FROM pgr_dijkstra(
- 'SELECT id, source, target, cost FROM edge_table',
- 7, 12, false, false
- );
+ SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2,3, true, false
+ );
- seq | node | edge | cost
- -----+------+------+------
- 0 | 7 | 8 | 1
- 1 | 8 | 9 | 1
- 2 | 9 | 15 | 1
- 3 | 12 | -1 | 0
- (4 rows)
+ seq | node | edge | cost
+ -----+------+------+------
+ (0 rows)
* With ``reverse_cost``
.. code-block:: sql
- SELECT seq, id1 AS node, id2 AS edge, cost
- FROM pgr_dijkstra(
- 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
- 7, 12, true, true
- );
+ SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2,3, true, true
+ );
+ seq | node | edge | cost
+ -----+------+------+------
+ 0 | 2 | 4 | 1
+ 1 | 5 | 8 | 1
+ 2 | 6 | 9 | 1
+ 3 | 9 | 16 | 1
+ 4 | 4 | 3 | 1
+ 5 | 3 | -1 | 0
+ (6 rows)
- seq | node | edge | cost
- -----+------+------+------
- 0 | 7 | 8 | 1
- 1 | 8 | 9 | 1
- 2 | 9 | 15 | 1
- 3 | 12 | -1 | 0
- (4 rows)
-The queries use the :ref:`sampledata` network.
+
+Examples: Undirected
+-------------------------------------------------------------------------------
+
+* Without ``reverse_cost``
+
+.. code-block:: sql
+
+ SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, false, false
+ );
+ seq | node | edge | cost
+ -----+------+------+------
+ 0 | 2 | 4 | 1
+ 1 | 5 | 8 | 1
+ 2 | 6 | 5 | 1
+ 3 | 3 | -1 | 0
+ (4 rows)
+
+
+* With ``reverse_cost``
+
+.. code-block:: sql
+
+ SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3, false, true
+ );
+ seq | node | edge | cost
+ -----+------+------+------
+ 0 | 2 | 2 | 1
+ 1 | 3 | -1 | 0
+ (2 rows)
+
+
+The queries use the :ref:`sampledata` network.
+
See Also
-------------------------------------------------------------------------------
diff --git a/src/dijkstra/doc/dijkstra_v3.rst b/src/dijkstra/doc/dijkstra_v3.rst
new file mode 100644
index 0000000..8a5659e
--- /dev/null
+++ b/src/dijkstra/doc/dijkstra_v3.rst
@@ -0,0 +1,811 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_dijkstra_v3:
+
+pgr_dijkstra - Shortest Path Dijkstra
+===============================================================================
+
+``pgr_dijkstra`` — Returns the shortest path(s) using Dijkstra algorithm.
+In particular, the Dijkstra algorithm implemented by Boost.Graph.
+
+.. figure:: ../../../doc/src/introduction/images/boost-inside.jpeg
+ :target: http://www.boost.org/libs/graph
+
+ Boost Graph Inside
+
+
+Synopsis
+-------------------------------------------------------------------------------
+
+Dijkstra's algorithm, conceived by Dutch computer scientist Edsger Dijkstra in 1956.
+It is a graph search algorithm that solves the shortest path problem for
+a graph with non-negative edge path costs, producing a shortest path from
+a starting vertex (``start_vid``) to an ending vertex (``end_vid``).
+This implementation can be used with a directed graph and an undirected graph.
+
+Signatures
+===============================================================================
+
+.. index::
+ single: dijkstra(edges_sql, start_vid, end_vid)
+
+.. rubric:: Minimal signature
+
+The minimal signature is for a **directed** graph from one ``start_vid`` to one ``end_vid``:
+
+.. code-block:: sql
+
+ pgr_dijkstra(text edges_sql, bigint start_vid, bigint end_vid)
+ RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost) or EMPTY SET
+
+
+
+
+.. index::
+ single: dijkstra(edges_sql, start_vid, end_vid, directed)
+
+.. rubric:: Dijkstra 1 to 1
+
+
+This signature performs a Dijkstra from one ``start_vid`` to one ``end_vid``:
+ - on a **directed** graph when ``directed`` flag is missing or is set to ``true``.
+ - on an **undirected** graph when ``directed`` flag is set to ``false``.
+
+.. code-block:: sql
+
+ pgr_dijkstra(text edges_sql, bigint start_vid, bigint end_vid,
+ boolean directed:=true);
+ RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost) or EMPTY SET
+
+
+
+
+.. index::
+ single: dijkstra(edges_sql, start_vids, end_vid, directed)
+
+.. rubric:: Dijkstra many to 1:
+
+.. code-block:: sql
+
+ pgr_dijkstra(text edges_sql, array[ANY_INTEGER] start_vids, bigint end_vid,
+ boolean directed:=true);
+ RETURNS SET OF (seq, path_seq, start_vid, node, edge, cost, agg_cost) or EMPTY SET
+
+This signature performs a Dijkstra from each ``start_vid`` in ``start_vids`` to one ``end_vid``:
+ - on a **directed** graph when ``directed`` flag is missing or is set to ``true``.
+ - on an **undirected** graph when ``directed`` flag is set to ``false``.
+
+Using this signature, will load once the graph and perform several one to one Dijkstra
+where the ending vertex is fixed.
+The result is the union of the results of the one to one dijkstra.
+
+The extra ``start_vid`` in the result is used to distinguish to which path it belongs.
+
+
+
+
+
+.. index::
+ single: dijkstra(edges_sql, start_vid, end_vids, directed)
+
+.. rubric:: Dijkstra 1 to many:
+
+.. code-block:: sql
+
+ pgr_dijkstra(text edges_sql, bigint start_vid, array[ANY_INTEGER] end_vids,
+ boolean directed:=true);
+ RETURNS SET OF (seq, path_seq, end_vid, node, edge, cost, agg_cost) or EMPTY SET
+
+This signature performs a Dijkstra from one ``start_vid`` to each ``end_vid`` in ``end_vids``:
+ - on a **directed** graph when ``directed`` flag is missing or is set to ``true``.
+ - on an **undirected** graph when ``directed`` flag is set to ``false``.
+
+Using this signature, will load once the graph and perform several 1 to 1 Dijkstra
+where the starting vertex is fixed.
+The result is the union of the results of the one to one dijkstra.
+
+The extra ``end_vid`` in the result is used to distinguish to which path it belongs.
+
+
+
+.. index::
+ single: dijkstra(edges_sql, start_vids, end_vids, directed)
+
+.. rubric:: Dijkstra many to many:
+
+.. code-block:: sql
+
+ pgr_dijkstra(text edges_sql, array[ANY_INTEGER] start_vids, array[ANY_INTEGER] end_vids,
+ boolean directed:=true);
+ RETURNS SET OF (seq, path_seq, start_vid, end_vid, node, edge, cost, agg_cost) or EMPTY SET
+
+This signature performs a Dijkstra from each ``start_vid`` in ``start_vids`` to each ``end_vid`` in ``end_vids``:
+ - on a **directed** graph when ``directed`` flag is missing or is set to ``true``.
+ - on an **undirected** graph when ``directed`` flag is set to ``false``.
+
+
+Using this signature, will load once the graph and perform all combinations
+for starting vertices and ending vertices.
+
+The extra ``start_vid`` and ``end_vid`` in the result is used to distinguish to which path it belongs.
+
+
+Description of the Signatures
+=============================
+
+Description of the SQL query
+-------------------------------------------------------------------------------
+
+:edges_sql: an SQL query, which should return a set of rows with the following columns:
+
+ :id: ``ANY-INTEGER`` identifier of the edge.
+ :source: ``ANY-INTEGER`` identifier of the first end point vertex of the edge.
+ :target: ``ANY-INTEGER`` identifier of the second end pont vertex of the edge.
+ :cost: ``ANY-NUMERICAL`` weight of the edge `(source, target)`, if negative: edge `(source, target)` does not exist, therefore it's not part of the graph.
+ :reverse_cost: ``ANY-NUMERICAL`` (optional) weight of the edge `(target, source)`, if negative: edge `(target, source)` does not exist, therefore it's not part of the graph.
+
+Where:
+
+:ANY-INTEGER: smallint, int, bigint
+:ANY-NUMERICAL: smallint, int, bigint, real, float
+
+For example:
+
+.. code-block:: sql
+
+ SELECT id, source, target, cost, reverse_cost from edge_table where geom && ST_Expand(ST_SetSRID(ST_Point(45, 34), 4326), 0.1)
+
+
+Description of the parameters of the signatures
+-------------------------------------------------------------------------------
+
+:sql: SQL query as decribed above.
+:start_vid: ``BIGINT`` identifier of the starting vertex of the path.
+:start_vids: ``array[ANY-INTEGER]`` array of identifiers of starting vertices.
+:end_vid: ``BIGINT`` identifier of the ending vertex of the path.
+:end_vids: ``array[ANY-INTEGER]`` array of identifiers of ending vertices.
+:directed: ``boolean`` (optional). When ``false`` the graph is considered as Undirected. Default is ``true`` which considers the graph as Directed.
+
+
+Description of the return values
+-------------------------------------------------------------------------------
+
+Returns set of ``(seq [, start_vid] [, end_vid] , node, edge, cost, agg_cost)``
+
+:seq: ``INT`` isequential value starting from **1**.
+:path_seq: ``INT`` relative position in the path. Has value **1** for the begining of a path.
+:start_vid: ``BIGINT`` id of the starting vertex. Used when multiple starting vetrices are in the query.
+:end_vid: ``BIGINT`` id of the ending vertex. Used when multiple ending vertices are in the query.
+:node: ``BIGINT`` id of the node in the path from start_vid to end_v.
+:edge: ``BIGINT`` id of the edge used to go from ``node`` to the next node in the path sequence. ``-1`` for the last node of the path.
+:cost: ``FLOAT`` cost to traverse from ``node`` using ``edge`` to the next node in the path sequence.
+:agg_cost: ``FLOAT`` total cost from ``start_v`` to ``node``.
+
+
+Examples
+========
+
+The examples of this section are based on the :ref:`sampledata` network.
+
+The examples include combinations from starting vertices 2 and 11 to ending vertices 3 and 5 in a directed and
+undirected graph with and with out reverse_cost.
+
+Examples for queries marked as ``directed`` with ``cost`` and ``reverse_cost`` columns
+--------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig1`
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | 8 | 1 | 1
+ 3 | 3 | 6 | 9 | 1 | 2
+ 4 | 4 | 9 | 16 | 1 | 3
+ 5 | 5 | 4 | 3 | 1 | 4
+ 6 | 6 | 3 | -1 | 0 | 5
+ (6 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 5
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | -1 | 0 | 1
+ (2 rows)
+
+When you pass an array we get a combined result:
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3,5]
+ );
+
+ seq | path_seq | end_vid | node | edge | cost | agg_cost
+ -----+----------+---------+------+------+------+----------
+ 1 | 1 | 3 | 2 | 4 | 1 | 0
+ 2 | 2 | 3 | 5 | 8 | 1 | 1
+ 3 | 3 | 3 | 6 | 9 | 1 | 2
+ 4 | 4 | 3 | 9 | 16 | 1 | 3
+ 5 | 5 | 3 | 4 | 3 | 1 | 4
+ 6 | 6 | 3 | 3 | -1 | 0 | 5
+ 7 | 1 | 5 | 2 | 4 | 1 | 0
+ 8 | 2 | 5 | 5 | -1 | 0 | 1
+ (8 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 3
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 11 | 13 | 1 | 0
+ 2 | 2 | 12 | 15 | 1 | 1
+ 3 | 3 | 9 | 16 | 1 | 2
+ 4 | 4 | 4 | 3 | 1 | 3
+ 5 | 5 | 3 | -1 | 0 | 4
+ (5 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 5
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 11 | 13 | 1 | 0
+ 2 | 2 | 12 | 15 | 1 | 1
+ 3 | 3 | 9 | 9 | 1 | 2
+ 4 | 4 | 6 | 8 | 1 | 3
+ 5 | 5 | 5 | -1 | 0 | 4
+ (5 rows)
+
+Some other combinations.
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], 5
+ );
+
+ seq | path_seq | start_vid | node | edge | cost | agg_cost
+ -----+----------+---------+------+------+------+----------
+ 1 | 1 | 2 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 5 | -1 | 0 | 1
+ 3 | 1 | 11 | 11 | 13 | 1 | 0
+ 4 | 2 | 11 | 12 | 15 | 1 | 1
+ 5 | 3 | 11 | 9 | 9 | 1 | 2
+ 6 | 4 | 11 | 6 | 8 | 1 | 3
+ 7 | 5 | 11 | 5 | -1 | 0 | 4
+ (7 rows)
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2, 11], array[3,5]
+ );
+ seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
+ -----+----------+---------+-------+------+------+------+----------
+ 1 | 1 | 2 | 3 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 3 | 5 | 8 | 1 | 1
+ 3 | 3 | 2 | 3 | 6 | 9 | 1 | 2
+ 4 | 4 | 2 | 3 | 9 | 16 | 1 | 3
+ 5 | 5 | 2 | 3 | 4 | 3 | 1 | 4
+ 6 | 6 | 2 | 3 | 3 | -1 | 0 | 5
+ 7 | 1 | 2 | 5 | 2 | 4 | 1 | 0
+ 8 | 2 | 2 | 5 | 5 | -1 | 0 | 1
+ 9 | 1 | 11 | 3 | 11 | 13 | 1 | 0
+ 10 | 2 | 11 | 3 | 12 | 15 | 1 | 1
+ 11 | 3 | 11 | 3 | 9 | 16 | 1 | 2
+ 12 | 4 | 11 | 3 | 4 | 3 | 1 | 3
+ 13 | 5 | 11 | 3 | 3 | -1 | 0 | 4
+ 14 | 1 | 11 | 5 | 11 | 13 | 1 | 0
+ 15 | 2 | 11 | 5 | 12 | 15 | 1 | 1
+ 16 | 3 | 11 | 5 | 9 | 9 | 1 | 2
+ 17 | 4 | 11 | 5 | 6 | 8 | 1 | 3
+ 18 | 5 | 11 | 5 | 5 | -1 | 0 | 4
+ (18 rows)
+
+
+
+
+Examples for queries marked as ``undirected`` with ``cost`` and ``reverse_cost`` columns
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig2`
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 2 | 1 | 0
+ 2 | 2 | 3 | -1 | 0 | 1
+ (2 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 5,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | -1 | 0 | 1
+ (2 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 3,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 11 | 11 | 1 | 0
+ 2 | 2 | 6 | 5 | 1 | 1
+ 3 | 3 | 3 | -1 | 0 | 2
+ (3 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 5,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 11 | 11 | 1 | 0
+ 2 | 2 | 6 | 8 | 1 | 1
+ 3 | 3 | 5 | -1 | 0 | 2
+ (3 rows)
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], 5,
+ false
+ );
+ seq | path_seq | start_vid | node | edge | cost | agg_cost
+ -----+----------+---------+------+------+------+----------
+ 1 | 1 | 2 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 5 | -1 | 0 | 1
+ 3 | 1 | 11 | 11 | 11 | 1 | 0
+ 4 | 2 | 11 | 6 | 8 | 1 | 1
+ 5 | 3 | 11 | 5 | -1 | 0 | 2
+ (5 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3,5],
+ false
+ );
+ seq | path_seq | end_vid | node | edge | cost | agg_cost
+ -----+----------+-------+------+------+------+----------
+ 1 | 1 | 3 | 2 | 2 | 1 | 0
+ 2 | 2 | 3 | 3 | -1 | 0 | 1
+ 3 | 1 | 5 | 2 | 4 | 1 | 0
+ 4 | 2 | 5 | 5 | -1 | 0 | 1
+ (4 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2, 11], array[3,5],
+ false
+ );
+ seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
+ -----+----------+---------+-------+------+------+------+----------
+ 1 | 1 | 2 | 3 | 2 | 2 | 1 | 0
+ 2 | 2 | 2 | 3 | 3 | -1 | 0 | 1
+ 3 | 1 | 2 | 5 | 2 | 4 | 1 | 0
+ 4 | 2 | 2 | 5 | 5 | -1 | 0 | 1
+ 5 | 1 | 11 | 3 | 11 | 11 | 1 | 0
+ 6 | 2 | 11 | 3 | 6 | 5 | 1 | 1
+ 7 | 3 | 11 | 3 | 3 | -1 | 0 | 2
+ 8 | 1 | 11 | 5 | 11 | 11 | 1 | 0
+ 9 | 2 | 11 | 5 | 6 | 8 | 1 | 1
+ 10 | 3 | 11 | 5 | 5 | -1 | 0 | 2
+ (10 rows)
+
+
+
+Examples for queries marked as ``directed`` with ``cost`` column
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig3`
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ (0 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 5
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | -1 | 0 | 1
+ (2 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 3
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ (0 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 5
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ (0 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], 5
+ );
+ seq | path_seq | start_vid | node | edge | cost | agg_cost
+ -----+----------+---------+------+------+------+----------
+ 1 | 1 | 2 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 5 | -1 | 0 | 1
+ (2 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3,5]
+ );
+ seq | path_seq | end_vid | node | edge | cost | agg_cost
+ -----+----------+-------+------+------+------+----------
+ 1 | 1 | 5 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | 5 | -1 | 0 | 1
+ (2 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2, 11], array[3,5]
+ );
+ seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
+ -----+----------+---------+-------+------+------+------+----------
+ 1 | 1 | 2 | 5 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 5 | 5 | -1 | 0 | 1
+ (2 rows)
+
+
+
+Examples for queries marked as ``undirected`` with ``cost`` column
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig4`
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | 8 | 1 | 1
+ 3 | 3 | 6 | 5 | 1 | 2
+ 4 | 4 | 3 | -1 | 0 | 3
+ (4 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 5,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | -1 | 0 | 1
+ (2 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 3,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 11 | 11 | 1 | 0
+ 2 | 2 | 6 | 5 | 1 | 1
+ 3 | 3 | 3 | -1 | 0 | 2
+ (3 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 5,
+ false
+ );
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 11 | 11 | 1 | 0
+ 2 | 2 | 6 | 8 | 1 | 1
+ 3 | 3 | 5 | -1 | 0 | 2
+ (3 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], 5,
+ false
+ );
+ seq | path_seq | start_vid | node | edge | cost | agg_cost
+ -----+----------+---------+------+------+------+----------
+ 1 | 1 | 2 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 5 | -1 | 0 | 1
+ 3 | 1 | 11 | 11 | 11 | 1 | 0
+ 4 | 2 | 11 | 6 | 8 | 1 | 1
+ 5 | 3 | 11 | 5 | -1 | 0 | 2
+ (5 rows)
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3,5],
+ false
+ );
+ seq | path_seq | end_vid | node | edge | cost | agg_cost
+ -----+----------+-------+------+------+------+----------
+ 1 | 1 | 3 | 2 | 4 | 1 | 0
+ 2 | 2 | 3 | 5 | 8 | 1 | 1
+ 3 | 3 | 3 | 6 | 5 | 1 | 2
+ 4 | 4 | 3 | 3 | -1 | 0 | 3
+ 5 | 1 | 5 | 2 | 4 | 1 | 0
+ 6 | 2 | 5 | 5 | -1 | 0 | 1
+ (6 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2, 11], array[3,5],
+ false
+ );
+ seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
+ -----+----------+---------+-------+------+------+------+----------
+ 1 | 1 | 2 | 3 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 3 | 5 | 8 | 1 | 1
+ 3 | 3 | 2 | 3 | 6 | 5 | 1 | 2
+ 4 | 4 | 2 | 3 | 3 | -1 | 0 | 3
+ 5 | 1 | 2 | 5 | 2 | 4 | 1 | 0
+ 6 | 2 | 2 | 5 | 5 | -1 | 0 | 1
+ 7 | 1 | 11 | 3 | 11 | 11 | 1 | 0
+ 8 | 2 | 11 | 3 | 6 | 5 | 1 | 1
+ 9 | 3 | 11 | 3 | 3 | -1 | 0 | 2
+ 10 | 1 | 11 | 5 | 11 | 11 | 1 | 0
+ 11 | 2 | 11 | 5 | 6 | 8 | 1 | 1
+ 12 | 3 | 11 | 5 | 5 | -1 | 0 | 2
+ (12 rows)
+
+
+
+
+Equvalences between signatures
+------------------------------
+
+.. code-block:: sql
+
+ -- V2
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ true, -- directed flag
+ true -- has_rcost
+ );
+
+ seq | id1 | id2 | cost
+ -----+-----+-----+------
+ 0 | 2 | 4 | 1
+ 1 | 5 | 8 | 1
+ 2 | 6 | 9 | 1
+ 3 | 9 | 16 | 1
+ 4 | 4 | 3 | 1
+ 5 | 3 | -1 | 0
+ (6 rows)
+
+
+ -- V3
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ true -- directed flag
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2,3
+ );
+
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 2 | 5 | 8 | 1 | 1
+ 3 | 3 | 6 | 9 | 1 | 2
+ 4 | 4 | 9 | 16 | 1 | 3
+ 5 | 5 | 4 | 3 | 1 | 4
+ 6 | 6 | 3 | -1 | 0 | 5
+ (6 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3],
+ true
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3]
+ );
+
+ seq | path_seq | end_vid | node | edge | cost | agg_cost
+ -----+----------+-------+------+------+------+----------
+ 1 | 1 | 3 | 2 | 4 | 1 | 0
+ 2 | 2 | 3 | 5 | 8 | 1 | 1
+ 3 | 3 | 3 | 6 | 9 | 1 | 2
+ 4 | 4 | 3 | 9 | 16 | 1 | 3
+ 5 | 5 | 3 | 4 | 3 | 1 | 4
+ 6 | 6 | 3 | 3 | -1 | 0 | 5
+ (6 rows)
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3],
+ true
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3]
+ );
+ seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
+ -----+----------+---------+-------+------+------+------+----------
+ 1 | 1 | 2 | 3 | 2 | 4 | 1 | 0
+ 2 | 2 | 2 | 3 | 5 | 8 | 1 | 1
+ 3 | 3 | 2 | 3 | 6 | 9 | 1 | 2
+ 4 | 4 | 2 | 3 | 9 | 16 | 1 | 3
+ 5 | 5 | 2 | 3 | 4 | 3 | 1 | 4
+ 6 | 6 | 2 | 3 | 3 | -1 | 0 | 5
+ (6 rows)
+
+
+
+
+
+Equivalences between signatures
+-------------------------------------------------------------------------------
+
+.. code-block:: sql
+
+ -- V2
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ false, -- directed flag
+ true -- has_rcost
+ );
+
+ seq | id1 | id2 | cost
+ -----+-----+-----+------
+ 0 | 2 | 2 | 1
+ 1 | 3 | -1 | 0
+ (2 rows)
+
+
+ -- V3
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ false -- directed flag
+ );
+
+ seq | path_seq | node | edge | cost | agg_cost
+ -----+----------+------+------+------+----------
+ 1 | 1 | 2 | 2 | 1 | 0
+ 2 | 2 | 3 | -1 | 0 | 1
+ (2 rows)
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3],
+ false
+ );
+ seq | path_seq | end_vid | node | edge | cost | agg_cost
+ -----+----------+-------+------+------+------+----------
+ 1 | 1 | 3 | 2 | 2 | 1 | 0
+ 2 | 2 | 3 | 3 | -1 | 0 | 1
+ (2 rows)
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], 3,
+ false
+ );
+ seq | path_seq | start_vid | node | edge | cost | agg_cost
+ -----+----------+---------+------+------+------+----------
+ 1 | 1 | 2 | 2 | 2 | 1 | 0
+ 2 | 2 | 2 | 3 | -1 | 0 | 1
+ (2 rows)
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3],
+ false
+ );
+ seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
+ -----+----------+---------+-------+------+------+------+----------
+ 1 | 1 | 2 | 3 | 2 | 2 | 1 | 0
+ 2 | 2 | 2 | 3 | 3 | -1 | 0 | 1
+ (2 rows)
+
+
+
+The queries use the :ref:`sampledata` network.
+
+.. rubric:: History
+
+* Renamed in version 2.0.0
+* Added functionality in version 2.1.0
+
+
+See Also
+-------------------------------------------------------------------------------
+
+* http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
+
+.. rubric:: Indices and tables
+
+* :ref:`genindex`
+* :ref:`search`
+
diff --git a/src/dijkstra/doc/index.rst b/src/dijkstra/doc/index.rst
index e05eca7..e48c6f5 100644
--- a/src/dijkstra/doc/index.rst
+++ b/src/dijkstra/doc/index.rst
@@ -3,7 +3,7 @@
pgRouting Manual
Copyright(c) pgRouting Contributors
- This documentation is licensed under a Creative Commons Attribution-Share
+ This documentation is licensed under a Creative Commons Attribution-Share
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
@@ -12,106 +12,109 @@
pgr_dijkstra - Shortest Path Dijkstra
===============================================================================
-.. index::
- single: pgr_dijkstra(text,integer,integer,boolean,boolean)
- module: dijkstra
+Version 2.0 (deprecated)
+------------------------
-Name
--------------------------------------------------------------------------------
+ - :ref:`pgr_dijkstra<pgr_dijkstra_v2>` - Shortest Path Dijkstra
-``pgr_dijkstra`` — Returns the shortest path using Dijkstra algorithm.
+Version 2.1
+------------------
+ - :ref:`pgr_dijkstra<pgr_dijkstra_v3>` - Shortest Path Dijkstra
-Synopsis
--------------------------------------------------------------------------------
+The problem definition
+======================
-Dijkstra's algorithm, conceived by Dutch computer scientist Edsger Dijkstra in 1956. It is a graph search algorithm that solves the single-source shortest path problem for a graph with non-negative edge path costs, producing a shortest path tree. Returns a set of :ref:`pgr_costResult <type_cost_result>` (seq, id1, id2, cost) rows, that make up a path.
-.. code-block:: sql
+Given the following query:
- pgr_costResult[] pgr_dijkstra(text sql, integer source, integer target,
- boolean directed, boolean has_rcost);
+pgr_dijkstra(:math:`sql, start_{vid}, end_{vid}, directed`)
-Description
--------------------------------------------------------------------------------
+where :math:`sql = \{(id_i, source_i, target_i, cost_i, reverse\_cost_i)\}`
-:sql: a SQL query, which should return a set of rows with the following columns:
+and
- .. code-block:: sql
+ - :math:`source = \bigcup source_i`,
+ - :math:`target = \bigcup target_i`,
- SELECT id, source, target, cost [,reverse_cost] FROM edge_table
+The graphs are defined as follows:
+.. rubric:: Directed graph
- :id: ``int4`` identifier of the edge
- :source: ``int4`` identifier of the source vertex
- :target: ``int4`` identifier of the target vertex
- :cost: ``float8`` value, of the edge traversal cost. A negative cost will prevent the edge from being inserted in the graph.
- :reverse_cost: ``float8`` (optional) the cost for the reverse traversal of the edge. This is only used when the ``directed`` and ``has_rcost`` parameters are ``true`` (see the above remark about negative costs).
+The weighted directed graph, :math:`G_d(V,E)`, is definied by:
-:source: ``int4`` id of the start point
-:target: ``int4`` id of the end point
-:directed: ``true`` if the graph is directed
-:has_rcost: if ``true``, the ``reverse_cost`` column of the SQL generated set of rows will be used for the cost of the traversal of the edge in the opposite direction.
+* the set of vertices :math:`V`
-Returns set of :ref:`type_cost_result`:
+ - :math:`V = source \cup target \cup {start_{vid}} \cup {end_{vid}}`
-:seq: row sequence
-:id1: node ID
-:id2: edge ID (``-1`` for the last row)
-:cost: cost to traverse from ``id1`` using ``id2``
+* the set of edges :math:`E`
+ - :math:`E = \begin{cases} &\{(source_i, target_i, cost_i) \text{ when } cost >=0 \} &\quad \text{ if } reverse\_cost = \varnothing \\ \\ &\{(source_i, target_i, cost_i) \text{ when } cost >=0 \} \\ \cup &\{(target_i, source_i, reverse\_cost_i) \text{ when } reverse\_cost_i >=0)\} &\quad \text{ if } reverse\_cost \neq \varnothing \\ \end{cases}`
-.. rubric:: History
-* Renamed in version 2.0.0
+.. rubric:: Undirected graph
-Examples
--------------------------------------------------------------------------------
+The weighted undirected graph, :math:`G_u(V,E)`, is definied by:
-* Without ``reverse_cost``
+* the set of vertices :math:`V`
-.. code-block:: sql
+ - :math:`V = source \cup target \cup {start_v{vid}} \cup {end_{vid}}`
- SELECT seq, id1 AS node, id2 AS edge, cost
- FROM pgr_dijkstra(
- 'SELECT id, source, target, cost FROM edge_table',
- 7, 12, false, false
- );
- seq | node | edge | cost
- -----+------+------+------
- 0 | 7 | 8 | 1
- 1 | 8 | 9 | 1
- 2 | 9 | 15 | 1
- 3 | 12 | -1 | 0
- (4 rows)
+* the set of edges :math:`E`
+ - :math:`E = \begin{cases} &\{(source_i, target_i, cost_i) \text{ when } cost >=0 \} \\ \cup &\{(target_i, source_i, cost_i) \text{ when } cost >=0 \} &\quad \text{ if } reverse\_cost = \varnothing \\ \\ &\{(source_i, target_i, cost_i) \text{ when } cost >=0 \} \\ \cup &\{(target_i, source_i, cost_i) \text{ when } cost >=0 \} \\ \cup &\{(target_i, source_i, reverse\_cost_i) \text{ when } reverse\_cost_i >=0)\} \\ \cup &\{(source_i, target_i, reverse\_cost_i) \text{ when } reverse\_co [...]
-* With ``reverse_cost``
-.. code-block:: sql
- SELECT seq, id1 AS node, id2 AS edge, cost
- FROM pgr_dijkstra(
- 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
- 7, 12, true, true
- );
+.. rubric:: The problem
- seq | node | edge | cost
- -----+------+------+------
- 0 | 7 | 8 | 1
- 1 | 8 | 9 | 1
- 2 | 9 | 15 | 1
- 3 | 12 | -1 | 0
- (4 rows)
+Given:
-The queries use the :ref:`sampledata` network.
+ - :math:`start_{vid} \in V` a starting vertex
+ - :math:`end_{vid} \in V` an ending vertex
+ - :math:`G(V,E) = \begin{cases} G_d(V,E) &\quad \text{ if } directed = true \\ G_u(V,E) &\quad \text{ if } directed = false \\ \end{cases}`
+Then:
-See Also
--------------------------------------------------------------------------------
+.. math:: \text{pgr_dijkstra}(sql, start_{vid}, end_{vid}, directed) =
+ \begin{cases}
+ \text{shortest path } \boldsymbol{\pi} \text{ between } start_{vid} \text{and } end_{vid} &\quad \text{if } \exists \boldsymbol{\pi} \\
+ \varnothing &\quad \text{otherwise} \\
+ \end{cases}
+
+:math:`\boldsymbol{\pi} = \{(path_\seq_i, node_i, edge_i, cost_i, agg\_cost_i)\}`
+
+where:
+ - :math:`path_\seq_i = i`
+ - :math:`path_\seq_{| \pi |} = | \pi |`
+ - :math:`node_i \in V`
+ - :math:`node_1 = start_{vid}`
+ - :math:`node_{| \pi |} = end_{vid}`
+ - :math:`\forall i \neq | \pi |, \quad (node_i, node_{i+1}, cost_i) \in E`
+ - :math:`edge_i = \begin{cases} id_{(node_i, node_{i+1},cost_i)} &\quad \text{when } i \neq | \pi | \\ -1 &\quad \text{when } i = | \pi | \\ \end{cases}`
+ - :math:`cost_i = cost_{(node_i, node_{i+1})}`
+ - :math:`agg\_cost_i = \begin{cases} 0 &\quad \text{when } i = 1 \\ \displaystyle\sum_{k=1}^{i} cost_{(node_{k-1}, node_k)} &\quad \text{when } i \neq 1 \\ \end{cases}`
+
+
+
+In other words: The algorithm returns a the shortest path between :math:`start_{vid}` and :math:`end_{vid}` , if it exists, in terms of a sequence of nodes and of edges,
+ - :math:`path_\seq` indicates the relative position in the path of the :math:`node` or :math:`edge`.
+ - :math:`cost` is the cost of the edge to be used to go to the next node.
+ - :math:`agg\_cost` is the cost from the :math:`start_{vid}` up to the node.
+
+
+If there is no path, the resulting set is empty.
+
+
+
+
+
+.. toctree::
+ :hidden:
+
+ ./dijkstra_v2
+ ./dijkstra_v3
-* :ref:`type_cost_result`
-* http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
diff --git a/src/dijkstra/sql/dijkstra.sql b/src/dijkstra/sql/dijkstra.sql
index 9ca49f8..cd27154 100644
--- a/src/dijkstra/sql/dijkstra.sql
+++ b/src/dijkstra/sql/dijkstra.sql
@@ -1,29 +1,159 @@
---
--- Copyright (c) 2005 Sylvain Pasche,
--- 2006-2007 Anton A. Patrushev, Orkney, Inc.
---
--- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
---
-
-
------------------------------------------------------------------------
--- Core function for Dijkstra shortest_path computation
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION pgr_dijkstra(sql text, source_id integer,
- target_id integer, directed boolean, has_reverse_cost boolean)
- RETURNS SETOF pgr_costResult
- AS '$libdir/librouting', 'shortest_path'
- LANGUAGE c IMMUTABLE STRICT;
+/*PGR
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+
+CREATE OR REPLACE FUNCTION _pgr_dijkstra(edges_sql text, start_vid bigint, end_vid bigint, directed boolean, has_rcost boolean,
+ OUT seq integer, OUT path_seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ '$libdir/librouting-2.1', 'shortest_path'
+ LANGUAGE c IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION _pgr_dijkstra(edges_sql text, start_vid bigint, end_vids anyarray, directed boolean, has_rcost boolean,
+ OUT seq integer, OUT path_seq integer, OUT end_vid bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ '$libdir/librouting-2.1', 'dijkstra_1_to_many'
+ LANGUAGE c IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION _pgr_dijkstra(edges_sql text, start_vids anyarray, end_vids bigint, directed boolean, has_rcost boolean,
+ OUT seq integer, OUT path_seq integer, OUT start_vid bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ '$libdir/librouting-2.1', 'dijkstra_many_to_1'
+ LANGUAGE c IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION _pgr_dijkstra(edges_sql text, start_vids anyarray, end_vids anyarray, directed boolean, has_rcost boolean,
+ OUT seq integer, OUT path_seq integer, OUT start_vid bigint, OUT end_vid bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ '$libdir/librouting-2.1', 'dijkstra_many_to_many'
+ LANGUAGE c IMMUTABLE STRICT;
+
+-- V2 signature
+CREATE OR REPLACE FUNCTION pgr_dijkstra(edges_sql text, start_vid bigint, end_vid bigint, directed boolean, has_rcost boolean)
+ RETURNS SETOF pgr_costresult AS
+ $BODY$
+ DECLARE
+ has_reverse boolean;
+ BEGIN
+ -- raise notice 'This function signature will no longer be supported in V3';
+ has_reverse =_pgr_parameter_check('dijkstra', edges_sql, false);
+ if (has_reverse != has_rcost) then
+ if (has_reverse) then -- raise NOTICE 'has_rcost set to false but reverse_cost column found, Ignoring';
+ else raise EXCEPTION 'has_rcost set to true but reverse_cost not found';
+ end if;
+ end if;
+
+ return query SELECT seq-1 as seq, node::integer as id1, edge::integer as id2, cost
+ FROM _pgr_dijkstra(edges_sql, start_vid, end_vid, directed, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+
+-- V3 signature
+CREATE OR REPLACE FUNCTION pgr_dijkstra(edges_sql text, start_vid bigint, end_vid bigint,
+ OUT seq integer, OUT path_seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ -- raise notice 'This function signature belongs to V3';
+ has_rcost =_pgr_parameter_check('dijkstra', edges_sql, true);
+ return query SELECT *
+ FROM _pgr_dijkstra(edges_sql, start_vid, end_vid, true, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+
+-- V3 signature
+CREATE OR REPLACE FUNCTION pgr_dijkstra(edges_sql text, start_vid bigint, end_vid bigint, directed boolean,
+ OUT seq integer, OUT path_seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ -- raise notice 'This function signature belongs to V3';
+ has_rcost =_pgr_parameter_check('dijkstra', edges_sql, true);
+ return query SELECT *
+ FROM _pgr_dijkstra(edges_sql, start_vid, end_vid, directed, has_rcost) a;
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+-- V3 signature for 1 to many
+CREATE OR REPLACE FUNCTION pgr_dijkstra(edges_sql text, start_vid bigint, end_vids anyarray, directed boolean default true,
+ OUT seq integer, OUT path_seq integer, OUT end_vid bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ has_rcost =_pgr_parameter_check('dijkstra', edges_sql, true);
+ return query SELECT *
+ FROM _pgr_dijkstra(edges_sql, start_vid, end_vids, directed, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+
+-- V3 signature for many to 1
+CREATE OR REPLACE FUNCTION pgr_dijkstra(edges_sql text, start_vids anyarray, end_vid bigint, directed boolean default true,
+ OUT seq integer, OUT path_seq integer, OUT start_vid bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ has_rcost =_pgr_parameter_check('dijkstra', edges_sql, true);
+ return query SELECT *
+ FROM _pgr_dijkstra(edges_sql, start_vids, end_vid, directed, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+
+-- V3 signature for many to many
+CREATE OR REPLACE FUNCTION pgr_dijkstra(edges_sql text, start_vids anyarray, end_vids anyarray, directed boolean default true,
+ OUT seq integer, OUT path_seq integer, OUT start_vid bigint, OUT end_vid bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ has_rcost =_pgr_parameter_check('dijkstra', edges_sql, true);
+ return query SELECT *
+ FROM _pgr_dijkstra(edges_sql, start_vids, end_vids, directed, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
diff --git a/src/dijkstra/src/1_to_many_dijkstra.c b/src/dijkstra/src/1_to_many_dijkstra.c
new file mode 100644
index 0000000..fe6d202
--- /dev/null
+++ b/src/dijkstra/src/1_to_many_dijkstra.c
@@ -0,0 +1,198 @@
+/*pgRouting
+ *
+ * File: 1_to_many_dijstra.c
+ * Copyright (c) 2015 Celia Virginia Vergara Castillo
+ *
+ * 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.
+ *
+ */
+
+// #define DEBUG
+
+#include "postgres.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "utils/array.h"
+#include "catalog/pg_type.h"
+#if PGSQL_VERSION > 92
+#include "access/htup_details.h"
+#endif
+
+#include "fmgr.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+#include "./dijkstra_driver.h"
+
+#ifndef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+
+static int dijkstra_1_to_many_driver(
+ char* sql, int64_t start_vertex,
+ int64_t *end_vertex, int num,
+ bool directed, bool has_rcost,
+ pgr_path_element3_t **path, int *path_count) {
+ int SPIcode;
+ pgr_edge_t *edges = NULL;
+ int64_t total_tuples = 0;
+
+
+ char *err_msg = (char *)"";
+ int ret = -1;
+
+
+ SPIcode = pgr_get_data(sql, &edges, &total_tuples, has_rcost,
+ start_vertex, start_vertex);
+
+ if (SPIcode == -1) {
+ return SPIcode;
+ }
+
+ ret = do_pgr_dijkstra_1_to_many(edges, total_tuples,
+ start_vertex, end_vertex, num,
+ has_rcost, directed,
+ path, path_count, &err_msg);
+
+ if (ret < 0) {
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
+
+
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
+}
+
+
+#ifndef _MSC_VER
+Datum dijkstra_1_to_many(PG_FUNCTION_ARGS);
+#else // _MSC_VER
+PGDLLEXPORT Datum dijkstra_1_to_many(PG_FUNCTION_ARGS);
+#endif // _MSC_VER
+
+
+PG_FUNCTION_INFO_V1(dijkstra_1_to_many);
+#ifndef _MSC_VER
+Datum
+#else // _MSC_VER
+PGDLLEXPORT Datum
+#endif
+dijkstra_1_to_many(PG_FUNCTION_ARGS) {
+ FuncCallContext *funcctx;
+ int call_cntr;
+ int max_calls;
+ TupleDesc tuple_desc;
+ pgr_path_element3_t *ret_path = 0;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL()) {
+ MemoryContext oldcontext;
+ int path_count = 0;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ int64_t* targetsArr;
+ int num;
+
+ targetsArr = (int64_t*) pgr_get_bigIntArray(&num, PG_GETARG_ARRAYTYPE_P(2));
+ PGR_DBG("targetsArr size %d ", num);
+
+
+#ifdef DEBUG
+ int i;
+ for (i = 0; i < num; ++i) {
+ PGR_DBG("targetsArr[%d]=%li", i, targetsArr[i]);
+ }
+#endif
+
+ PGR_DBG("Calling dijkstra_1_to_many_driver");
+ dijkstra_1_to_many_driver(
+ pgr_text2char(PG_GETARG_TEXT_P(0)),
+ PG_GETARG_INT64(1),
+ targetsArr, num,
+ PG_GETARG_BOOL(3),
+ PG_GETARG_BOOL(4), &ret_path, &path_count);
+
+ free(targetsArr);
+
+ /* total number of tuples to be returned */
+ funcctx->max_calls = path_count;
+ funcctx->user_fctx = ret_path;
+ 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);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ call_cntr = funcctx->call_cntr;
+ max_calls = funcctx->max_calls;
+ tuple_desc = funcctx->tuple_desc;
+ ret_path = (pgr_path_element3_t*) funcctx->user_fctx;
+
+ /* do when there is more left to send */
+ if (call_cntr < max_calls) {
+ HeapTuple tuple;
+ Datum result;
+ Datum *values;
+ char* nulls;
+
+ values = palloc(7 * sizeof(Datum));
+ nulls = palloc(7 * sizeof(char));
+ // id, start_v, node, edge, cost, tot_cost
+ values[0] = Int32GetDatum(call_cntr + 1);
+ nulls[0] = ' ';
+ values[1] = Int32GetDatum(ret_path[call_cntr].seq);
+ nulls[1] = ' ';
+ values[2] = Int64GetDatum(ret_path[call_cntr].to);
+ nulls[2] = ' ';
+ values[3] = Int64GetDatum(ret_path[call_cntr].vertex);
+ nulls[3] = ' ';
+ values[4] = Int64GetDatum(ret_path[call_cntr].edge);
+ nulls[4] = ' ';
+ values[5] = Float8GetDatum(ret_path[call_cntr].cost);
+ nulls[5] = ' ';
+ values[6] = Float8GetDatum(ret_path[call_cntr].tot_cost);
+ nulls[6] = ' ';
+
+ tuple = heap_formtuple(tuple_desc, values, nulls);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ /* clean up (this is not really necessary) */
+ pfree(values);
+ pfree(nulls);
+
+ SRF_RETURN_NEXT(funcctx, result);
+ } else {
+ /* do when there is no more left */
+ if (ret_path) free(ret_path);
+ SRF_RETURN_DONE(funcctx);
+ }
+}
+
diff --git a/src/dijkstra/src/CMakeLists.txt b/src/dijkstra/src/CMakeLists.txt
index bd05f4d..17b95aa 100644
--- a/src/dijkstra/src/CMakeLists.txt
+++ b/src/dijkstra/src/CMakeLists.txt
@@ -1,13 +1,6 @@
-#SET(LIBRARY_OUTPUT_PATH ../../../lib/)
-#IF(APPLE)
-# SET(LIBRARY_MODE_TARGET "MODULE")
-#ELSE(APPLE)
-# SET(LIBRARY_MODE_TARGET "SHARED")
-#ENDIF(APPLE)
-#ADD_LIBRARY(routing ${LIBRARY_MODE_TARGET} dijkstra.c boost_wrapper.cpp)
-#INSTALL(TARGETS routing DESTINATION ${LIBRARY_INSTALL_PATH})
-#IF(APPLE)
-# SET_TARGET_PROPERTIES(routing PROPERTIES LINK_FLAGS "-bundle_loader ${POSTGRESQL_EXECUTABLE} -bundle")
-#ENDIF(APPLE)
-
-ADD_LIBRARY(dijkstra OBJECT dijkstra.c boost_wrapper.cpp)
+ADD_LIBRARY(dijkstra OBJECT
+ dijkstra.c
+ 1_to_many_dijkstra.c
+ many_to_1_dijkstra.c
+ many_to_many_dijkstra.c
+ dijkstra_driver.cpp)
diff --git a/src/dijkstra/src/boost_wrapper.cpp b/src/dijkstra/src/boost_wrapper.cpp
deleted file mode 100644
index 25a14aa..0000000
--- a/src/dijkstra/src/boost_wrapper.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Shortest path algorithm for PostgreSQL
- *
- * Copyright (c) 2005 Sylvain Pasche
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-// Include C header first for windows build issue
-#include "dijkstra.h"
-#include <cfloat>
-
-#include <boost/config.hpp>
-
-#include <boost/graph/graph_traits.hpp>
-#include <boost/graph/adjacency_list.hpp>
-#include <boost/graph/dijkstra_shortest_paths.hpp>
-
-using namespace std;
-using namespace boost;
-
-// Maximal number of nodes in the path (to avoid infinite loops)
-#define MAX_NODES 100000000
-
-struct Vertex
-{
- int id;
- float8 cost;
-};
-
-// Adds an edge to the graph.
-// Edge id, cost, source and target ids and coordinates are copied also
-template <class G, class E>
-static void
-graph_add_edge(G &graph, E &e, int id, int source, int target, float8 cost)
-{
- bool inserted;
-
- if (cost < 0) // edges are not inserted in the graph if cost is negative
- return;
-
- tie(e, inserted) = add_edge(source, target, graph);
-
- graph[e].cost = cost;
- graph[e].id = id;
-
- typedef typename graph_traits<G>::vertex_descriptor Vertex;
- Vertex s = vertex(source, graph);
- Vertex t = vertex(target, graph);
-}
-
-
-int
-boost_dijkstra(edge_t *edges, unsigned int count, int start_vertex, int end_vertex,
- bool directed, bool has_reverse_cost,
- path_element_t **path, int *path_count, char **err_msg)
-{
-try {
- // FIXME: use a template for the directedS parameters
- typedef adjacency_list < listS, vecS, directedS, no_property, Vertex> graph_t;
-
- typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
- typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
- typedef std::pair<int, int> Edge;
-
- // FIXME: compute this value
- const unsigned int num_nodes = ((directed && has_reverse_cost ? 2 : 1) * count) + 100;
-
- graph_t graph(num_nodes);
-
- // commented out to fix APPLE build, is it needed?
- //property_map<graph_t, edge_weight_t>::type weightmap = get(edge_weight, graph);
-
- for (std::size_t j = 0; j < count; ++j)
- {
- edge_descriptor e;
- graph_add_edge<graph_t, edge_descriptor>(graph, e,
- edges[j].id, edges[j].source,
- edges[j].target, edges[j].cost);
-
- if (!directed || (directed && has_reverse_cost))
- {
- float8 cost;
-
- if (has_reverse_cost)
- {
- cost = edges[j].reverse_cost;
- }
- else
- {
- cost = edges[j].cost;
- }
-
- graph_add_edge<graph_t, edge_descriptor>(graph, e,
- edges[j].id,
- edges[j].target,
- edges[j].source,
- cost);
- }
- }
-
- std::vector<vertex_descriptor> predecessors(num_vertices(graph));
-
- vertex_descriptor _source = vertex(start_vertex, graph);
-
- if ((long)_source < 0)
- {
- *err_msg = (char *) "Starting vertex not found";
- return -1;
- }
-
- vertex_descriptor _target = vertex(end_vertex, graph);
- if ((long)_target < 0)
- {
- *err_msg = (char *) "Ending vertex not found";
- return -1;
- }
-
- std::vector<float8> distances(num_vertices(graph));
- // calling Boost function
- dijkstra_shortest_paths(graph, _source,
- predecessor_map(&predecessors[0]).
- weight_map(get(&Vertex::cost, graph))
- .distance_map(&distances[0]));
-
- vector<int> path_vect;
- int max = MAX_NODES;
- path_vect.push_back(_target);
-
- while (_target != _source)
- {
- if (_target == predecessors[_target])
- {
- *err_msg = (char *) "No path found";
- return 0;
- }
- _target = predecessors[_target];
-
- path_vect.push_back(_target);
- if (!max--)
- {
- *err_msg = (char *) "Overflow";
- return -1;
- }
- }
-
- *path = (path_element_t *) malloc(sizeof(path_element_t) * (path_vect.size() + 1));
- *path_count = path_vect.size();
-
- for(int i = path_vect.size() - 1, j = 0; i >= 0; i--, j++)
- {
- graph_traits < graph_t >::vertex_descriptor v_src;
- graph_traits < graph_t >::vertex_descriptor v_targ;
- graph_traits < graph_t >::edge_descriptor e;
- graph_traits < graph_t >::out_edge_iterator out_i, out_end;
-
- (*path)[j].vertex_id = path_vect.at(i);
-
- (*path)[j].edge_id = -1;
- (*path)[j].cost = distances[_target];
-
- if (i == 0)
- {
- continue;
- }
-
- v_src = path_vect.at(i);
- v_targ = path_vect.at(i - 1);
- double cost = 99999999.9;
- int edge_id = 0;
-
- for (tie(out_i, out_end) = out_edges(v_src, graph);
- out_i != out_end; ++out_i)
- {
- graph_traits < graph_t >::vertex_descriptor v, targ;
- e = *out_i;
- v = source(e, graph);
- targ = target(e, graph);
-
- if (targ == v_targ)
- {
- // if there are multiple parallel edges get the lowest cost
- if (graph[*out_i].cost < cost)
- {
- edge_id = graph[*out_i].id;
- cost = graph[*out_i].cost;
- }
- }
- }
- (*path)[j].edge_id = edge_id;
- (*path)[j].cost = cost;
- }
-
- return EXIT_SUCCESS;
- }
- catch(...) {
- *err_msg = (char *) "Unknown exception caught!";
- return -1;
- }
-}
diff --git a/src/dijkstra/src/dijkstra.c b/src/dijkstra/src/dijkstra.c
index 3929aab..9653d99 100644
--- a/src/dijkstra/src/dijkstra.c
+++ b/src/dijkstra/src/dijkstra.c
@@ -2,6 +2,7 @@
* Shortest path algorithm for PostgreSQL
*
* Copyright (c) 2005 Sylvain Pasche
+ * 2015 Celia Virginia Vergara Castillo
*
* 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
@@ -15,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -28,312 +29,104 @@
#endif
#include "fmgr.h"
-
-#include "dijkstra.h"
-
-Datum shortest_path(PG_FUNCTION_ARGS);
-
-#undef DEBUG
-//#define DEBUG 1
-
-#ifdef DEBUG
-#define DBG(format, arg...) \
- elog(NOTICE, format , ## arg)
-#else
-#define DBG(format, arg...) do { ; } while (0)
-#endif
-
-// The number of tuples to fetch from the SPI cursor at each iteration
-#define TUPLIMIT 1000
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+#include "./dijkstra_driver.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
-static char *
-text2char(text *in)
-{
- char *out = palloc(VARSIZE(in));
-
- memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
- out[VARSIZE(in) - VARHDRSZ] = '\0';
- return out;
-}
-
-static int
-finish(int code, int ret)
-{
- code = SPI_finish();
- if (code != SPI_OK_FINISH ) {
- elog(ERROR,"couldn't disconnect from SPI");
- return -1 ;
- }
- return ret;
-}
-
-typedef struct edge_columns
-{
- int id;
- int source;
- int target;
- int cost;
- int reverse_cost;
-} edge_columns_t;
-
-static int
-fetch_edge_columns(SPITupleTable *tuptable, edge_columns_t *edge_columns,
- bool has_reverse_cost)
-{
- edge_columns->id = SPI_fnumber(SPI_tuptable->tupdesc, "id");
- edge_columns->source = SPI_fnumber(SPI_tuptable->tupdesc, "source");
- edge_columns->target = SPI_fnumber(SPI_tuptable->tupdesc, "target");
- edge_columns->cost = SPI_fnumber(SPI_tuptable->tupdesc, "cost");
- if (edge_columns->id == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->source == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->target == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->cost == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "Error, query must return columns "
- "'id', 'source', 'target' and 'cost'");
- return -1;
- }
-
- if (SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->source) != INT4OID ||
- SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->target) != INT4OID ||
- SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->cost) != FLOAT8OID) {
- elog(ERROR, "Error, columns 'source', 'target' must be of type int4, 'cost' must be of type float8");
- return -1;
- }
-
- DBG("columns: id %i source %i target %i cost %i",
- edge_columns->id, edge_columns->source,
- edge_columns->target, edge_columns->cost);
-
- if (has_reverse_cost) {
- edge_columns->reverse_cost = SPI_fnumber(SPI_tuptable->tupdesc,
- "reverse_cost");
-
- if (edge_columns->reverse_cost == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "Error, reverse_cost is used, but query did't return "
- "'reverse_cost' column");
- return -1;
- }
+Datum shortest_path(PG_FUNCTION_ARGS);
- if (SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->reverse_cost)
- != FLOAT8OID) {
- elog(ERROR, "Error, columns 'reverse_cost' must be of type float8");
- return -1;
- }
+static int compute_shortest_path(char* sql, int64_t start_vertex,
+ int64_t end_vertex, bool directed,
+ bool has_rcost,
+ pgr_path_element3_t **path, int *path_count) {
+ int SPIcode = 0;
+ pgr_edge_t *edges = NULL;
+ int64_t total_tuples = 0;
- DBG("columns: reverse_cost cost %i", edge_columns->reverse_cost);
- }
-
- return 0;
-}
-static void
-fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc,
- edge_columns_t *edge_columns, edge_t *target_edge)
-{
- Datum binval;
- bool isnull;
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->id, &isnull);
- if (isnull) elog(ERROR, "id contains a null value");
- target_edge->id = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->source, &isnull);
- if (isnull) elog(ERROR, "source contains a null value");
- target_edge->source = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->target, &isnull);
- if (isnull) elog(ERROR, "target contains a null value");
- target_edge->target = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->cost, &isnull);
- if (isnull) elog(ERROR, "cost contains a null value");
- target_edge->cost = DatumGetFloat8(binval);
-
- if (edge_columns->reverse_cost != -1) {
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->reverse_cost,
- &isnull);
- if (isnull) elog(ERROR, "reverse_cost contains a null value");
- target_edge->reverse_cost = DatumGetFloat8(binval);
- }
-}
-
-
-static int compute_shortest_path(char* sql, int start_vertex,
- int end_vertex, bool directed,
- bool has_reverse_cost,
- path_element_t **path, int *path_count)
-{
-
- int SPIcode;
- void *SPIplan;
- Portal SPIportal;
- bool moredata = TRUE;
- int ntuples;
- edge_t *edges = NULL;
- int total_tuples = 0;
- edge_columns_t edge_columns = {.id= -1, .source= -1, .target= -1,
- .cost= -1, .reverse_cost= -1};
- int v_max_id=0;
- int v_min_id=INT_MAX;
-
- int s_count = 0;
- int t_count = 0;
-
- char *err_msg;
+ char *err_msg = (char *)"";
int ret = -1;
- register int z;
-
- DBG("start shortest_path\n");
-
- SPIcode = SPI_connect();
- if (SPIcode != SPI_OK_CONNECT) {
- elog(ERROR, "shortest_path: couldn't open a connection to SPI");
- return -1;
- }
- SPIplan = SPI_prepare(sql, 0, NULL);
- if (SPIplan == NULL) {
- elog(ERROR, "shortest_path: couldn't create query plan via SPI");
- return -1;
+ if (start_vertex == end_vertex) {
+ PGR_DBG("Starting vertex and Ending Vertex are equal");
+ *path = noPathFound3(-1, path_count, (*path));
+ return 0;
}
- if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) {
- elog(ERROR, "shortest_path: SPI_cursor_open('%s') returns NULL", sql);
- return -1;
- }
+ PGR_DBG("Load data");
- while (moredata == TRUE) {
- SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
-
- if (edge_columns.id == -1) {
- if (fetch_edge_columns(SPI_tuptable, &edge_columns,
- has_reverse_cost) == -1)
- return finish(SPIcode, ret);
- }
-
- ntuples = SPI_processed;
- total_tuples += ntuples;
- if (!edges)
- edges = palloc(total_tuples * sizeof(edge_t));
- else
- edges = repalloc(edges, total_tuples * sizeof(edge_t));
-
- if (edges == NULL) {
- elog(ERROR, "Out of memory");
- return finish(SPIcode, ret);
- }
-
- if (ntuples > 0) {
- int t;
- SPITupleTable *tuptable = SPI_tuptable;
- TupleDesc tupdesc = SPI_tuptable->tupdesc;
-
- for (t = 0; t < ntuples; t++) {
- HeapTuple tuple = tuptable->vals[t];
- fetch_edge(&tuple, &tupdesc, &edge_columns,
- &edges[total_tuples - ntuples + t]);
- }
- SPI_freetuptable(tuptable);
- }
- else {
- moredata = FALSE;
- }
+ int readCode = pgr_get_data(sql, &edges, &total_tuples, has_rcost,
+ start_vertex, end_vertex);
+
+ if (readCode == -1 || total_tuples == 0) {
+ *path = noPathFound3(-1, path_count, (*path));
+ PGR_DBG("No edge tuples found");
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
}
- //defining min and max vertex id
-
- DBG("Total %i tuples", total_tuples);
-
- for(z=0; z<total_tuples; z++) {
- if(edges[z].source<v_min_id) v_min_id=edges[z].source;
- if(edges[z].source>v_max_id) v_max_id=edges[z].source;
- if(edges[z].target<v_min_id) v_min_id=edges[z].target;
- if(edges[z].target>v_max_id) v_max_id=edges[z].target;
-
- DBG("%i <-> %i", v_min_id, v_max_id);
+ if (total_tuples == 1
+ && (edges[0].cost < 0 && edges[0].reverse_cost < 0)) {
+ PGR_DBG("One edge with cost == %f and reverse_cost == %f", edges[0].cost, edges[0].reverse_cost );
+ *path = noPathFound3(-1, path_count, (*path));
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
}
- //::::::::::::::::::::::::::::::::::::
- //:: reducing vertex id (renumbering)
- //::::::::::::::::::::::::::::::::::::
- for(z=0; z<total_tuples; z++) {
- //check if edges[] contains source and target
- if(edges[z].source == start_vertex || edges[z].target == start_vertex)
- ++s_count;
- if(edges[z].source == end_vertex || edges[z].target == end_vertex)
- ++t_count;
-
- edges[z].source-=v_min_id;
- edges[z].target-=v_min_id;
- DBG("%i - %i", edges[z].source, edges[z].target);
+ if (total_tuples == 1) {
+ PGR_DBG("One edge with cost == %f and reverse_cost == %f", edges[0].cost, edges[0].reverse_cost );
+ PGR_DBG("The soruce == %ld and target == %ld", edges[0].source, edges[0].target);
+ if ((edges[0].cost >= 0 && edges[0].source != start_vertex && edges[0].target != end_vertex)
+ || (edges[0].reverse_cost >= 0 && edges[0].source != end_vertex && edges[0].target != start_vertex)) {
+ PGR_DBG("There must be a solution or empty for undirected");
+ }
+ if (edges[0].cost >= 0 && edges[0].source == start_vertex && edges[0].target == end_vertex) {
+ PGR_DBG("Solution from source to target");
+ }
+ if (edges[0].reverse_cost >= 0 && edges[0].target == start_vertex && edges[0].source == end_vertex) {
+ PGR_DBG("Solution from target to source");
+ }
}
- DBG("Total %i tuples", total_tuples);
- if(s_count == 0) {
- elog(ERROR, "Start vertex was not found.");
- return -1;
- }
-
- if(t_count == 0) {
- elog(ERROR, "Target vertex was not found.");
- return -1;
- }
-
- DBG("Calling boost_dijkstra\n");
-
- start_vertex -= v_min_id;
- end_vertex -= v_min_id;
+ PGR_DBG("Total %ld tuples in query:", total_tuples);
- ret = boost_dijkstra(edges, total_tuples, start_vertex, end_vertex,
- directed, has_reverse_cost,
- path, path_count, &err_msg);
+ ret = do_pgr_dijkstra(edges, total_tuples,
+ start_vertex, end_vertex,
+ has_rcost, directed,
+ path, path_count, &err_msg);
if (ret < 0) {
- //elog(ERROR, "Error computing path: %s", err_msg);
- ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
errmsg("Error computing path: %s", err_msg)));
- }
-
- DBG("SIZE %i\n",*path_count);
-
- //::::::::::::::::::::::::::::::::
- //:: restoring original vertex id
- //::::::::::::::::::::::::::::::::
- for(z=0;z<*path_count;z++) {
- //DBG("vetex %i\n",(*path)[z].vertex_id);
- (*path)[z].vertex_id+=v_min_id;
}
- DBG("ret = %i\n", ret);
-
- DBG("*path_count = %i\n", *path_count);
+ PGR_DBG("total records found %i\n", *path_count);
+ PGR_DBG("Exist Status = %i\n", ret);
+ PGR_DBG("Returned message = %s\n", err_msg);
- DBG("ret = %i\n", ret);
-
- return finish(SPIcode, ret);
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
}
PG_FUNCTION_INFO_V1(shortest_path);
Datum
-shortest_path(PG_FUNCTION_ARGS)
-{
+shortest_path(PG_FUNCTION_ARGS) {
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tuple_desc;
- path_element_t *path = 0;
+ pgr_path_element3_t *ret_path = 0;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int path_count = 0;
- int ret;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
@@ -342,29 +135,22 @@ shortest_path(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- ret = compute_shortest_path(text2char(PG_GETARG_TEXT_P(0)),
- PG_GETARG_INT32(1),
- PG_GETARG_INT32(2),
+ compute_shortest_path(pgr_text2char(PG_GETARG_TEXT_P(0)),
+ PG_GETARG_INT64(1),
+ PG_GETARG_INT64(2),
PG_GETARG_BOOL(3),
- PG_GETARG_BOOL(4), &path, &path_count);
-#ifdef DEBUG
- DBG("Ret is %i", ret);
- if (ret >= 0) {
- int i;
- for (i = 0; i < path_count; i++) {
- DBG("Step %i vertex_id %i ", i, path[i].vertex_id);
- DBG(" edge_id %i ", path[i].edge_id);
- DBG(" cost %f ", path[i].cost);
- }
- }
-#endif
+ PG_GETARG_BOOL(4), &ret_path, &path_count);
/* total number of tuples to be returned */
funcctx->max_calls = path_count;
- funcctx->user_fctx = path;
+ funcctx->user_fctx = ret_path;
+ 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 = BlessTupleDesc(
- RelationNameGetTupleDesc("pgr_costResult"));
+ funcctx->tuple_desc = tuple_desc;
MemoryContextSwitchTo(oldcontext);
}
@@ -375,7 +161,7 @@ shortest_path(PG_FUNCTION_ARGS)
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
tuple_desc = funcctx->tuple_desc;
- path = (path_element_t*) funcctx->user_fctx;
+ ret_path = (pgr_path_element3_t*) funcctx->user_fctx;
/* do when there is more left to send */
if (call_cntr < max_calls) {
@@ -384,18 +170,22 @@ shortest_path(PG_FUNCTION_ARGS)
Datum *values;
char* nulls;
- values = palloc(4 * sizeof(Datum));
- nulls = palloc(4 * sizeof(char));
-
- values[0] = Int32GetDatum(call_cntr);
+ values = palloc(6 * sizeof(Datum));
+ nulls = palloc(6 * sizeof(char));
+
+ values[0] = Int32GetDatum(ret_path[call_cntr].seq);
nulls[0] = ' ';
- values[1] = Int32GetDatum(path[call_cntr].vertex_id);
+ values[1] = Int32GetDatum(ret_path[call_cntr].seq);
nulls[1] = ' ';
- values[2] = Int32GetDatum(path[call_cntr].edge_id);
+ values[2] = Int64GetDatum(ret_path[call_cntr].vertex);
nulls[2] = ' ';
- values[3] = Float8GetDatum(path[call_cntr].cost);
+ values[3] = Int64GetDatum(ret_path[call_cntr].edge);
nulls[3] = ' ';
-
+ values[4] = Float8GetDatum(ret_path[call_cntr].cost);
+ nulls[4] = ' ';
+ values[5] = Float8GetDatum(ret_path[call_cntr].tot_cost);
+ nulls[5] = ' ';
+
tuple = heap_formtuple(tuple_desc, values, nulls);
/* make the tuple into a datum */
@@ -406,10 +196,9 @@ shortest_path(PG_FUNCTION_ARGS)
pfree(nulls);
SRF_RETURN_NEXT(funcctx, result);
- }
- /* do when there is no more left */
- else {
- if (path) free(path);
+ } else {
+ /* do when there is no more left */
+ if (ret_path) free(ret_path);
SRF_RETURN_DONE(funcctx);
}
}
diff --git a/src/dijkstra/src/dijkstra.h b/src/dijkstra/src/dijkstra.h
deleted file mode 100644
index ca5bea4..0000000
--- a/src/dijkstra/src/dijkstra.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Shortest path algorithm for PostgreSQL
- *
- * Copyright (c) 2005 Sylvain Pasche
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DIJKSTRA_H
-#define _DIJKSTRA_H
-
-#include "postgres.h"
-
-typedef struct edge
-{
- int id;
- int source;
- int target;
- float8 cost;
- float8 reverse_cost;
-} edge_t;
-
-typedef struct path_element
-{
- int vertex_id;
- int edge_id;
- float8 cost;
-} path_element_t;
-
-#ifdef __cplusplus
-extern "C"
-#endif
-int boost_dijkstra(edge_t *edges, unsigned int count, int start_vertex, int end_vertex,
- bool directed, bool has_reverse_cost,
- path_element_t **path, int *path_count, char **err_msg);
-
-#endif
diff --git a/src/dijkstra/src/dijkstra_driver.cpp b/src/dijkstra/src/dijkstra_driver.cpp
new file mode 100644
index 0000000..db7a200
--- /dev/null
+++ b/src/dijkstra/src/dijkstra_driver.cpp
@@ -0,0 +1,367 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+// #define DEBUG
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
+#include <sstream>
+#include <deque>
+#include <vector>
+#include "./pgr_dijkstra.hpp"
+#include "./dijkstra_driver.h"
+
+extern "C" {
+#include "postgres.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+}
+
+
+// #include "./../../common/src/pgr_types.h"
+// #include "./../../common/src/postgres_connection.h"
+
+
+int do_pgr_dijkstra_many_to_many(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t *start_vertex, int s_len, int64_t *end_vertex, int e_len,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg) {
+ try {
+ // in c code this should this must have been checked:
+ // 1) cant check anything
+ if (total_tuples == 1) {
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ *ret_path = NULL;
+ return 0;
+ }
+
+std::ostringstream log;
+ graphType gType = directedFlag? DIRECTED: UNDIRECTED;
+ const int initial_size = 1;
+
+ std::deque< Path >paths;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ Pgr_dijkstra < DirectedGraph > digraph(gType, initial_size);
+ Pgr_dijkstra < UndirectedGraph > undigraph(gType, initial_size);
+
+ std::vector< int64_t > start_vertices(start_vertex, start_vertex + s_len);
+ std::vector< int64_t > end_vertices(end_vertex, end_vertex + e_len);
+ if (directedFlag) {
+ digraph.initialize_graph(data_edges, total_tuples);
+ digraph.dijkstra(paths, start_vertices, end_vertices);
+ } else {
+ undigraph.initialize_graph(data_edges, total_tuples);
+ undigraph.dijkstra(paths, start_vertices, end_vertices);
+ }
+
+ int count(count_tuples(paths));
+
+log << "count" << count;
+ if (count == 0) {
+ *err_msg = strdup(
+ "NOTICE: No paths found between any of the starting vertices and any of the Ending vertices");
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ return 0;
+ }
+
+
+ *ret_path = pgr_get_memory3(count, (*ret_path));
+ int sequence(collapse_paths(ret_path, paths));
+
+log << "sequence" << sequence;
+
+#if 1
+ *err_msg = strdup("OK");
+#else
+ *err_msg = strdup(log.str().c_str());
+#endif
+ *path_count = sequence;
+ return EXIT_SUCCESS;
+ } catch ( ... ) {
+ *err_msg = strdup("Caught unknown expection!");
+ return -1;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int do_pgr_dijkstra_many_to_1(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t *start_vertex, int s_len, int64_t end_vertex,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char **err_msg) {
+ try {
+ // in c code this should this must have been checked:
+ // 1) end_vertex is in the data_edges
+
+ #if 0 // set to 1 if needed
+ std::ostringstream log;
+ #endif
+ if (total_tuples == 1) {
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ *ret_path = NULL;
+ return 0;
+ }
+
+ graphType gType = directedFlag? DIRECTED: UNDIRECTED;
+ const int initial_size = 1;
+
+ std::deque< Path >paths;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ Pgr_dijkstra < DirectedGraph > digraph(gType, initial_size);
+ Pgr_dijkstra < UndirectedGraph > undigraph(gType, initial_size);
+
+ std::vector< int64_t > start_vertices(start_vertex, start_vertex + s_len);
+
+ if (directedFlag) {
+ digraph.initialize_graph(data_edges, total_tuples);
+ digraph.dijkstra(paths, start_vertices, end_vertex);
+ } else {
+ undigraph.initialize_graph(data_edges, total_tuples);
+ undigraph.dijkstra(paths, start_vertices, end_vertex);
+ }
+
+
+ int count(count_tuples(paths));
+
+ if (count == 0) {
+ *err_msg = strdup(
+ "NOTICE: No paths found between any of the starting vertices and the Ending vertex");
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ return 0;
+ }
+
+
+ *ret_path = pgr_get_memory3(count, (*ret_path));
+ int sequence(collapse_paths(ret_path, paths));
+
+
+ #if 1
+ *err_msg = strdup("OK");
+ #else
+ *err_msg = strdup(log.str().c_str());
+ #endif
+ *path_count = sequence;
+ return EXIT_SUCCESS;
+ } catch ( ... ) {
+ *err_msg = strdup("Caught unknown expection!");
+ return -1;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+int do_pgr_dijkstra_1_to_many(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t start_vertex, int64_t *end_vertex, int e_len,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char **err_msg) {
+ try {
+ // in c code this should this must have been checked:
+ // 1) start_vertex is in the data_edges
+
+ if (total_tuples == 1) {
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ *ret_path = NULL;
+ return 0;
+ }
+ graphType gType = directedFlag? DIRECTED: UNDIRECTED;
+ const int initial_size = 1;
+
+ std::deque< Path >paths;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ Pgr_dijkstra < DirectedGraph > digraph(gType, initial_size);
+ Pgr_dijkstra < UndirectedGraph > undigraph(gType, initial_size);
+
+
+ std::vector< int64_t > end_vertices(end_vertex, end_vertex + e_len);
+
+ if (directedFlag) {
+ digraph.initialize_graph(data_edges, total_tuples);
+ digraph.dijkstra(paths, start_vertex, end_vertices);
+ } else {
+ undigraph.initialize_graph(data_edges, total_tuples);
+ undigraph.dijkstra(paths, start_vertex, end_vertices);
+ }
+
+ int count(count_tuples(paths));
+
+ if (count == 0) {
+ *err_msg = strdup(
+ "NOTICE: No paths found between Starting and any of the Ending vertices");
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ return 0;
+ }
+
+
+ // get the space required to store all the paths
+ *ret_path = pgr_get_memory3(count, (*ret_path));
+ int sequence(collapse_paths(ret_path, paths));
+
+ #if 1
+ *err_msg = strdup("OK");
+ #else
+ *err_msg = strdup(log.str().c_str());
+ #endif
+
+ *path_count = sequence;
+ return EXIT_SUCCESS;
+ } catch ( ... ) {
+ *err_msg = strdup("Caught unknown expection!");
+ return -1;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+int do_pgr_dijkstra(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t start_vertex, int64_t end_vertex,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char **err_msg) {
+ try {
+ // in c code this should have been checked:
+ // 1) start_vertex is in the data_edges DONE
+ // 2) end_vertex is in the data_edges DONE
+ // 3) start and end_vertex are different DONE
+
+ if (total_tuples == 1) {
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ *ret_path = NULL;
+ return 0;
+ }
+ graphType gType = directedFlag? DIRECTED: UNDIRECTED;
+ const int initial_size = 1;
+
+ Path path;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ Pgr_dijkstra < DirectedGraph > digraph(gType, initial_size);
+ Pgr_dijkstra < UndirectedGraph > undigraph(gType, initial_size);
+
+ if (directedFlag) {
+ digraph.initialize_graph(data_edges, total_tuples);
+ digraph.dijkstra(path, start_vertex, end_vertex);
+ } else {
+ undigraph.initialize_graph(data_edges, total_tuples);
+ undigraph.dijkstra(path, start_vertex, end_vertex);
+ }
+
+ int count(path.path.size());
+
+ if (count == 0) {
+ *err_msg = strdup(
+ "NOTICE: No path found between Starting and Ending vertices");
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ return 0;
+ }
+
+
+
+ // get the space required to store all the paths
+ *ret_path = NULL;
+ *ret_path = pgr_get_memory3(count, (*ret_path));
+
+ int sequence = 0;
+ path.dpPrint(ret_path, sequence);
+
+ #if 1
+ *err_msg = strdup("OK");
+ #else
+ *err_msg = strdup(log.str().c_str());
+ #endif
+ *path_count = count;
+ return EXIT_SUCCESS;
+ } catch ( ... ) {
+ *err_msg = strdup("Caught unknown expection!");
+ return -1;
+ }
+}
+
+#if 0 // used for debugging
+std::ostringstream log;
+// move around this lines to force a return with an empty path and the log msg
+// cool for debugging
+if 0
+*err_msg = strdup(log.str().c_str());
+(*path_count) = 1;
+*ret_path = noPathFound3(start_vertex, (*ret_path));
+return -1;
+#endif
+
diff --git a/src/dijkstra/src/dijkstra_driver.h b/src/dijkstra/src/dijkstra_driver.h
new file mode 100644
index 0000000..92b91d3
--- /dev/null
+++ b/src/dijkstra/src/dijkstra_driver.h
@@ -0,0 +1,61 @@
+/*PGR
+
+file: dijkstra_driver.h
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_DIJKSTRA_SRC_DIJKSTRA_DRIVER_H_
+#define SRC_DIJKSTRA_SRC_DIJKSTRA_DRIVER_H_
+
+#include "./../../common/src/pgr_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int do_pgr_dijkstra_many_to_many(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t *start_vertex, int s_len, int64_t *end_vertex, int e_len,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg);
+
+int do_pgr_dijkstra_many_to_1(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t *start_vertex, int s_len, int64_t end_vertex,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg);
+
+int do_pgr_dijkstra_1_to_many(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t start_vertex, int64_t *end_vertex, int n_end,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg);
+
+int do_pgr_dijkstra(pgr_edge_t * edges, int64_t total_tuples,
+ int64_t start_vertex, int64_t end_vertex,
+ bool has_rcost, bool directed,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SRC_DIJKSTRA_SRC_DIJKSTRA_DRIVER_H_
diff --git a/src/dijkstra/src/many_to_1_dijkstra.c b/src/dijkstra/src/many_to_1_dijkstra.c
new file mode 100644
index 0000000..ea2735d
--- /dev/null
+++ b/src/dijkstra/src/many_to_1_dijkstra.c
@@ -0,0 +1,188 @@
+/*pgRouting
+ *
+ * File: many_to_1_dijkstra.c
+ * Copyright (c) 2015 Celia Virginia Vergara Castillo
+ *
+ * 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.
+ *
+ */
+// #define DEBUG
+#include "postgres.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "utils/array.h"
+#include "catalog/pg_type.h"
+#if PGSQL_VERSION > 92
+#include "access/htup_details.h"
+#endif
+
+#include "fmgr.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+#include "./dijkstra_driver.h"
+
+#ifndef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+
+static int dijkstra_many_to_1_driver(
+ char* sql, int64_t *start_vertex, int num,
+ int64_t end_vertex,
+ bool directed, bool has_rcost,
+ pgr_path_element3_t **path, int *path_count) {
+ int SPIcode;
+ pgr_edge_t *edges = NULL;
+ int64_t total_tuples = 0;
+
+
+ char *err_msg = (char *)"";
+ int ret = -1;
+
+
+ SPIcode = pgr_get_data(sql, &edges, &total_tuples, has_rcost,
+ end_vertex, end_vertex);
+
+ if (SPIcode == -1) {
+ return SPIcode;
+ }
+
+ ret = do_pgr_dijkstra_many_to_1(edges, total_tuples,
+ start_vertex, num, end_vertex,
+ has_rcost, directed,
+ path, path_count, &err_msg);
+
+ if (ret < 0) {
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
+
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
+}
+
+
+#ifndef _MSC_VER
+Datum dijkstra_many_to_1(PG_FUNCTION_ARGS);
+#else // _MSC_VER
+PGDLLEXPORT Datum dijkstra_many_to_1(PG_FUNCTION_ARGS);
+#endif // _MSC_VER
+
+
+PG_FUNCTION_INFO_V1(dijkstra_many_to_1);
+#ifndef _MSC_VER
+Datum
+#else // _MSC_VER
+PGDLLEXPORT Datum
+#endif
+dijkstra_many_to_1(PG_FUNCTION_ARGS) {
+ FuncCallContext *funcctx;
+ int call_cntr;
+ int max_calls;
+ TupleDesc tuple_desc;
+ pgr_path_element3_t *ret_path = 0;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL()) {
+ MemoryContext oldcontext;
+ int path_count = 0;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ int64_t* sourcesArr;
+ int num;
+
+ sourcesArr = (int64_t*) pgr_get_bigIntArray(&num, PG_GETARG_ARRAYTYPE_P(1));
+ PGR_DBG("sourcesArr size %d ", num);
+
+ PGR_DBG("Calling dijkstra_many_to_1_driver");
+ dijkstra_many_to_1_driver(
+ pgr_text2char(PG_GETARG_TEXT_P(0)),
+ sourcesArr, num,
+ PG_GETARG_INT64(2),
+ PG_GETARG_BOOL(3),
+ PG_GETARG_BOOL(4), &ret_path, &path_count);
+
+ free(sourcesArr);
+
+ /* total number of tuples to be returned */
+ funcctx->max_calls = path_count;
+ funcctx->user_fctx = ret_path;
+
+ 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);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ call_cntr = funcctx->call_cntr;
+ max_calls = funcctx->max_calls;
+ tuple_desc = funcctx->tuple_desc;
+ ret_path = (pgr_path_element3_t*) funcctx->user_fctx;
+
+ /* do when there is more left to send */
+ if (call_cntr < max_calls) {
+ HeapTuple tuple;
+ Datum result;
+ Datum *values;
+ char* nulls;
+
+ values = palloc(7 * sizeof(Datum));
+ nulls = palloc(7 * sizeof(char));
+ // id, start_v, node, edge, cost, tot_cost
+ values[0] = Int32GetDatum(call_cntr + 1);
+ nulls[0] = ' ';
+ values[1] = Int32GetDatum(ret_path[call_cntr].seq);
+ nulls[1] = ' ';
+ values[2] = Int64GetDatum(ret_path[call_cntr].from);
+ nulls[2] = ' ';
+ values[3] = Int64GetDatum(ret_path[call_cntr].vertex);
+ nulls[3] = ' ';
+ values[4] = Int64GetDatum(ret_path[call_cntr].edge);
+ nulls[4] = ' ';
+ values[5] = Float8GetDatum(ret_path[call_cntr].cost);
+ nulls[5] = ' ';
+ values[6] = Float8GetDatum(ret_path[call_cntr].tot_cost);
+ nulls[6] = ' ';
+
+ tuple = heap_formtuple(tuple_desc, values, nulls);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ /* clean up (this is not really necessary) */
+ pfree(values);
+ pfree(nulls);
+
+ SRF_RETURN_NEXT(funcctx, result);
+ } else {
+ /* do when there is no more left */
+ if (ret_path) free(ret_path);
+ SRF_RETURN_DONE(funcctx);
+ }
+}
+
diff --git a/src/dijkstra/src/many_to_many_dijkstra.c b/src/dijkstra/src/many_to_many_dijkstra.c
new file mode 100644
index 0000000..85c2d59
--- /dev/null
+++ b/src/dijkstra/src/many_to_many_dijkstra.c
@@ -0,0 +1,188 @@
+/*pgRouting
+ *
+ * File: many_to_1_dijkstra.c
+ * Copyright (c) 2015 Celia Virginia Vergara Castillo
+ *
+ * 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.
+ *
+ */
+// #define DEBUG
+#include "postgres.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "utils/array.h"
+#include "catalog/pg_type.h"
+#if PGSQL_VERSION > 92
+#include "access/htup_details.h"
+#endif
+
+#include "fmgr.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+#include "./dijkstra_driver.h"
+
+#ifndef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+
+static int dijkstra_many_to_many_driver(
+ char* sql,
+ int64_t *start_vertex, int s_len,
+ int64_t *end_vertex, int e_len,
+ bool directed, bool has_rcost,
+ pgr_path_element3_t **path, int *path_count) {
+ int SPIcode = 0;
+ pgr_edge_t *edges = NULL;
+ int64_t total_tuples = 0;
+
+
+ char *err_msg = (char *)"";
+ int ret = -1;
+
+ pgr_get_data(sql, &edges, &total_tuples, has_rcost, -1, -1);
+
+ ret = do_pgr_dijkstra_many_to_many(edges, total_tuples,
+ start_vertex, s_len, end_vertex, e_len,
+ has_rcost, directed,
+ path, path_count, &err_msg);
+
+ if (ret < 0) {
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
+
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
+}
+
+
+#ifndef _MSC_VER
+Datum dijkstra_many_to_many(PG_FUNCTION_ARGS);
+#else // _MSC_VER
+PGDLLEXPORT Datum dijkstra_many_to_many(PG_FUNCTION_ARGS);
+#endif // _MSC_VER
+
+
+PG_FUNCTION_INFO_V1(dijkstra_many_to_many);
+#ifndef _MSC_VER
+Datum
+#else // _MSC_VER
+PGDLLEXPORT Datum
+#endif
+dijkstra_many_to_many(PG_FUNCTION_ARGS) {
+ FuncCallContext *funcctx;
+ int call_cntr;
+ int max_calls;
+ TupleDesc tuple_desc;
+ pgr_path_element3_t *ret_path = 0;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL()) {
+ MemoryContext oldcontext;
+ int path_count = 0;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ int64_t* sourcesArr;
+ int64_t* targetsArr;
+ int s_len, e_len;
+
+ sourcesArr = (int64_t*) pgr_get_bigIntArray(&s_len, PG_GETARG_ARRAYTYPE_P(1));
+ targetsArr = (int64_t*) pgr_get_bigIntArray(&e_len, PG_GETARG_ARRAYTYPE_P(2));
+ PGR_DBG("sourcesArr size %d ", num);
+
+ PGR_DBG("Calling dijkstra_many_to_1_driver");
+ dijkstra_many_to_many_driver(
+ pgr_text2char(PG_GETARG_TEXT_P(0)),
+ sourcesArr, s_len,
+ targetsArr, e_len,
+ PG_GETARG_BOOL(3),
+ PG_GETARG_BOOL(4), &ret_path, &path_count);
+
+ free(sourcesArr);
+ free(targetsArr);
+
+ /* total number of tuples to be returned */
+ funcctx->max_calls = path_count;
+ funcctx->user_fctx = ret_path;
+
+ 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);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ call_cntr = funcctx->call_cntr;
+ max_calls = funcctx->max_calls;
+ tuple_desc = funcctx->tuple_desc;
+ ret_path = (pgr_path_element3_t*) funcctx->user_fctx;
+
+ /* do when there is more left to send */
+ if (call_cntr < max_calls) {
+ HeapTuple tuple;
+ Datum result;
+ Datum *values;
+ char* nulls;
+
+ values = palloc(8 * sizeof(Datum));
+ nulls = palloc(8 * sizeof(char));
+ // id, start_v, node, edge, cost, tot_cost
+ values[0] = Int32GetDatum(call_cntr + 1);
+ nulls[0] = ' ';
+ values[1] = Int32GetDatum(ret_path[call_cntr].seq);
+ nulls[1] = ' ';
+ values[2] = Int64GetDatum(ret_path[call_cntr].from);
+ nulls[2] = ' ';
+ values[3] = Int64GetDatum(ret_path[call_cntr].to);
+ nulls[3] = ' ';
+ values[4] = Int64GetDatum(ret_path[call_cntr].vertex);
+ nulls[4] = ' ';
+ values[5] = Int64GetDatum(ret_path[call_cntr].edge);
+ nulls[5] = ' ';
+ values[6] = Float8GetDatum(ret_path[call_cntr].cost);
+ nulls[6] = ' ';
+ values[7] = Float8GetDatum(ret_path[call_cntr].tot_cost);
+ nulls[7] = ' ';
+
+ tuple = heap_formtuple(tuple_desc, values, nulls);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ /* clean up (this is not really necessary) */
+ pfree(values);
+ pfree(nulls);
+
+ SRF_RETURN_NEXT(funcctx, result);
+ } else {
+ /* do when there is no more left */
+ if (ret_path) free(ret_path);
+ SRF_RETURN_DONE(funcctx);
+ }
+}
+
diff --git a/src/dijkstra/src/pgr_dijkstra.hpp b/src/dijkstra/src/pgr_dijkstra.hpp
new file mode 100644
index 0000000..c9d6ee7
--- /dev/null
+++ b/src/dijkstra/src/pgr_dijkstra.hpp
@@ -0,0 +1,375 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_DIJKSTRA_SRC_PGR_DIJKSTRA_H_
+#define SRC_DIJKSTRA_SRC_PGR_DIJKSTRA_H_
+
+
+#include <deque>
+#include <vector>
+#include <set>
+
+#include <boost/config.hpp>
+
+
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+
+#include "./../../common/src/basePath_SSEC.hpp"
+#include "./../../common/src/baseGraph.hpp"
+#include "postgres.h"
+
+template < class G >
+class Pgr_dijkstra
+ :public Pgr_base_graph<G> {
+ public:
+ //! \brief the constructor
+ explicit Pgr_dijkstra(graphType gtype, const int initial_size)
+ :Pgr_base_graph<G>(gtype, initial_size) {}
+
+
+ /*! \brief Perfom the inizialization of the graph
+ For Dijkstra only requieres the data insertion.
+
+ Any other different initialization needs a different function.
+ \param[in] data_edges
+ \param[in] count
+ */
+ void
+ initialize_graph(pgr_edge_t *data_edges, int64_t count) {
+ this->graph_insert_data(data_edges, count);
+ }
+
+ void
+ dijkstra(Path &path, int64_t start_vertex, int64_t end_vertex) {
+ typedef typename boost::graph_traits < G >::vertex_descriptor V;
+
+ // adjust predecessors and distances vectors
+ this->predecessors.clear();
+ this->distances.clear();
+
+ this->predecessors.resize(boost::num_vertices(this->graph));
+ this->distances.resize(boost::num_vertices(this->graph));
+
+ // get the graphs source and target
+ V v_source;
+ V v_target;
+
+ if (!this->get_gVertex(start_vertex, v_source)
+ || !this->get_gVertex(end_vertex, v_target)) {
+ // path.clear();
+ return;
+ }
+
+ // perform the algorithm
+ dijkstra_1_to_1(v_source, v_target);
+
+ // get the results
+ this->get_path(path, v_source, v_target);
+ return;
+ }
+
+
+
+
+ // preparation for 1 to many
+ void
+ dijkstra(std::deque< Path > &paths,
+ int64_t start_vertex,
+ std::vector< int64_t > end_vertex) {
+ typedef typename boost::graph_traits < G >::vertex_descriptor V;
+
+ // adjust predecessors and distances vectors
+ this->predecessors.clear();
+ this->distances.clear();
+
+ this->predecessors.resize(boost::num_vertices(this->graph));
+ this->distances.resize(boost::num_vertices(this->graph));
+
+ // get the graphs source and target
+ V v_source;
+ if (!this->get_gVertex(start_vertex, v_source)) {
+ // paths.clear();
+ return;
+ }
+
+ std::set< V > v_targets;
+ for (unsigned int i = 0; i < end_vertex.size(); i++) {
+ V v_target;
+ if (this->get_gVertex(end_vertex[i], v_target)) {
+ v_targets.insert(v_target);
+ }
+ }
+
+ // perform the algorithm
+ dijkstra_1_to_many(v_source, v_targets);
+
+ // get the results // route id are the targets
+ this->get_path(paths, v_source, v_targets);
+ return;
+ }
+
+ // preparation for many to 1
+ void
+ dijkstra(std::deque< Path > &paths,
+ std::vector < int64_t > start_vertex,
+ int64_t end_vertex) {
+ typedef typename boost::graph_traits < G >::vertex_descriptor V;
+
+ // adjust predecessors and distances vectors
+ this->predecessors.clear();
+ this->distances.clear();
+
+ this->predecessors.resize(boost::num_vertices(this->graph));
+ this->distances.resize(boost::num_vertices(this->graph));
+
+ // get the graphs source and target
+ V v_target;
+ if (!this->get_gVertex(end_vertex, v_target)) {
+ // paths.clear();
+ return;
+ }
+
+ std::set< V > v_sources;
+ for (unsigned int i = 0; i < start_vertex.size(); i++) {
+ V v_source;
+ if (!this->get_gVertex(start_vertex[i], v_source)) {
+ // paths.clear();
+ return;
+ }
+ v_sources.insert(v_source);
+ }
+
+ // perform the algorithm // a call for each of the sources
+ for (const auto &v_source : v_sources) {
+ Path path;
+ dijkstra_1_to_1(v_source, v_target);
+ this->get_path(path, v_source, v_target);
+ paths.push_back(path);
+ }
+ return;
+ }
+
+ // preparation for many to many
+ void
+ dijkstra(std::deque< Path > &paths,
+ std::vector< int64_t > start_vertex,
+ std::vector< int64_t > end_vertex) {
+ // a call to 1 to many is faster for each of the sources
+ for (const auto &start : start_vertex) {
+ dijkstra(paths, start, end_vertex);
+ }
+ return;
+ }
+
+
+
+ // preparation for 1 to distance
+ void
+ dijkstra_dd(Path &path, int64_t start_vertex, float8 distance) {
+ typedef typename boost::graph_traits < G >::vertex_descriptor V;
+
+ // adjust predecessors and distances vectors
+ this->predecessors.clear();
+ this->distances.clear();
+ this->nodesInDistance.clear();
+
+ this->predecessors.resize(boost::num_vertices(this->graph));
+ this->distances.resize(boost::num_vertices(this->graph));
+
+ // get ource;
+ V v_source;
+ if (!this->get_gVertex(start_vertex, v_source)) {
+ path.clear();
+ return;
+ }
+
+ // perform the algorithm
+ dijkstra_1_to_distance(v_source, distance);
+
+ // get the results
+ this->get_nodesInDistance(path, v_source, distance);
+ return;
+ }
+
+
+ // preparation for many to distance
+ void
+ dijkstra_dd(std::deque< Path > &paths,
+ std::vector< int64_t > start_vertex,
+ float8 distance) {
+ typedef typename boost::graph_traits < G >::vertex_descriptor V;
+
+ // adjust predecessors and distances vectors
+ this->predecessors.clear();
+ this->distances.clear();
+ this->nodesInDistance.clear();
+
+ this->predecessors.resize(boost::num_vertices(this->graph));
+ this->distances.resize(boost::num_vertices(this->graph));
+
+ // get the graph's source
+ std::set< V > v_sources;
+ for (unsigned int i = 0; i < start_vertex.size(); i++) {
+ V v_source;
+ if (!this->get_gVertex(start_vertex[i], v_source)) {
+ paths.clear();
+ return;
+ }
+ v_sources.insert(v_source);
+ }
+
+ // perform the algorithm
+ for (const auto &v_source : v_sources) {
+ dijkstra_1_to_distance(v_source, distance);
+ Path path;
+ this->get_nodesInDistance(path, v_source, distance);
+ paths.push_back(path);
+ }
+
+ return;
+ }
+
+
+
+ private:
+ //! visitor that terminates when we find the goal
+ struct found_one_goal{}; //!< exception for termination
+
+ //! class for stopping when 1 target is found
+ template <class Vertex>
+ class dijkstra_one_goal_visitor
+ :public boost::default_dijkstra_visitor {
+ public:
+ explicit dijkstra_one_goal_visitor(Vertex goal) : m_goal(goal) {}
+ template <class Graph>
+ void examine_vertex(Vertex u, Graph& g) {
+ if (u == m_goal) throw found_one_goal();
+ }
+ private:
+ Vertex m_goal;
+ };
+
+
+ //! class for stopping when a distance/cost has being surpassed
+ template <class Vertex>
+ class dijkstra_distance_visitor
+ :public boost::default_dijkstra_visitor {
+ public:
+ explicit dijkstra_distance_visitor(float8 goal,
+ std::deque< Vertex > &nodesInDistance,
+ std::vector< float8 > &distances)
+ :m_goal(goal), m_nodes(nodesInDistance), m_dist(distances) {}
+ template <class Graph>
+ void examine_vertex(Vertex u, Graph& g) {
+ m_nodes.push_back(u);
+ if (m_dist[u] >= m_goal) throw found_one_goal();
+ }
+ private:
+ float8 m_goal;
+ std::deque< Vertex > &m_nodes;
+ std::vector< float8 > &m_dist;
+ };
+
+ //! visitor that terminates when we find all goals
+ struct found_all_goals{}; //!< exception for termination
+
+ //! class for stopping when all targets are found
+ template <class V>
+ class dijkstra_many_goal_visitor
+ :public boost::default_dijkstra_visitor {
+ public:
+ explicit dijkstra_many_goal_visitor(std::set< V > goals)
+ :m_goals(goals) {}
+ template <class Graph>
+ void examine_vertex(V u, Graph &g) {
+ typename std::set< V >::iterator s_it;
+ s_it = m_goals.find(u);
+ if (s_it == m_goals.end()) return;
+ // we found one more goal
+ m_goals.erase(s_it);
+ if (m_goals.size() == 0) throw found_all_goals();
+ }
+ private:
+ std::set< V > m_goals;
+ };
+
+
+
+ //! Call to Dijkstra 1 source to many targets
+ template <class V>
+ bool
+ dijkstra_1_to_many(V source, std::set< V > targets) {
+ bool found = false;
+ try {
+ boost::dijkstra_shortest_paths(this->graph, source,
+ boost::predecessor_map(&this->predecessors[0])
+ .weight_map(get(&boost_edge_t::cost, this->graph))
+ .distance_map(&this->distances[0])
+ .visitor(dijkstra_many_goal_visitor< V >(targets)));
+ }
+ catch(found_all_goals &fg) {
+ found = true; // Target vertex found
+ }
+ return found;
+ }
+
+ //! Call to Dijkstra 1 source to 1 target
+ template <class V>
+ bool
+ dijkstra_1_to_1(V source, V target) {
+ bool found = false;
+ try {
+ boost::dijkstra_shortest_paths(this->graph, source,
+ boost::predecessor_map(&this->predecessors[0])
+ .weight_map(get(&boost_edge_t::cost, this->graph))
+ .distance_map(&this->distances[0])
+ .visitor(dijkstra_one_goal_visitor<V>(target)));
+ }
+ catch(found_one_goal &fg) {
+ found = true; // Target vertex found
+ }
+ return found;
+ }
+
+ //! Call to Dijkstra 1 source to distance
+ template <class V>
+ bool
+ dijkstra_1_to_distance(V source, float8 distance) {
+ bool found = false;
+ try {
+ boost::dijkstra_shortest_paths(this->graph, source,
+ boost::predecessor_map(&this->predecessors[0])
+ .weight_map(get(&boost_edge_t::cost, this->graph))
+ .distance_map(&this->distances[0])
+ .visitor(dijkstra_distance_visitor< V >(
+ distance,
+ this->nodesInDistance,
+ this->distances)));
+ }
+ catch(found_one_goal &fg) {
+ found = true; // Target vertex found
+ }
+ return found;
+ }
+};
+
+#endif // SRC_DIJKSTRA_SRC_PGR_DIJKSTRA_H_
diff --git a/src/dijkstra/test/1_to_many.result b/src/dijkstra/test/1_to_many.result
new file mode 100644
index 0000000..37a056f
--- /dev/null
+++ b/src/dijkstra/test/1_to_many.result
@@ -0,0 +1,32 @@
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|9|1|2
+4|4|3|9|16|1|3
+5|5|3|4|3|1|4
+6|6|3|3|-1|0|5
+1|1|3|2|2|1|0
+2|2|3|3|-1|0|1
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|5|1|2
+4|4|3|3|-1|0|3
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|9|1|2
+4|4|3|9|16|1|3
+5|5|3|4|3|1|4
+6|6|3|3|-1|0|5
+7|1|5|2|4|1|0
+8|2|5|5|-1|0|1
+1|1|3|2|2|1|0
+2|2|3|3|-1|0|1
+3|1|5|2|4|1|0
+4|2|5|5|-1|0|1
+1|1|5|2|4|1|0
+2|2|5|5|-1|0|1
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|5|1|2
+4|4|3|3|-1|0|3
+5|1|5|2|4|1|0
+6|2|5|5|-1|0|1
diff --git a/src/dijkstra/test/1_to_many.test.sql b/src/dijkstra/test/1_to_many.test.sql
new file mode 100644
index 0000000..a79a978
--- /dev/null
+++ b/src/dijkstra/test/1_to_many.test.sql
@@ -0,0 +1,53 @@
+
+
+-- Examples for :ref:`fig1-direct-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3]
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3], false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3]
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3], false
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3,5]
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3,5], false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3,5]
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3,5], false
+ );
+
+
diff --git a/src/dijkstra/test/dijkstra-dir-00.result b/src/dijkstra/test/dijkstra-dir-00.result
new file mode 100644
index 0000000..38c8853
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-dir-00.result
@@ -0,0 +1,35 @@
+0|11|13|1
+1|12|15|1
+2|9|9|1
+3|8|8|1
+4|7|7|1
+5|6|6|1
+6|5|-1|0
+1|1|11|13|1|0
+2|2|12|15|1|1
+3|3|9|9|1|2
+4|4|8|8|1|3
+5|5|7|7|1|4
+6|6|6|6|1|5
+7|7|5|-1|0|6
+1|1|11|13|1|0
+2|2|12|15|1|1
+3|3|9|9|1|2
+4|4|8|8|1|3
+5|5|7|7|1|4
+6|6|6|6|1|5
+7|7|5|-1|0|6
+1|1|11|13|1|0
+2|2|12|15|1|1
+3|3|9|9|1|2
+4|4|8|8|1|3
+5|5|7|7|1|4
+6|6|6|6|1|5
+7|7|5|-1|0|6
+1|1|11|13|1|0
+2|2|12|15|1|1
+3|3|9|9|1|2
+4|4|8|8|1|3
+5|5|7|7|1|4
+6|6|6|6|1|5
+7|7|5|-1|0|6
diff --git a/src/dijkstra/test/dijkstra-dir-00.test.sql b/src/dijkstra/test/dijkstra-dir-00.test.sql
new file mode 100644
index 0000000..291f474
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-dir-00.test.sql
@@ -0,0 +1,43 @@
+-- all this queries are equivlent (give the same results)
+
+-- include reverse_costs
+-- convert -1 costs to a large number
+-- ignores -1 costs
+-- directed = true (DIRECTED)
+-- autodetect reverse_cost
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost,
+ case when reverse_cost<=0 then 999 else reverse_cost end as reverse_cost
+ from edges1',
+ 11, 5, true, true);
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost,
+ case when reverse_cost<=0 then 999 else reverse_cost end as reverse_cost
+ from edges1',
+ 11, 5, true);
+
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ case when cost<=0 then 999 else cost end as cost,
+ case when reverse_cost<=0 then 999 else reverse_cost end as reverse_cost
+ from edges1',
+ 11, 5);
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ cost,
+ reverse_cost
+ from edges1',
+ 11, 5);
+
+
+select * from pgr_dijkstra(
+ 'select *
+ from edges1',
+ 11, 5);
+
diff --git a/src/dijkstra/test/dijkstra-dir-01.result b/src/dijkstra/test/dijkstra-dir-01.result
new file mode 100644
index 0000000..9aaa39c
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-dir-01.result
@@ -0,0 +1,20 @@
+0|5|6|1
+1|6|7|1
+2|7|8|1
+3|8|11|1
+4|11|-1|0
+1|1|5|6|1|0
+2|2|6|7|1|1
+3|3|7|8|1|2
+4|4|8|11|1|3
+5|5|11|-1|0|4
+1|1|5|6|1|0
+2|2|6|7|1|1
+3|3|7|8|1|2
+4|4|8|11|1|3
+5|5|11|-1|0|4
+1|1|5|6|1|0
+2|2|6|7|1|1
+3|3|7|8|1|2
+4|4|8|11|1|3
+5|5|11|-1|0|4
diff --git a/src/dijkstra/test/dijkstra-dir-01.test.sql b/src/dijkstra/test/dijkstra-dir-01.test.sql
new file mode 100644
index 0000000..c61717a
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-dir-01.test.sql
@@ -0,0 +1,35 @@
+-- all this queries are equivlent (give the same results)
+
+-- DOES NOT include reverse_costs
+-- convert -1 costs to a large number
+-- ignores -1 costs
+-- directed = false (UNDIRECTED)
+-- autodetect reverse_cost
+
+-- no path found
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost
+ from edges1',
+ 5, 11, true, false);
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost
+ from edges1',
+ 5, 11 ,true);
+
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ case when cost<=0 then 999 else cost end as cost
+ from edges1',
+ 5, 11);
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ cost
+ from edges1',
+ 5, 11);
+
diff --git a/src/dijkstra/test/dijkstra-undi-00.result b/src/dijkstra/test/dijkstra-undi-00.result
new file mode 100644
index 0000000..6fc5c9a
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-undi-00.result
@@ -0,0 +1,25 @@
+0|11|11|1
+1|8|8|1
+2|7|7|1
+3|6|6|1
+4|5|-1|0
+1|1|11|11|1|0
+2|2|8|8|1|1
+3|3|7|7|1|2
+4|4|6|6|1|3
+5|5|5|-1|0|4
+1|1|11|11|1|0
+2|2|8|8|1|1
+3|3|7|7|1|2
+4|4|6|6|1|3
+5|5|5|-1|0|4
+1|1|11|11|1|0
+2|2|8|8|1|1
+3|3|7|7|1|2
+4|4|6|6|1|3
+5|5|5|-1|0|4
+1|1|11|11|1|0
+2|2|8|8|1|1
+3|3|7|7|1|2
+4|4|6|6|1|3
+5|5|5|-1|0|4
diff --git a/src/dijkstra/test/dijkstra-undi-00.test.sql b/src/dijkstra/test/dijkstra-undi-00.test.sql
new file mode 100644
index 0000000..fe24eda
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-undi-00.test.sql
@@ -0,0 +1,43 @@
+-- all this queries are equivlent (give the same results)
+
+-- include reverse_costs
+-- convert -1 costs to a large number
+-- ignores -1 costs
+-- directed = false (UNDIRECTED)
+-- autodetect reverse_cost
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost,
+ case when reverse_cost<=0 then 999 else reverse_cost end as reverse_cost
+ from edges1',
+ 11, 5, false, true);
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost,
+ case when reverse_cost<=0 then 999 else reverse_cost end as reverse_cost
+ from edges1',
+ 11, 5, false);
+
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ case when cost<=0 then 999 else cost end as cost,
+ case when reverse_cost<=0 then 999 else reverse_cost end as reverse_cost
+ from edges1',
+ 11, 5,false);
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ cost,
+ reverse_cost
+ from edges1',
+ 11, 5, false);
+
+
+select * from pgr_dijkstra(
+ 'select *
+ from edges1',
+ 11, 5, false);
+
diff --git a/src/dijkstra/test/dijkstra-undi-01.result b/src/dijkstra/test/dijkstra-undi-01.result
new file mode 100644
index 0000000..4cf32e2
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-undi-01.result
@@ -0,0 +1,20 @@
+0|11|11|1
+1|8|8|1
+2|7|7|1
+3|6|6|1
+4|5|-1|0
+1|1|11|11|1|0
+2|2|8|8|1|1
+3|3|7|7|1|2
+4|4|6|6|1|3
+5|5|5|-1|0|4
+1|1|11|11|1|0
+2|2|8|8|1|1
+3|3|7|7|1|2
+4|4|6|6|1|3
+5|5|5|-1|0|4
+1|1|11|11|1|0
+2|2|8|8|1|1
+3|3|7|7|1|2
+4|4|6|6|1|3
+5|5|5|-1|0|4
diff --git a/src/dijkstra/test/dijkstra-undi-01.test.sql b/src/dijkstra/test/dijkstra-undi-01.test.sql
new file mode 100644
index 0000000..c7c00c5
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-undi-01.test.sql
@@ -0,0 +1,33 @@
+
+-- DOES NOT include reverse_costs
+-- convert -1 costs to a large number
+-- ignores -1 costs
+-- directed = false (UNDIRECTED)
+-- autodetect reverse_cost
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost
+ from edges1',
+ 11, 5, false, false);
+
+select * from pgr_dijkstra(
+ 'select id as id, source::int4, target::int4,
+ case when cost<=0 then 999 else cost end as cost
+ from edges1',
+ 11, 5, false);
+
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ case when cost<=0 then 999 else cost end as cost
+ from edges1',
+ 11, 5, false);
+
+select * from pgr_dijkstra(
+ 'select id, source, target,
+ cost
+ from edges1',
+ 11, 5, false);
+
+
diff --git a/src/dijkstra/test/dijkstra-v2.result b/src/dijkstra/test/dijkstra-v2.result
new file mode 100644
index 0000000..9518c72
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-v2.result
@@ -0,0 +1,12 @@
+0|2|4|1
+1|5|8|1
+2|6|9|1
+3|9|16|1
+4|4|3|1
+5|3|-1|0
+0|2|4|1
+1|5|8|1
+2|6|5|1
+3|3|-1|0
+0|2|2|1
+1|3|-1|0
diff --git a/doc/test/dijkstra-any.test b/src/dijkstra/test/dijkstra-v2.test.sql
similarity index 51%
rename from doc/test/dijkstra-any.test
rename to src/dijkstra/test/dijkstra-v2.test.sql
index 1593f19..1f7c86e 100644
--- a/doc/test/dijkstra-any.test
+++ b/src/dijkstra/test/dijkstra-v2.test.sql
@@ -1,15 +1,30 @@
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
--- PGR_dijkstra
+-- PGR_dijkstra V.2.0
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
SELECT seq, id1 AS node, id2 AS edge, cost
FROM pgr_dijkstra(
- 'SELECT id, source, target, cost FROM edge_table order by id',
- 7, 12, false, false);
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2,3, true, false
+ );
SELECT seq, id1 AS node, id2 AS edge, cost
FROM pgr_dijkstra(
'SELECT id, source, target, cost, reverse_cost FROM edge_table',
- 7, 12, true, true);
+ 2,3, true, true
+ );
+
+SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, false, false
+ );
+
+SELECT seq, id1 AS node, id2 AS edge, cost
+ FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3, false, true
+ );
+
diff --git a/src/dijkstra/test/dijkstra-v3.result b/src/dijkstra/test/dijkstra-v3.result
new file mode 100644
index 0000000..6ef73fb
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-v3.result
@@ -0,0 +1,175 @@
+1|1|2|4|1|0
+2|2|5|8|1|1
+3|3|6|9|1|2
+4|4|9|16|1|3
+5|5|4|3|1|4
+6|6|3|-1|0|5
+1|1|2|4|1|0
+2|2|5|-1|0|1
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|9|1|2
+4|4|3|9|16|1|3
+5|5|3|4|3|1|4
+6|6|3|3|-1|0|5
+7|1|5|2|4|1|0
+8|2|5|5|-1|0|1
+1|1|11|13|1|0
+2|2|12|15|1|1
+3|3|9|16|1|2
+4|4|4|3|1|3
+5|5|3|-1|0|4
+1|1|11|13|1|0
+2|2|12|15|1|1
+3|3|9|9|1|2
+4|4|6|8|1|3
+5|5|5|-1|0|4
+1|1|2|2|4|1|0
+2|2|2|5|-1|0|1
+3|1|11|11|13|1|0
+4|2|11|12|15|1|1
+5|3|11|9|9|1|2
+6|4|11|6|8|1|3
+7|5|11|5|-1|0|4
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|9|1|2
+4|4|2|3|9|16|1|3
+5|5|2|3|4|3|1|4
+6|6|2|3|3|-1|0|5
+7|1|2|5|2|4|1|0
+8|2|2|5|5|-1|0|1
+9|1|11|3|11|13|1|0
+10|2|11|3|12|15|1|1
+11|3|11|3|9|16|1|2
+12|4|11|3|4|3|1|3
+13|5|11|3|3|-1|0|4
+14|1|11|5|11|13|1|0
+15|2|11|5|12|15|1|1
+16|3|11|5|9|9|1|2
+17|4|11|5|6|8|1|3
+18|5|11|5|5|-1|0|4
+1|1|2|2|1|0
+2|2|3|-1|0|1
+1|1|2|4|1|0
+2|2|5|-1|0|1
+1|1|11|11|1|0
+2|2|6|5|1|1
+3|3|3|-1|0|2
+1|1|11|11|1|0
+2|2|6|8|1|1
+3|3|5|-1|0|2
+1|1|2|2|4|1|0
+2|2|2|5|-1|0|1
+3|1|11|11|11|1|0
+4|2|11|6|8|1|1
+5|3|11|5|-1|0|2
+1|1|3|2|2|1|0
+2|2|3|3|-1|0|1
+3|1|5|2|4|1|0
+4|2|5|5|-1|0|1
+1|1|2|3|2|2|1|0
+2|2|2|3|3|-1|0|1
+3|1|2|5|2|4|1|0
+4|2|2|5|5|-1|0|1
+5|1|11|3|11|11|1|0
+6|2|11|3|6|5|1|1
+7|3|11|3|3|-1|0|2
+8|1|11|5|11|11|1|0
+9|2|11|5|6|8|1|1
+10|3|11|5|5|-1|0|2
+1|1|2|4|1|0
+2|2|5|-1|0|1
+1|1|2|2|4|1|0
+2|2|2|5|-1|0|1
+1|1|5|2|4|1|0
+2|2|5|5|-1|0|1
+1|1|2|5|2|4|1|0
+2|2|2|5|5|-1|0|1
+1|1|2|4|1|0
+2|2|5|8|1|1
+3|3|6|5|1|2
+4|4|3|-1|0|3
+1|1|2|4|1|0
+2|2|5|-1|0|1
+1|1|11|11|1|0
+2|2|6|5|1|1
+3|3|3|-1|0|2
+1|1|11|11|1|0
+2|2|6|8|1|1
+3|3|5|-1|0|2
+1|1|2|2|4|1|0
+2|2|2|5|-1|0|1
+3|1|11|11|11|1|0
+4|2|11|6|8|1|1
+5|3|11|5|-1|0|2
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|5|1|2
+4|4|3|3|-1|0|3
+5|1|5|2|4|1|0
+6|2|5|5|-1|0|1
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|5|1|2
+4|4|2|3|3|-1|0|3
+5|1|2|5|2|4|1|0
+6|2|2|5|5|-1|0|1
+7|1|11|3|11|11|1|0
+8|2|11|3|6|5|1|1
+9|3|11|3|3|-1|0|2
+10|1|11|5|11|11|1|0
+11|2|11|5|6|8|1|1
+12|3|11|5|5|-1|0|2
+0|2|4|1
+1|5|8|1
+2|6|9|1
+3|9|16|1
+4|4|3|1
+5|3|-1|0
+1|1|2|4|1|0
+2|2|5|8|1|1
+3|3|6|9|1|2
+4|4|9|16|1|3
+5|5|4|3|1|4
+6|6|3|-1|0|5
+1|1|2|4|1|0
+2|2|5|8|1|1
+3|3|6|9|1|2
+4|4|9|16|1|3
+5|5|4|3|1|4
+6|6|3|-1|0|5
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|9|1|2
+4|4|3|9|16|1|3
+5|5|3|4|3|1|4
+6|6|3|3|-1|0|5
+1|1|3|2|4|1|0
+2|2|3|5|8|1|1
+3|3|3|6|9|1|2
+4|4|3|9|16|1|3
+5|5|3|4|3|1|4
+6|6|3|3|-1|0|5
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|9|1|2
+4|4|2|3|9|16|1|3
+5|5|2|3|4|3|1|4
+6|6|2|3|3|-1|0|5
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|9|1|2
+4|4|2|3|9|16|1|3
+5|5|2|3|4|3|1|4
+6|6|2|3|3|-1|0|5
+0|2|2|1
+1|3|-1|0
+1|1|2|2|1|0
+2|2|3|-1|0|1
+1|1|3|2|2|1|0
+2|2|3|3|-1|0|1
+1|1|2|2|2|1|0
+2|2|2|3|-1|0|1
+1|1|2|3|2|2|1|0
+2|2|2|3|3|-1|0|1
diff --git a/src/dijkstra/test/dijkstra-v3.test.sql b/src/dijkstra/test/dijkstra-v3.test.sql
new file mode 100644
index 0000000..ac79aa1
--- /dev/null
+++ b/src/dijkstra/test/dijkstra-v3.test.sql
@@ -0,0 +1,276 @@
+
+-- Examples for :ref:`fig1-direct-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 5
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3,5]
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 3
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 5
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], 5
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2, 11], array[3,5]
+ );
+
+
+-- Examples for :ref:`fig2-undirect-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 5,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 3,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 11, 5,
+ false
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], 5,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3,5],
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2, 11], array[3,5],
+ false
+ );
+
+
+-- Examples for :ref:`fig3-direct-Cost`
+-------------------------------------------------------------------------------
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 5
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 3
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 5
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], 5
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3,5]
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2, 11], array[3,5]
+ );
+
+
+
+
+-- Examples for :ref:`fig4-undirect-Cost`
+-------------------------------------------------------------------------------
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 5,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 3,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 11, 5,
+ false
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], 5,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, array[3,5],
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2, 11], array[3,5],
+ false
+ );
+
+
+
+
+-- Equivalences for :ref:`fig1-direct-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ -- V2
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ true, -- directed flag
+ true -- has_rcost
+ );
+
+ -- V3
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ true -- directed flag
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2,3
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3],
+ true
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3]
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3],
+ true
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3]
+ );
+
+
+
+-- Equivalences for :ref:`fig2-undirect-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ -- V2
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ false, -- directed flag
+ true -- has_rcost
+ );
+
+
+ -- V3
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3,
+ false -- directed flag
+ );
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, array[3],
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], 3,
+ false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3],
+ false
+ );
+
+
diff --git a/src/dijkstra/test/dijkstra.data b/src/dijkstra/test/dijkstra.data
new file mode 100644
index 0000000..341990c
--- /dev/null
+++ b/src/dijkstra/test/dijkstra.data
@@ -0,0 +1,84 @@
+BEGIN;
+--
+-- PostgreSQL database dump
+--
+
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = off;
+SET check_function_bodies = false;
+SET client_min_messages = warning;
+SET escape_string_warning = off;
+
+SET search_path = public, pg_catalog;
+
+SET default_tablespace = '';
+
+SET default_with_oids = false;
+
+--
+-- Name: edges1; Type: TABLE; Schema: public; Owner: -; Tablespace:
+--
+
+DROP TABLE IF EXISTS edges1 CASCADE;
+
+CREATE TABLE edges1 (
+ id integer NOT NULL,
+ dir character varying,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ to_cost double precision,
+ rule text,
+ the_geom geometry,
+ CONSTRAINT enforce_dims_the_geom CHECK ((st_ndims(the_geom) = 2)),
+ CONSTRAINT enforce_geotype_the_geom CHECK (((geometrytype(the_geom) = 'LINESTRING'::text) OR (the_geom IS NULL)))
+-- , CONSTRAINT enforce_srid_the_geom CHECK ((st_srid(the_geom) = (0)))
+);
+
+
+
+--
+-- Data for Name: edges1; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY edges1 (id, dir, source, target, cost, reverse_cost, x1, y1, x2, y2, to_cost, rule, the_geom) FROM stdin WITH NULL '__NULL__';
+1 B 1 2 1 1 2 0 2 1 __NULL__ __NULL__ 010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2 TF 2 3 -1 1 2 1 3 1 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3 TF 3 4 -1 1 3 1 4 1 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4 B 2 7 1 1 2 1 2 2 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5 FT 3 8 1 -1 3 1 3 2 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6 B 5 6 1 1 0 2 1 2 __NULL__ __NULL__ 01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7 B 6 7 1 1 1 2 2 2 __NULL__ __NULL__ 010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8 B 7 8 1 1 2 2 3 2 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9 B 8 9 1 1 3 2 4 2 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10 B 7 10 1 1 2 2 2 3 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11 FT 8 11 1 -1 3 2 3 3 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12 FT 10 11 1 -1 2 3 3 3 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13 FT 11 12 1 -1 3 3 4 3 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14 B 10 13 1 1 2 3 2 4 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15 B 9 12 1 1 4 2 4 3 __NULL__ __NULL__ 0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16 B 4 9 1 1 4 1 4 2 __NULL__ __NULL__ 0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+\.
+
+
+
+--
+-- Name: edges1_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
+--
+
+ALTER TABLE ONLY edges1
+ ADD CONSTRAINT edges1_pkey PRIMARY KEY (id);
+
+select pgr_createVerticesTable('edges1');
+
+--
+-- PostgreSQL database dump complete
+--
+COMMIT;
+
+
diff --git a/src/dijkstra/test/issue-353.result b/src/dijkstra/test/issue-353.result
new file mode 100644
index 0000000..737ce00
--- /dev/null
+++ b/src/dijkstra/test/issue-353.result
@@ -0,0 +1,24 @@
+1|1|2|5|2|4|1|0
+2|2|2|5|5|-1|0|1
+3|1|2|6|2|4|1|0
+4|2|2|6|5|8|1|1
+5|3|2|6|6|-1|0|2
+6|1|7|5|7|6|1|0
+7|2|7|5|8|7|1|1
+8|3|7|5|5|-1|0|2
+9|1|7|6|7|6|1|0
+10|2|7|6|8|7|1|1
+11|3|7|6|5|8|1|2
+12|4|7|6|6|-1|0|3
+1|1|2|5|2|4|1|0
+2|2|2|5|5|-1|0|1
+3|1|2|6|2|4|1|0
+4|2|2|6|5|8|1|1
+5|3|2|6|6|-1|0|2
+6|1|7|5|7|6|1|0
+7|2|7|5|8|7|1|1
+8|3|7|5|5|-1|0|2
+9|1|7|6|7|6|1|0
+10|2|7|6|8|7|1|1
+11|3|7|6|5|8|1|2
+12|4|7|6|6|-1|0|3
diff --git a/src/dijkstra/test/issue-353.test.sql b/src/dijkstra/test/issue-353.test.sql
new file mode 100644
index 0000000..f7da593
--- /dev/null
+++ b/src/dijkstra/test/issue-353.test.sql
@@ -0,0 +1,8 @@
+-- test for issue 353
+
+select * from pgr_dijkstra( 'select id, source, target, cost from edge_table',
+ array[2,7], array[5,6]);
+select * from pgr_dijkstra( 'select id, source, target, cost from edge_table',
+ array[2,7], array[17,18]);
+select * from pgr_dijkstra( 'select id, source, target, cost from edge_table',
+array[2,7], array[5,6,17,18]);
diff --git a/src/dijkstra/test/many_to_1.result b/src/dijkstra/test/many_to_1.result
new file mode 100644
index 0000000..b34d93e
--- /dev/null
+++ b/src/dijkstra/test/many_to_1.result
@@ -0,0 +1,35 @@
+1|1|2|2|4|1|0
+2|2|2|5|8|1|1
+3|3|2|6|9|1|2
+4|4|2|9|16|1|3
+5|5|2|4|3|1|4
+6|6|2|3|-1|0|5
+1|1|2|2|2|1|0
+2|2|2|3|-1|0|1
+1|1|2|2|4|1|0
+2|2|2|5|8|1|1
+3|3|2|6|5|1|2
+4|4|2|3|-1|0|3
+1|1|2|2|4|1|0
+2|2|2|5|8|1|1
+3|3|2|6|9|1|2
+4|4|2|9|16|1|3
+5|5|2|4|3|1|4
+6|6|2|3|-1|0|5
+7|1|11|11|13|1|0
+8|2|11|12|15|1|1
+9|3|11|9|16|1|2
+10|4|11|4|3|1|3
+11|5|11|3|-1|0|4
+1|1|2|2|2|1|0
+2|2|2|3|-1|0|1
+3|1|11|11|11|1|0
+4|2|11|6|5|1|1
+5|3|11|3|-1|0|2
+1|1|2|2|4|1|0
+2|2|2|5|8|1|1
+3|3|2|6|5|1|2
+4|4|2|3|-1|0|3
+5|1|11|11|11|1|0
+6|2|11|6|5|1|1
+7|3|11|3|-1|0|2
diff --git a/src/dijkstra/test/many_to_1.test.sql b/src/dijkstra/test/many_to_1.test.sql
new file mode 100644
index 0000000..075aff2
--- /dev/null
+++ b/src/dijkstra/test/many_to_1.test.sql
@@ -0,0 +1,53 @@
+
+
+-- Examples for :ref:`fig1-direct-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], 3
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], 3, false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2], 3
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2], 3, false
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], 3
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], 3, false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], 3
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], 3, false
+ );
+
+
diff --git a/src/dijkstra/test/many_to_many.result b/src/dijkstra/test/many_to_many.result
new file mode 100644
index 0000000..3b463fe
--- /dev/null
+++ b/src/dijkstra/test/many_to_many.result
@@ -0,0 +1,54 @@
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|9|1|2
+4|4|2|3|9|16|1|3
+5|5|2|3|4|3|1|4
+6|6|2|3|3|-1|0|5
+1|1|2|3|2|2|1|0
+2|2|2|3|3|-1|0|1
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|5|1|2
+4|4|2|3|3|-1|0|3
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|9|1|2
+4|4|2|3|9|16|1|3
+5|5|2|3|4|3|1|4
+6|6|2|3|3|-1|0|5
+7|1|2|5|2|4|1|0
+8|2|2|5|5|-1|0|1
+9|1|11|3|11|13|1|0
+10|2|11|3|12|15|1|1
+11|3|11|3|9|16|1|2
+12|4|11|3|4|3|1|3
+13|5|11|3|3|-1|0|4
+14|1|11|5|11|13|1|0
+15|2|11|5|12|15|1|1
+16|3|11|5|9|9|1|2
+17|4|11|5|6|8|1|3
+18|5|11|5|5|-1|0|4
+1|1|2|3|2|2|1|0
+2|2|2|3|3|-1|0|1
+3|1|2|5|2|4|1|0
+4|2|2|5|5|-1|0|1
+5|1|11|3|11|11|1|0
+6|2|11|3|6|5|1|1
+7|3|11|3|3|-1|0|2
+8|1|11|5|11|11|1|0
+9|2|11|5|6|8|1|1
+10|3|11|5|5|-1|0|2
+1|1|2|5|2|4|1|0
+2|2|2|5|5|-1|0|1
+1|1|2|3|2|4|1|0
+2|2|2|3|5|8|1|1
+3|3|2|3|6|5|1|2
+4|4|2|3|3|-1|0|3
+5|1|2|5|2|4|1|0
+6|2|2|5|5|-1|0|1
+7|1|11|3|11|11|1|0
+8|2|11|3|6|5|1|1
+9|3|11|3|3|-1|0|2
+10|1|11|5|11|11|1|0
+11|2|11|5|6|8|1|1
+12|3|11|5|5|-1|0|2
diff --git a/src/dijkstra/test/many_to_many.test.sql b/src/dijkstra/test/many_to_many.test.sql
new file mode 100644
index 0000000..8bd747f
--- /dev/null
+++ b/src/dijkstra/test/many_to_many.test.sql
@@ -0,0 +1,50 @@
+
+
+-- Examples for :ref:`fig1-direct-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3]
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2], array[3], false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2], array[3]
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2], array[3], false
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], array[3,5]
+ );
+
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,11], array[3,5], false
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], array[3,5]
+ );
+
+ SELECT * FROM pgr_dijkstra(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,11], array[3,5], false
+ );
+
+
diff --git a/doc/test/sampledata.data b/src/dijkstra/test/sampledata.data
similarity index 97%
copy from doc/test/sampledata.data
copy to src/dijkstra/test/sampledata.data
index a5e899c..db6f2cb 100644
--- a/doc/test/sampledata.data
+++ b/src/dijkstra/test/sampledata.data
@@ -4,6 +4,7 @@
-- SAMPLE DATA
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
+drop table if exists edge_table;
CREATE TABLE edge_table (
id serial,
@@ -46,6 +47,7 @@ UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
select pgr_createTopology('edge_table',0.001);
+drop table if exists vertex_table;
CREATE TABLE vertex_table (
id serial,
x double precision,
diff --git a/src/dijkstra/test/spd-any-00.data b/src/dijkstra/test/spd-any-00.data
deleted file mode 100644
index 0b883d6..0000000
--- a/src/dijkstra/test/spd-any-00.data
+++ /dev/null
@@ -1,212 +0,0 @@
-BEGIN;
---
--- PostgreSQL database dump
---
-
-SET client_encoding = 'UTF8';
-SET standard_conforming_strings = off;
-SET check_function_bodies = false;
-SET client_min_messages = warning;
-SET escape_string_warning = off;
-
-SET search_path = public, pg_catalog;
-
-SET default_tablespace = '';
-
-SET default_with_oids = false;
-
---
--- Name: edges1; Type: TABLE; Schema: public; Owner: -; Tablespace:
---
-
-DROP TABLE IF EXISTS edges1 CASCADE;
-
-CREATE TABLE edges1 (
- eid integer NOT NULL,
- dir character varying,
- source integer,
- target integer,
- cost double precision,
- reverse_cost double precision,
- x1 double precision,
- y1 double precision,
- x2 double precision,
- y2 double precision,
- to_cost double precision,
- rule text,
- the_geom geometry,
- CONSTRAINT enforce_dims_the_geom CHECK ((st_ndims(the_geom) = 2)),
- CONSTRAINT enforce_geotype_the_geom CHECK (((geometrytype(the_geom) = 'LINESTRING'::text) OR (the_geom IS NULL)))
--- , CONSTRAINT enforce_srid_the_geom CHECK ((st_srid(the_geom) = (0)))
-);
-
-
---
--- Name: restrictions1; Type: TABLE; Schema: public; Owner: -; Tablespace:
---
-
-DROP TABLE IF EXISTS restrictions1 CASCADE;
-
-CREATE TABLE restrictions1 (
- rid integer NOT NULL,
- to_cost double precision,
- teid integer,
- feid integer,
- via text
-);
-
-
---
--- Name: restrictions1_rid_seq; Type: SEQUENCE; Schema: public; Owner: -
---
-
-CREATE SEQUENCE restrictions1_rid_seq
- INCREMENT BY 1
- NO MAXVALUE
- NO MINVALUE
- CACHE 1;
-
-
---
--- Name: restrictions1_rid_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
---
-
-ALTER SEQUENCE restrictions1_rid_seq OWNED BY restrictions1.rid;
-
-
---
--- Name: restrictions1_rid_seq; Type: SEQUENCE SET; Schema: public; Owner: -
---
-
-SELECT pg_catalog.setval('restrictions1_rid_seq', 1, true);
-
-
---
--- Name: restrictions1a; Type: TABLE; Schema: public; Owner: -; Tablespace:
---
-
-DROP TABLE IF EXISTS restrictions1a CASCADE;
-
-CREATE TABLE restrictions1a (
- rid integer,
- to_cost double precision,
- teid integer,
- feid integer,
- via text
-);
-
-
---
--- Name: rid; Type: DEFAULT; Schema: public; Owner: -
---
-
-ALTER TABLE restrictions1 ALTER COLUMN rid SET DEFAULT nextval('restrictions1_rid_seq'::regclass);
-
-
---
--- Data for Name: edges1; Type: TABLE DATA; Schema: public; Owner: -
---
-
-COPY edges1 (eid, dir, source, target, cost, reverse_cost, x1, y1, x2, y2, to_cost, rule, the_geom) FROM stdin WITH NULL '__NULL__';
-1 B 1 2 1 1 2 0 2 1 __NULL__ __NULL__ 010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
-2 TF 2 3 -1 1 2 1 3 1 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
-3 TF 3 4 -1 1 3 1 4 1 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
-4 B 2 7 1 1 2 1 2 2 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
-5 FT 3 8 1 -1 3 1 3 2 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
-6 B 5 6 1 1 0 2 1 2 __NULL__ __NULL__ 01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
-7 B 6 7 1 1 1 2 2 2 __NULL__ __NULL__ 010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
-8 B 7 8 1 1 2 2 3 2 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000004000000000000008400000000000000040
-9 B 8 9 1 1 3 2 4 2 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000004000000000000010400000000000000040
-10 B 7 10 1 1 2 2 2 3 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000004000000000000000400000000000000840
-11 FT 8 11 1 -1 3 2 3 3 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000004000000000000008400000000000000840
-12 FT 10 11 1 -1 2 3 3 3 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000084000000000000008400000000000000840
-13 FT 11 12 1 -1 3 3 4 3 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000084000000000000010400000000000000840
-14 B 10 13 1 1 2 3 2 4 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000084000000000000000400000000000001040
-15 B 9 12 1 1 4 2 4 3 __NULL__ __NULL__ 0102000000020000000000000000001040000000000000004000000000000010400000000000000840
-16 B 4 9 1 1 4 1 4 2 __NULL__ __NULL__ 0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
-\.
-
-
---
--- Data for Name: restrictions1; Type: TABLE DATA; Schema: public; Owner: -
---
-
-COPY restrictions1 (rid, to_cost, teid, feid, via) FROM stdin WITH NULL '__NULL__';
-1 100 7 4 __NULL__
-2 4 8 3 5
-3 100 9 16 __NULL__
-\.
-
-
---
--- Data for Name: restrictions1a; Type: TABLE DATA; Schema: public; Owner: -
---
-
-COPY restrictions1a (rid, to_cost, teid, feid, via) FROM stdin WITH NULL '__NULL__';
-1 100 7 4 __NULL__
-\.
-
-
---
--- Name: edges1_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
---
-
-ALTER TABLE ONLY edges1
- ADD CONSTRAINT edges1_pkey PRIMARY KEY (eid);
-
-
---
--- Name: restrictions1_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
---
-
-ALTER TABLE ONLY restrictions1
- ADD CONSTRAINT restrictions1_pkey PRIMARY KEY (rid);
-
-
---
--- PostgreSQL database dump complete
---
-COMMIT;
-
-/*
-
-select * from turn_restrict_shortest_path(
- 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
- 1, -- edge_id for start
- 0.5, -- midpoint of edge
- 6, -- edge_id of route end
- 0.5, -- midpoint of edge
- true, -- directed graph?
- true, -- has_reverse_cost?
- null); -- no turn restrictions
-
-select * from turn_restrict_shortest_path(
- 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
- 1, -- node_id of start
- 5, -- node_id of end
- true, -- directed graph?
- true, -- has_reverse_cost?
- null); -- no turn restrictions
-
-select * from turn_restrict_shortest_path(
- 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
- 1, -- edge_id for start
- 0.5, -- midpoint of edge
- 6, -- edge_id of route end
- 0.5, -- midpoint of edge
- true, -- directed graph?
- true, -- has_reverse_cost?
- -- include the turn restrictions
- 'select to_cost, teid as target_id, feid||coalesce('',''||via,'''') as via_path from restrictions1');
-
-select * from turn_restrict_shortest_path(
- 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
- 1, -- node_id of start
- 5, -- node_id of end
- true, -- directed graph?
- true, -- has_reverse_cost?
- -- include the turn restrictions
- 'select to_cost, teid as target_id, feid||coalesce('',''||via,'''') as via_path from restrictions1');
-
-*/
-
diff --git a/src/dijkstra/test/spd-any-00.rest b/src/dijkstra/test/spd-any-00.rest
deleted file mode 100644
index f1081c0..0000000
--- a/src/dijkstra/test/spd-any-00.rest
+++ /dev/null
@@ -1,7 +0,0 @@
-0|11|13|1
-1|12|15|1
-2|9|9|1
-3|8|8|1
-4|7|7|1
-5|6|6|1
-6|5|-1|0
diff --git a/src/dijkstra/test/spd-any-00.test b/src/dijkstra/test/spd-any-00.test
deleted file mode 100644
index 8d37fb6..0000000
--- a/src/dijkstra/test/spd-any-00.test
+++ /dev/null
@@ -1,5 +0,0 @@
--- include reverse_costs
--- convert -1 costs to a large number
-
-select * from pgr_dijkstra('select eid as id, source::int4, target::int4, case when cost<=0 then 999 else cost end as cost, case when reverse_cost<=0 then 999 else reverse_cost end as reverse_cost from edges1', 11, 5, false, true);
-
diff --git a/src/dijkstra/test/spd-any-01.rest b/src/dijkstra/test/spd-any-01.rest
deleted file mode 100644
index 80afeab..0000000
--- a/src/dijkstra/test/spd-any-01.rest
+++ /dev/null
@@ -1,5 +0,0 @@
-0|11|11|1
-1|8|8|1
-2|7|7|1
-3|6|6|1
-4|5|-1|0
diff --git a/src/dijkstra/test/spd-any-01.test b/src/dijkstra/test/spd-any-01.test
deleted file mode 100644
index 091ca47..0000000
--- a/src/dijkstra/test/spd-any-01.test
+++ /dev/null
@@ -1,4 +0,0 @@
--- ignore reverse costs
--- eliminate edges with negative costs
-
-select * from pgr_dijkstra('select eid as id, source::int4, target::int4, cost from edges1 where cost>0', 11, 5, false, false);
diff --git a/src/dijkstra/test/spd-any-02.rest b/src/dijkstra/test/spd-any-02.rest
deleted file mode 100644
index 80afeab..0000000
--- a/src/dijkstra/test/spd-any-02.rest
+++ /dev/null
@@ -1,5 +0,0 @@
-0|11|11|1
-1|8|8|1
-2|7|7|1
-3|6|6|1
-4|5|-1|0
diff --git a/src/dijkstra/test/spd-any-02.test b/src/dijkstra/test/spd-any-02.test
deleted file mode 100644
index 9ca08a8..0000000
--- a/src/dijkstra/test/spd-any-02.test
+++ /dev/null
@@ -1,5 +0,0 @@
--- this causes a server crash because of -1 costs
--- code needs to be revised to check for costs < 0 and eliminate these edges
--- should 0.0 costs be allowed??
-select * from pgr_dijkstra('select eid as id, source::int4, target::int4, cost from edges1', 11, 5, false, false);
-
diff --git a/src/dijkstra/test/spd-any-03.rest b/src/dijkstra/test/spd-any-03.rest
deleted file mode 100644
index f777225..0000000
--- a/src/dijkstra/test/spd-any-03.rest
+++ /dev/null
@@ -1,2 +0,0 @@
-0|10|2|1
-1|20|-1|0
diff --git a/src/dijkstra/test/spd-any-03.test b/src/dijkstra/test/spd-any-03.test
deleted file mode 100644
index 07420e2..0000000
--- a/src/dijkstra/test/spd-any-03.test
+++ /dev/null
@@ -1,6 +0,0 @@
-select * from pgr_dijkstra('
- SELECT unnest(array[1,2]) as id,
- unnest(array[10,10]) as source,
- unnest(array[20,20]) as target,
- unnest(array[2,1])::float8 as cost
- '::text, 10, 20, false, false);
diff --git a/src/dijkstra/test/spd-any-04.rest b/src/dijkstra/test/spd-any-04.rest
deleted file mode 100644
index f1081c0..0000000
--- a/src/dijkstra/test/spd-any-04.rest
+++ /dev/null
@@ -1,7 +0,0 @@
-0|11|13|1
-1|12|15|1
-2|9|9|1
-3|8|8|1
-4|7|7|1
-5|6|6|1
-6|5|-1|0
diff --git a/src/dijkstra/test/spd-any-04.test b/src/dijkstra/test/spd-any-04.test
deleted file mode 100644
index 4f94726..0000000
--- a/src/dijkstra/test/spd-any-04.test
+++ /dev/null
@@ -1,5 +0,0 @@
--- include reverse_costs
--- convert -1 costs to a large number
-
-select * from pgr_dijkstra('select eid as id, source::int4, target::int4, cost, reverse_cost from edges1', 11, 5, false, true);
-
diff --git a/src/dijkstra/test/test.conf b/src/dijkstra/test/test.conf
index de15f88..8f2c321 100644
--- a/src/dijkstra/test/test.conf
+++ b/src/dijkstra/test/test.conf
@@ -3,9 +3,26 @@
%main::tests = (
'any' => {
'comment' => 'Dijkstra test for any versions.',
- 'data' => ['spd-any-00.data'],
- 'tests' => [qw(spd-any-00 spd-any-01 spd-any-02 spd-any-03 spd-any-04)]
+ 'data' => ['dijkstra.data', 'sampledata.data'],
+ 'tests' => [qw(
+zero_one_edge_has_rev
+zero_one_edge_no_rev
+zero_one_edge_-1_rev
+1_to_many
+many_to_1
+many_to_many
+dijkstra-v2
+dijkstra-v3
+dijkstra-undi-00
+dijkstra-undi-01
+dijkstra-dir-00
+dijkstra-dir-01
+issue-353
+)],
+ 'nottesting' => [qw(
+)]
},
+
# 'vpg-vpgis' => {}, # for version specific tests
# '8-1' => {}, # for pg 8.x and postgis 1.x
# '9.2-2.1' => {}, # for pg 9.2 and postgis 2.1
diff --git a/src/dijkstra/test/zero_one_edge_-1_rev.result b/src/dijkstra/test/zero_one_edge_-1_rev.result
new file mode 100644
index 0000000..dcad1f7
--- /dev/null
+++ b/src/dijkstra/test/zero_one_edge_-1_rev.result
@@ -0,0 +1,20 @@
+-- 0 edges tests
+-- directed graph
+-- undirected graph
+-- 1 edges tests
+-- edge doesnt have source
+4|2|5|1|-1
+-- directed graph
+-- undirected graph
+-- edge doesnt have target
+3|3|4|-1|-1
+-- directed graph
+-- undirected graph
+-- edge has both
+3|3|4|-1|-1
+-- directed graph
+-- undirected graph
+-- edge has both
+2|2|3|-1|-1
+-- directed graph
+-- undirected graph
diff --git a/src/dijkstra/test/zero_one_edge_-1_rev.test.sql b/src/dijkstra/test/zero_one_edge_-1_rev.test.sql
new file mode 100644
index 0000000..0cc09c2
--- /dev/null
+++ b/src/dijkstra/test/zero_one_edge_-1_rev.test.sql
@@ -0,0 +1,80 @@
+
+\qecho -- 0 edges tests
+
+select id, source, target, cost, -1 as reverse_cost from edge_table where id>18;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id>18 ',3, array[2], false);
+
+
+\qecho -- 1 edges tests
+
+\qecho -- edge doesnt have source
+select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 4 ',3, array[2], false);
+
+\qecho -- edge doesnt have target
+select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3 ',3, array[2], false);
+
+\qecho -- edge has both
+select id, source, target, cost, -1 as reverse_cost from edge_table where id = 3;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',3, array[2], false);
+
+\qecho -- edge has both
+select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',2, 3);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[2], 3);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[2], array[3]);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',2, array[3]);
+
+\qecho -- undirected graph
+
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',2, 3, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[2], 3, false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',array[2], array[3], false);
+select * from pgr_dijkstra('select id, source, target, cost, -1 as reverse_cost from edge_table where id = 2 ',2, array[3], false);
diff --git a/src/dijkstra/test/zero_one_edge_has_rev.result b/src/dijkstra/test/zero_one_edge_has_rev.result
new file mode 100644
index 0000000..9a58e94
--- /dev/null
+++ b/src/dijkstra/test/zero_one_edge_has_rev.result
@@ -0,0 +1,44 @@
+-- 0 edges tests
+-- directed graph
+-- undirected graph
+-- 1 edges tests
+-- edge doesnt have source
+4|2|5|1|1
+-- directed graph
+-- undirected graph
+-- edge doesnt have target
+3|3|4|-1|1
+-- directed graph
+-- undirected graph
+-- edge has both
+3|3|4|-1|1
+-- directed graph
+1|1|3|2|1|0
+2|2|2|-1|0|1
+1|1|3|3|2|1|0
+2|2|3|2|-1|0|1
+1|1|3|2|3|2|1|0
+2|2|3|2|2|-1|0|1
+1|1|2|3|2|1|0
+2|2|2|2|-1|0|1
+-- undirected graph
+1|1|3|2|1|0
+2|2|2|-1|0|1
+1|1|3|3|2|1|0
+2|2|3|2|-1|0|1
+1|1|3|2|3|2|1|0
+2|2|3|2|2|-1|0|1
+1|1|2|3|2|1|0
+2|2|2|2|-1|0|1
+-- edge has both
+3|3|4|-1|1
+-- directed graph
+-- undirected graph
+1|1|2|2|1|0
+2|2|3|-1|0|1
+1|1|2|2|2|1|0
+2|2|2|3|-1|0|1
+1|1|2|3|2|2|1|0
+2|2|2|3|3|-1|0|1
+1|1|3|2|2|1|0
+2|2|3|3|-1|0|1
diff --git a/src/dijkstra/test/zero_one_edge_has_rev.test.sql b/src/dijkstra/test/zero_one_edge_has_rev.test.sql
new file mode 100644
index 0000000..73076c4
--- /dev/null
+++ b/src/dijkstra/test/zero_one_edge_has_rev.test.sql
@@ -0,0 +1,80 @@
+
+\qecho -- 0 edges tests
+
+select id, source, target, cost, reverse_cost from edge_table where id>18;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id>18 ',3, array[2], false);
+
+
+\qecho -- 1 edges tests
+
+\qecho -- edge doesnt have source
+select id, source, target, cost, reverse_cost from edge_table where id = 4;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 4 ',3, array[2], false);
+
+\qecho -- edge doesnt have target
+select id, source, target, cost, reverse_cost from edge_table where id = 3;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 3 ',3, array[2], false);
+
+\qecho -- edge has both
+select id, source, target, cost, reverse_cost from edge_table where id = 3;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',3, array[2], false);
+
+\qecho -- edge has both
+select id, source, target, cost, reverse_cost from edge_table where id = 3;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',2, 3);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[2], 3);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[2], array[3]);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',2, array[3]);
+
+\qecho -- undirected graph
+
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',2, 3, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[2], 3, false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',array[2], array[3], false);
+select * from pgr_dijkstra('select id, source, target, cost, reverse_cost from edge_table where id = 2 ',2, array[3], false);
diff --git a/src/dijkstra/test/zero_one_edge_no_rev.result b/src/dijkstra/test/zero_one_edge_no_rev.result
new file mode 100644
index 0000000..31a2aa6
--- /dev/null
+++ b/src/dijkstra/test/zero_one_edge_no_rev.result
@@ -0,0 +1,20 @@
+-- 0 edges tests
+-- directed graph
+-- undirected graph
+-- 1 edges tests
+-- edge doesnt have source
+4|2|5|1
+-- directed graph
+-- undirected graph
+-- edge doesnt have target
+3|3|4|-1
+-- directed graph
+-- undirected graph
+-- edge has both
+3|3|4|-1
+-- directed graph
+-- undirected graph
+-- edge has both
+2|2|3|-1
+-- directed graph
+-- undirected graph
diff --git a/src/dijkstra/test/zero_one_edge_no_rev.test.sql b/src/dijkstra/test/zero_one_edge_no_rev.test.sql
new file mode 100644
index 0000000..6c758eb
--- /dev/null
+++ b/src/dijkstra/test/zero_one_edge_no_rev.test.sql
@@ -0,0 +1,80 @@
+
+\qecho -- 0 edges tests
+
+select id, source, target, cost from edge_table where id>18;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id>18 ',3, array[2], false);
+
+
+\qecho -- 1 edges tests
+
+\qecho -- edge doesnt have source
+select id, source, target, cost from edge_table where id = 4;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 4 ',3, array[2], false);
+
+\qecho -- edge doesnt have target
+select id, source, target, cost from edge_table where id = 3;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 3 ',3, array[2], false);
+
+\qecho -- edge has both
+select id, source, target, cost from edge_table where id = 3;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',3, 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[3], 2);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[3], array[2]);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',3, array[2]);
+
+\qecho -- undirected graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',3, 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[3], 2, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[3], array[2], false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',3, array[2], false);
+
+\qecho -- edge has both
+select id, source, target, cost from edge_table where id = 2;
+
+\qecho -- directed graph
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',2, 3);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[2], 3);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[2], array[3]);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',2, array[3]);
+
+\qecho -- undirected graph
+
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',2, 3, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[2], 3, false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',array[2], array[3], false);
+select * from pgr_dijkstra('select id, source, target, cost from edge_table where id = 2 ',2, array[3], false);
diff --git a/src/dijkstra/tester/boost_wrapper.cpp b/src/dijkstra/tester/boost_wrapper.cpp
index 6b83226..3eddbef 100644
--- a/src/dijkstra/tester/boost_wrapper.cpp
+++ b/src/dijkstra/tester/boost_wrapper.cpp
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/dijkstra/tester/dijkstra.h b/src/dijkstra/tester/dijkstra.h
index 2c3aa13..ed79dc5 100644
--- a/src/dijkstra/tester/dijkstra.h
+++ b/src/dijkstra/tester/dijkstra.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/driving_distance/CMakeLists.txt b/src/driving_distance/CMakeLists.txt
index c4a8382..c51535e 100644
--- a/src/driving_distance/CMakeLists.txt
+++ b/src/driving_distance/CMakeLists.txt
@@ -1,5 +1,4 @@
SET(PACKAGE_SQL_FILES "")
ADD_SUBDIRECTORY(sql)
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
-#MESSAGE("core/driving_distance: ${PACKAGE_SQL_FILES}")
SUBDIRS(doc src test)
diff --git a/src/driving_distance/doc/dd_alphashape.rst b/src/driving_distance/doc/dd_alphashape.rst
index 1a01926..c4c5d04 100644
--- a/src/driving_distance/doc/dd_alphashape.rst
+++ b/src/driving_distance/doc/dd_alphashape.rst
@@ -13,17 +13,12 @@ pgr_alphaShape
===============================================================================
.. index::
- single: pgr_alphashape(text)
- module: driving_distance
+ single: pgr_alphashape(text,float8)
Name
-------------------------------------------------------------------------------
-``pgr_alphashape`` — Core function for alpha shape computation.
-
-.. note::
-
- This function should not be used directly. Use :ref:`pgr_drivingDistance <pgr_driving_distance>` instead.
+``pgr_alphaShape`` — Core function for alpha shape computation.
Synopsis
@@ -33,7 +28,7 @@ Returns a table with (x, y) rows that describe the vertices of an alpha shape.
.. code-block:: sql
- table() pgr_alphashape(text sql);
+ table() pgr_alphaShape(text sql [, float8 alpha]);
Description
@@ -49,17 +44,21 @@ Description
:x: ``float8`` x-coordinate
:y: ``float8`` y-coordinate
+:alpha: (optional) ``float8`` alpha value. If specified alpha value equals 0 (default), then optimal alpha value is used.
+ For more information, see `CGAL - 2D Alpha Shapes <http://doc.cgal.org/latest/Alpha_shapes_2/group__PkgAlphaShape2.html>`_.
-Returns a vertex record for each row :
+Returns a vertex record for each row:
:x: x-coordinate
:y: y-coordinate
+If a result includes multiple outer/inner rings, return those with separator row (x=NULL and y=NULL).
.. rubric:: History
* Renamed in version 2.0.0
-
+* Added alpha argument with default 0 (use optimal value) in version 2.1.0
+* Supported to return multiple outer/inner ring coordinates with separator row (x=NULL and y=NULL) in version 2.1.0
Examples
-------------------------------------------------------------------------------
@@ -67,23 +66,23 @@ In the alpha shape code we have no way to control the order of the points so the
.. code-block:: sql
- SELECT * FROM pgr_alphashape('SELECT id, x, y FROM vertex_table');
+ SELECT * FROM pgr_alphaShape('SELECT id, x, y FROM vertex_table');
x | y
---+---
+ 2 | 4
+ 0 | 2
2 | 0
4 | 1
4 | 2
4 | 3
- 2 | 4
- 0 | 2
(6 rows)
- SELECT round(st_area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) as st_area
- from (select st_makeline(points order by id) as openline from
- (SELECT st_makepoint(x,y) as points ,row_number() over() AS id
- FROM pgr_alphAShape('SELECT id, x, y FROM vertex_table')
- ) as a) as foo;
+ SELECT round(ST_Area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) AS st_area
+ FROM (SELECT ST_MakeLine(points ORDER BY id) AS openline FROM
+ (SELECT ST_MakePoint(x, y) AS points, row_number() over() AS id
+ FROM pgr_alphaShape('SELECT id, x, y FROM vertex_table')
+ ) AS a) AS foo;
st_area
---------
@@ -91,9 +90,10 @@ In the alpha shape code we have no way to control the order of the points so the
(1 row)
- SELECT * FROM pgr_alphAShape('SELECT id::integer, st_x(the_geom)::float as x, st_y(the_geom)::float as y FROM edge_table_vertices_pgr');
+ SELECT * FROM pgr_alphaShape('SELECT id::integer, ST_X(the_geom)::float AS x, ST_Y(the_geom)::float AS y FROM edge_table_vertices_pgr');
x | y
-----+-----
+ 2 | 4
0.5 | 3.5
0 | 2
2 | 0
@@ -101,18 +101,17 @@ In the alpha shape code we have no way to control the order of the points so the
4 | 2
4 | 3
3.5 | 4
- 2 | 4
(8 rows)
- SELECT round(st_area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) as st_area
- from (select st_makeline(points order by id) as openline from
- (SELECT st_makepoint(x,y) as points ,row_number() over() AS id
- FROM pgr_alphAShape('SELECT id::integer, st_x(the_geom)::float as x, st_y(the_geom)::float as y FROM edge_table_vertices_pgr')
- ) as a) as foo;
+ SELECT round(ST_Area(ST_MakePolygon(ST_AddPoint(foo.openline, ST_StartPoint(foo.openline))))::numeric, 2) AS st_area
+ FROM (SELECT ST_MakeLine(points ORDER BY id) AS openline FROM
+ (SELECT ST_MakePoint(x, y) AS points, row_number() over() AS id
+ FROM pgr_alphaShape('SELECT id::integer, ST_X(the_geom)::float AS x, ST_Y(the_geom)::float AS y FROM edge_table_vertices_pgr')
+ ) AS a) AS foo;
st_area
---------
- 10.00
+ 11.75
(1 row)
diff --git a/src/driving_distance/doc/dd_driving_distance.rst b/src/driving_distance/doc/dd_driving_distance_v2.rst
similarity index 88%
rename from src/driving_distance/doc/dd_driving_distance.rst
rename to src/driving_distance/doc/dd_driving_distance_v2.rst
index 0d0529f..7c71a6c 100644
--- a/src/driving_distance/doc/dd_driving_distance.rst
+++ b/src/driving_distance/doc/dd_driving_distance_v2.rst
@@ -7,24 +7,19 @@
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
-.. _pgr_driving_distance:
+.. _pgr_driving_distance_v2:
-pgr_drivingDistance
+pgr_drivingDistance (V2.0)
===============================================================================
.. index::
- single: pgr_drivingDistance(text,integer,double precision,boolean,boolean)
- module: driving_distance
+ single: drivingDistance(text,integer,double precision,boolean,boolean) -- deprecated
Name
-------------------------------------------------------------------------------
``pgr_drivingDistance`` - Returns the driving distance from a start node.
-.. note::
-
- Requires :ref:`to build pgRouting <build>` with support for Driving Distance.
-
Synopsis
-------------------------------------------------------------------------------
@@ -36,6 +31,14 @@ This function computes a Dijkstra shortest path solution them extracts the cost
pgr_costResult[] pgr_drivingDistance(text sql, integer source, double precision distance,
boolean directed, boolean has_rcost);
+.. warning:: This signature is being deprecated on version 2.1, Please use it
+ without the ``has_rcost`` flag instead:
+
+ ``pgr_drivingDistance(sql, start_v, distance, directed)``
+
+ See :ref:`pgr_driving_distance_v3`
+
+
Description
-------------------------------------------------------------------------------
@@ -90,12 +93,9 @@ Examples
seq | node | cost
-----+------+------
- 0 | 2 | 1
- 1 | 6 | 1
- 2 | 7 | 0
- 3 | 8 | 1
- 4 | 10 | 1
- (5 rows)
+ 0 | 7 | 0
+ 1 | 8 | 1
+ (2 rows)
* With ``reverse_cost``
@@ -110,11 +110,8 @@ Examples
seq | node | cost
-----+------+------
- 0 | 2 | 1
- 1 | 6 | 1
- 2 | 7 | 0
- 3 | 8 | 1
- 4 | 10 | 1
+ 0 | 7 | 0
+ 1 | 8 | 1
(5 rows)
diff --git a/src/driving_distance/doc/dd_driving_distance_v3.rst b/src/driving_distance/doc/dd_driving_distance_v3.rst
new file mode 100644
index 0000000..78b4dd1
--- /dev/null
+++ b/src/driving_distance/doc/dd_driving_distance_v3.rst
@@ -0,0 +1,475 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_driving_distance_v3:
+
+pgr_drivingDistance
+===============================================================================
+
+
+Name
+-------------------------------------------------------------------------------
+
+``pgr_drivingDistance`` - Returns the driving distance from a start node.
+
+
+.. figure:: ../../../doc/src/introduction/images/boost-inside.jpeg
+ :target: http://www.boost.org/libs/graph
+
+ Boost Graph Inside
+
+Synopsis
+-------------------------------------------------------------------------------
+
+Using Dijkstra algorithm, extracts all the nodes that have costs less than or equal to the value ``distance``.
+The edges extracted will conform the corresponding spanning tree.
+
+.. index::
+ single: drivingDistance(edges_sql, start_vid, distance)
+
+.. rubric:: The minimal signature:
+
+.. code-block:: sql
+
+ pgr_drivingDistance(sql text, start_v bigint, distance float8)
+ RETURNS SET OF (seq, node, edge, cost, agg_cost)
+
+
+.. index::
+ single: drivingDistance(edges_sql, start_vid, distance, directed)
+
+.. rubric:: Driving Distance from a single starting point:
+
+.. code-block:: sql
+
+ pgr_drivingDistance(sql text, start_vid bigint, distance float8, directed boolean)
+ RETURNS SET OF (seq, node, edge, cost, agg_cost)
+
+
+.. index::
+ single: drivingDistance(edges_sql, start_vids, distance, directed, equiCost)
+
+.. rubric:: Driving Distance from a multiple starting points:
+
+.. code-block:: sql
+
+ pgr_drivingDistance(sql text, start_vids anyarray, distance float8,
+ directed boolean default true,
+ equicost boolean default false)
+ RETURNS SET OF (seq, start_vid, node, edge, cost, agg_cost)
+
+Description of the SQL query
+-------------------------------------------------------------------------------
+
+:sql: a SQL query, which should return a set of rows with the following columns:
+
+ .. code-block:: sql
+
+ SELECT id, source, target, cost [,reverse_cost] FROM edge_table
+
+
+ :id: ``ANY-INTEGER`` identifier of the edge.
+ :source: ``ANY-INTEGER`` identifier of the source vertex of the edge.
+ :target: ``ANY-INTEGER`` identifier of the target vertex of the edge.
+ :cost: ``ANY-NUMERICAL`` value of the edge traversal cost. A negative cost will prevent the edge (``source``, ``target``) from being inserted in the graph.
+ :reverse_cost: ``ANY-NUMERICAL`` (optional) the value for the reverse traversal of the edge. A negative cost will prevent the edge (``target``, ``source``) from being inserted in the graph.
+
+Where:
+
+:ANY-INTEGER: smallint, int, bigint
+:ANY-NUMERICAL: smallint, int, bigint, real, float
+
+Description of the parameters of the signatures
+-------------------------------------------------------------------------------
+
+:sql: SQL query as decribed above.
+:start_v: ``BIGINT`` id of the starting vertex.
+:start_v: ``array[ANY-INTEGER]`` array of id of starting vertices.
+:distance: ``FLOAT`` Upper limit for the inclusion of the node in the result.
+:directed: ``boolean`` (optional). When ``false`` the graph is considered as Undirected. Default is ``true`` which considers the graph as Directed.
+:equicost: ``boolean`` (optional). When ``true`` the node will only appear in the closest ``start_v`` list. Default is ``false`` which resembles several calls using the single starting point signatures. Tie brakes are arbitrarely.
+
+
+Description of the return values
+-------------------------------------------------------------------------------
+
+Returns set of ``(seq [, start_v], node, edge, cost, agg_cost)``
+
+:seq: ``INT`` row sequence.
+:start_v: ``BIGINT`` id of the starting vertex. Used when multiple starting vetrices are in the query.
+:node: ``BIGINT`` id of the node within the limits from ``start_v``.
+:edge: ``BIGINT`` id of the edge used to arrive to ``node``. ``0`` when the ``node`` is the ``start_v``.
+:cost: ``FLOAT`` cost to traverse ``edge``.
+:agg_cost: ``FLOAT`` total cost from ``start_v`` to ``node``.
+
+
+
+Examples for queries marked as ``directed`` with ``cost`` and ``reverse_cost`` columns
+--------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig1`
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 1 | 1 | 1 | 1
+ 2 | 2 | -1 | 0 | 0
+ 3 | 5 | 4 | 1 | 1
+ 4 | 6 | 8 | 1 | 2
+ 5 | 11 | 12 | 1 | 3
+ 6 | 10 | 10 | 1 | 2
+ 7 | 13 | 14 | 1 | 3
+ 8 | 9 | 9 | 1 | 3
+ 9 | 7 | 6 | 1 | 3
+ 10 | 8 | 7 | 1 | 2
+ (10 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 13, 3
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 2 | 4 | 1 | 3
+ 2 | 5 | 10 | 1 | 2
+ 3 | 6 | 8 | 1 | 3
+ 4 | 11 | 12 | 1 | 2
+ 5 | 10 | 14 | 1 | 1
+ 6 | 12 | 13 | 1 | 3
+ 7 | 13 | -1 | 0 | 0
+ 8 | 8 | 7 | 1 | 3
+ (8 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 1 | 1 | 1 | 1
+ 2 | 2 | 2 | -1 | 0 | 0
+ 3 | 2 | 5 | 4 | 1 | 1
+ 4 | 2 | 6 | 8 | 1 | 2
+ 5 | 2 | 11 | 12 | 1 | 3
+ 6 | 2 | 10 | 10 | 1 | 2
+ 7 | 2 | 13 | 14 | 1 | 3
+ 8 | 2 | 9 | 9 | 1 | 3
+ 9 | 2 | 7 | 6 | 1 | 3
+ 10 | 2 | 8 | 7 | 1 | 2
+ 11 | 13 | 2 | 4 | 1 | 3
+ 12 | 13 | 5 | 10 | 1 | 2
+ 13 | 13 | 6 | 8 | 1 | 3
+ 14 | 13 | 11 | 12 | 1 | 2
+ 15 | 13 | 10 | 14 | 1 | 1
+ 16 | 13 | 12 | 13 | 1 | 3
+ 17 | 13 | 13 | -1 | 0 | 0
+ 18 | 13 | 8 | 7 | 1 | 3
+ (18 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3, equicost:=true
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 1 | 1 | 1 | 1
+ 2 | 2 | 2 | -1 | 0 | 0
+ 3 | 2 | 5 | 4 | 1 | 1
+ 4 | 2 | 6 | 8 | 1 | 2
+ 5 | 2 | 7 | 6 | 1 | 3
+ 6 | 2 | 8 | 7 | 1 | 2
+ 7 | 2 | 9 | 9 | 1 | 3
+ 8 | 2 | 10 | 10 | 1 | 2
+ 9 | 2 | 11 | 12 | 1 | 3
+ 10 | 13 | 13 | -1 | 0 | 0
+ 11 | 13 | 12 | 13 | 1 | 3
+ (11 rows)
+
+
+
+Examples for queries marked as ``undirected`` with ``cost`` and ``reverse_cost`` columns
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig2`
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3, false
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 1 | 1 | 1 | 1
+ 2 | 2 | -1 | 0 | 0
+ 3 | 3 | 2 | 1 | 1
+ 4 | 4 | 3 | 1 | 2
+ 5 | 5 | 4 | 1 | 1
+ 6 | 6 | 8 | 1 | 2
+ 7 | 11 | 12 | 1 | 3
+ 8 | 10 | 10 | 1 | 2
+ 9 | 13 | 14 | 1 | 3
+ 10 | 9 | 16 | 1 | 3
+ 11 | 7 | 6 | 1 | 3
+ 12 | 8 | 7 | 1 | 2
+ (12 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 13, 3, false
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 2 | 4 | 1 | 3
+ 2 | 5 | 10 | 1 | 2
+ 3 | 6 | 11 | 1 | 3
+ 4 | 11 | 12 | 1 | 2
+ 5 | 10 | 14 | 1 | 1
+ 6 | 12 | 13 | 1 | 3
+ 7 | 13 | -1 | 0 | 0
+ 8 | 8 | 7 | 1 | 3
+ (8 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3, false
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 1 | 1 | 1 | 1
+ 2 | 2 | 2 | -1 | 0 | 0
+ 3 | 2 | 3 | 2 | 1 | 1
+ 4 | 2 | 4 | 3 | 1 | 2
+ 5 | 2 | 5 | 4 | 1 | 1
+ 6 | 2 | 6 | 8 | 1 | 2
+ 7 | 2 | 11 | 12 | 1 | 3
+ 8 | 2 | 10 | 10 | 1 | 2
+ 9 | 2 | 13 | 14 | 1 | 3
+ 10 | 2 | 9 | 16 | 1 | 3
+ 11 | 2 | 7 | 6 | 1 | 3
+ 12 | 2 | 8 | 7 | 1 | 2
+ 13 | 13 | 2 | 4 | 1 | 3
+ 14 | 13 | 5 | 10 | 1 | 2
+ 15 | 13 | 6 | 11 | 1 | 3
+ 16 | 13 | 11 | 12 | 1 | 2
+ 17 | 13 | 10 | 14 | 1 | 1
+ 18 | 13 | 12 | 13 | 1 | 3
+ 19 | 13 | 13 | -1 | 0 | 0
+ 20 | 13 | 8 | 7 | 1 | 3
+ (20 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3, false, equicost:=true
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 1 | 1 | 1 | 1
+ 2 | 2 | 2 | -1 | 0 | 0
+ 3 | 2 | 3 | 2 | 1 | 1
+ 4 | 2 | 4 | 3 | 1 | 2
+ 5 | 2 | 5 | 4 | 1 | 1
+ 6 | 2 | 6 | 8 | 1 | 2
+ 7 | 2 | 7 | 6 | 1 | 3
+ 8 | 2 | 8 | 7 | 1 | 2
+ 9 | 2 | 9 | 16 | 1 | 3
+ 10 | 2 | 10 | 10 | 1 | 2
+ 11 | 2 | 11 | 12 | 1 | 3
+ 12 | 13 | 13 | -1 | 0 | 0
+ 13 | 13 | 12 | 13 | 1 | 3
+ (13 rows)
+
+
+
+
+Examples for queries marked as ``directed`` with ``cost`` column
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig3`
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 2 | -1 | 0 | 0
+ 2 | 5 | 4 | 1 | 1
+ 3 | 6 | 8 | 1 | 2
+ 4 | 11 | 11 | 1 | 3
+ 5 | 10 | 10 | 1 | 2
+ 6 | 13 | 14 | 1 | 3
+ 7 | 9 | 9 | 1 | 3
+ (7 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 13, 3
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 13 | -1 | 0 | 0
+ (1 row)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 2 | -1 | 0 | 0
+ 2 | 2 | 5 | 4 | 1 | 1
+ 3 | 2 | 6 | 8 | 1 | 2
+ 4 | 2 | 11 | 11 | 1 | 3
+ 5 | 2 | 10 | 10 | 1 | 2
+ 6 | 2 | 13 | 14 | 1 | 3
+ 7 | 2 | 9 | 9 | 1 | 3
+ 8 | 13 | 13 | -1 | 0 | 0
+ (8 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3, equicost:=true
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 2 | -1 | 0 | 0
+ 2 | 2 | 5 | 4 | 1 | 1
+ 3 | 2 | 6 | 8 | 1 | 2
+ 4 | 2 | 9 | 9 | 1 | 3
+ 5 | 2 | 10 | 10 | 1 | 2
+ 6 | 2 | 11 | 11 | 1 | 3
+ 7 | 13 | 13 | -1 | 0 | 0
+ (7 rows)
+
+
+
+Examples for queries marked as ``undirected`` with ``cost`` column
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig4`
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, false
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 1 | 1 | 1 | 1
+ 2 | 2 | -1 | 0 | 0
+ 3 | 3 | 5 | 1 | 3
+ 4 | 5 | 4 | 1 | 1
+ 5 | 6 | 8 | 1 | 2
+ 6 | 11 | 12 | 1 | 3
+ 7 | 10 | 10 | 1 | 2
+ 8 | 13 | 14 | 1 | 3
+ 9 | 9 | 9 | 1 | 3
+ 10 | 7 | 6 | 1 | 3
+ 11 | 8 | 7 | 1 | 2
+ (11 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 13, 3, false
+ );
+ seq | node | edge | cost | agg_cost
+ -----+------+------+------+----------
+ 1 | 2 | 4 | 1 | 3
+ 2 | 5 | 10 | 1 | 2
+ 3 | 6 | 11 | 1 | 3
+ 4 | 11 | 12 | 1 | 2
+ 5 | 10 | 14 | 1 | 1
+ 6 | 12 | 13 | 1 | 3
+ 7 | 13 | -1 | 0 | 0
+ 8 | 8 | 7 | 1 | 3
+ (8 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3, false
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 1 | 1 | 1 | 1
+ 2 | 2 | 2 | -1 | 0 | 0
+ 3 | 2 | 3 | 5 | 1 | 3
+ 4 | 2 | 5 | 4 | 1 | 1
+ 5 | 2 | 6 | 8 | 1 | 2
+ 6 | 2 | 11 | 12 | 1 | 3
+ 7 | 2 | 10 | 10 | 1 | 2
+ 8 | 2 | 13 | 14 | 1 | 3
+ 9 | 2 | 9 | 9 | 1 | 3
+ 10 | 2 | 7 | 6 | 1 | 3
+ 11 | 2 | 8 | 7 | 1 | 2
+ 12 | 13 | 2 | 4 | 1 | 3
+ 13 | 13 | 5 | 10 | 1 | 2
+ 14 | 13 | 6 | 11 | 1 | 3
+ 15 | 13 | 11 | 12 | 1 | 2
+ 16 | 13 | 10 | 14 | 1 | 1
+ 17 | 13 | 12 | 13 | 1 | 3
+ 18 | 13 | 13 | -1 | 0 | 0
+ 19 | 13 | 8 | 7 | 1 | 3
+ (19 rows)
+
+ SELECT * FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3, false, equicost:=true
+ );
+ seq | from_v | node | edge | cost | agg_cost
+ -----+--------+------+------+------+----------
+ 1 | 2 | 1 | 1 | 1 | 1
+ 2 | 2 | 2 | -1 | 0 | 0
+ 3 | 2 | 3 | 5 | 1 | 3
+ 4 | 2 | 5 | 4 | 1 | 1
+ 5 | 2 | 6 | 8 | 1 | 2
+ 6 | 2 | 7 | 6 | 1 | 3
+ 7 | 2 | 8 | 7 | 1 | 2
+ 8 | 2 | 9 | 9 | 1 | 3
+ 9 | 2 | 10 | 10 | 1 | 2
+ 10 | 2 | 11 | 12 | 1 | 3
+ 11 | 13 | 13 | -1 | 0 | 0
+ 12 | 13 | 12 | 13 | 1 | 3
+ (12 rows)
+
+
+
+The queries use the :ref:`sampledata` network.
+
+
+
+.. rubric:: History
+
+* Renamed in version 2.0.0
+* Added functionality in version 2.1
+
+
+See Also
+-------------------------------------------------------------------------------
+
+* :ref:`pgr_alphashape` - Alpha shape computation
+* :ref:`pgr_points_as_polygon` - Polygon around set of points
+
+.. rubric:: Indices and tables
+
+* :ref:`genindex`
+* :ref:`search`
+
diff --git a/src/driving_distance/doc/dd_points_as_polygon.rst b/src/driving_distance/doc/dd_points_as_polygon.rst
index 48c52af..e363efc 100644
--- a/src/driving_distance/doc/dd_points_as_polygon.rst
+++ b/src/driving_distance/doc/dd_points_as_polygon.rst
@@ -13,8 +13,7 @@ pgr_pointsAsPolygon
===============================================================================
.. index::
- single: pgr_pointsAsPolygon(text)
- module: driving_distance
+ single: pgr_pointsAsPolygon(text,float8)
Name
-------------------------------------------------------------------------------
@@ -25,11 +24,11 @@ Name
Synopsis
-------------------------------------------------------------------------------
-Returns the alpha shape as polygon geometry.
+Returns the alpha shape as (multi)polygon geometry.
.. code-block:: sql
- geometry pgr_pointsAsPolygon(text sql);
+ geometry pgr_pointsAsPolygon(text sql [, float8 alpha]);
Description
@@ -45,18 +44,22 @@ Description
:x: ``float8`` x-coordinate
:y: ``float8`` y-coordinate
+:alpha: (optional) ``float8`` alpha value. If specified alpha value equals 0 (default), then optimal alpha value is used.
+ For more information, see `CGAL - 2D Alpha Shapes <http://doc.cgal.org/latest/Alpha_shapes_2/group__PkgAlphaShape2.html>`_.
-Returns a polygon geometry.
+Returns a (multi)polygon geometry (with holes).
.. rubric:: History
* Renamed in version 2.0.0
+* Added alpha argument with default 0 (use optimal value) in version 2.1.0
+* Supported to return a (multi)polygon geometry (with holes) in version 2.1.0
Examples
-------------------------------------------------------------------------------
-In the following query there is not way to control which point in the polygon is the first in the list, so you may get similar but different results than the following which are also correct. Each of the pgr_pointsAsPolygon queries below is followed by one the compute the area of the polygon. This area should remain constant regardles of the order of the points making up the polygon.
+In the following query there is no way to control which point in the polygon is the first in the list, so you may get similar but different results than the following which are also correct. Each of the pgr_pointsAsPolygon queries below is followed by one the compute the area of the polygon. This area should remain constant regardles of the order of the points making up the polygon.
.. code-block:: sql
@@ -64,10 +67,10 @@ In the following query there is not way to control which point in the polygon is
st_astext
----------------------------------------
- POLYGON((2 0,4 1,4 2,4 3,2 4,0 2,2 0))
+ POLYGON((2 4,4 3,4 2,4 1,2 0,0 2,2 4))
(1 row)
- SELECT round(ST_Area(pgr_pointsAsPolygon('SELECT id, x, y FROM vertex_table'))::numeric, 2) as st_area;
+ SELECT round(ST_Area(pgr_pointsAsPolygon('SELECT id, x, y FROM vertex_table'))::numeric, 2) AS st_area;
st_area
---------
@@ -75,15 +78,15 @@ In the following query there is not way to control which point in the polygon is
(1 row)
- SELECT ST_ASText(pgr_pointsASPolygon('SELECT id::integer, st_x(the_geom)::float as x, st_y(the_geom)::float as y
- FROM edge_table_vertices_pgr'));
+ SELECT ST_AsText(pgr_pointsAsPolygon('SELECT id::integer, ST_X(the_geom)::float AS x, ST_Y(the_geom)::float AS y
+ FROM edge_table_vertices_pgr'));
st_astext
----------------------------------------------------------
- POLYGON((0.5 3.5,0 2,2 0,4 1,4 2,4 3,3.5 4,2 4,0.5 3.5))
+ POLYGON((2 4,3.5 4,4 3,4 2,4 1,2 0,0 2,0.5 3.5,2 4))
(1 row)
- SELECT round(ST_Area(pgr_pointsASPolygon('SELECT id::integer, st_x(the_geom)::float as x, st_y(the_geom)::float as y
- FROM edge_table_vertices_pgr'))::numeric, 2) as st_area;
+ SELECT round(ST_Area(pgr_pointsAsPolygon('SELECT id::integer, ST_X(the_geom)::float AS x, ST_Y(the_geom)::float AS y
+ FROM edge_table_vertices_pgr'))::numeric, 2) AS st_area;
st_area
---------
diff --git a/src/driving_distance/doc/index.rst b/src/driving_distance/doc/index.rst
index 526ae94..b3c3184 100644
--- a/src/driving_distance/doc/index.rst
+++ b/src/driving_distance/doc/index.rst
@@ -1,26 +1,44 @@
-..
+..
****************************************************************************
pgRouting Manual
Copyright(c) pgRouting Contributors
- This documentation is licensed under a Creative Commons Attribution-Share
+ This documentation is licensed under a Creative Commons Attribution-Share
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
-.. _dd_index:
+.. _pgr_driving_distance:
-With Driving Distance Enabled
+Driving Distance
===============================================================================
-Driving distance related Functions
- - :ref:`pgr_driving_distance` - Driving Distance
- - :ref:`pgr_alphaShape` - Alpha shape computation
- - :ref:`pgr_points_as_polygon` - Polygon around set of points
-
+Version 2.0 (deprecated)
+------------------------
+
+ - :ref:`pgr_driving_distance<pgr_driving_distance_v2>` - Driving Distance
+
+
+Version 2.1
+------------------
+
+ - :ref:`pgr_driving_distance<pgr_driving_distance_v3>` - Driving Distance
+
+
+.. _pgr_driving_distance_post:
+
+Driving Distance post-processing
+===============================================================================
+
+ - :ref:`pgr_alphaShape` - Alpha shape computation
+ - :ref:`pgr_points_as_polygon` - Polygon around set of points
+
+
.. toctree::
:hidden:
- pgr_drivingDistance - Driving Distance <dd_driving_distance>
- pgr_alphaShape - Alpha shape computation <dd_alphashape>
- pgr_pointsAsPolygon - Polygon around set of points <dd_points_as_polygon>
+ ./dd_driving_distance_v2.rst
+ ./dd_driving_distance_v3.rst
+ ./dd_alphashape.rst
+ ./dd_points_as_polygon.rst
+
diff --git a/src/driving_distance/sql/routing_dd.sql b/src/driving_distance/sql/routing_dd.sql
index 711936c..4d2bafc 100644
--- a/src/driving_distance/sql/routing_dd.sql
+++ b/src/driving_distance/sql/routing_dd.sql
@@ -14,67 +14,176 @@
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--
-----------------------------------------------------------------------
-- Core function for driving distance.
-- The sql should return edge and vertex ids.
-----------------------------------------------------------------------
+/*
CREATE OR REPLACE FUNCTION pgr_drivingDistance(sql text, source_id integer, distance float8, directed boolean, has_reverse_cost boolean)
- RETURNS SETOF pgr_costResult
+ RETURNS SETOF pgr_costResultBig
AS '$libdir/librouting_dd', 'driving_distance'
LANGUAGE c IMMUTABLE STRICT;
-
+*/
+CREATE OR REPLACE FUNCTION _pgr_drivingDistance(sql text, start_v bigint, distance float8, directed boolean, has_rcost boolean,
+ OUT seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ '$libdir/librouting-2.1', 'driving_distance'
+ LANGUAGE c IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION _pgr_drivingDistance(sql text, start_v anyarray, distance float8, directed boolean, equicost boolean, has_rcost boolean,
+ OUT seq integer, OUT start_v bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ '$libdir/librouting-2.1', 'driving_many_to_dist'
+ LANGUAGE c IMMUTABLE STRICT;
+
+
+-- OLD SIGNATURE
+CREATE OR REPLACE FUNCTION pgr_drivingDistance(sql text, source bigint, distance float8, directed boolean, has_rcost boolean)
+ RETURNS SETOF pgr_costresult AS
+ $BODY$
+ DECLARE
+ has_reverse boolean;
+ BEGIN
+ -- old signature, things are int and float8 only
+ has_reverse =_pgr_parameter_check('driving', sql, false);
+
+ if (has_reverse != has_rcost) then
+ if (has_reverse) then --raise NOTICE 'has_rcost set to false but reverse_cost column found, Ignoring';
+ else raise EXCEPTION 'has_rcost set to true but reverse_cost not found';
+ end if;
+ end if;
+
+ return query SELECT seq-1 as seq, node::integer as id1, edge::integer as id2, agg_cost as cost
+ FROM _pgr_drivingDistance(sql, source, distance, directed, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+
+CREATE OR REPLACE FUNCTION pgr_drivingDistance(sql text, start_v bigint, distance float8,
+ OUT seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ has_rcost =_pgr_parameter_check('driving', sql, true);
+ return query SELECT *
+ FROM _pgr_drivingDistance(sql, start_v, distance, true, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+
+CREATE OR REPLACE FUNCTION pgr_drivingDistance(sql text, start_v bigint, distance float8, directed boolean,
+ OUT seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ has_rcost =_pgr_parameter_check('driving', sql, true);
+ return query SELECT *
+ FROM _pgr_drivingDistance(sql, start_v, distance, directed, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+CREATE OR REPLACE FUNCTION pgr_drivingDistance(sql text, start_v anyarray, distance float8, directed boolean default true, equicost boolean default false,
+ OUT seq integer, OUT from_v bigint, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ has_rcost =_pgr_parameter_check('driving', sql, true);
+ return query SELECT *
+ FROM _pgr_drivingDistance(sql, start_v, distance, directed, equicost, has_rcost);
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+
+
+
-----------------------------------------------------------------------
-- Core function for alpha shape computation.
-- The sql should return vertex ids and x,y values. Return ordered
-- vertex ids.
-----------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION pgr_alphashape(sql text, OUT x float8, OUT y float8)
+CREATE OR REPLACE FUNCTION pgr_alphashape(sql text, alpha float8 DEFAULT 0, OUT x float8, OUT y float8)
RETURNS SETOF record
- AS '$libdir/librouting_dd', 'alphashape'
+ AS '$libdir/librouting-2.1', 'alphashape'
LANGUAGE c IMMUTABLE STRICT;
----------------------------------------------------------
-- Draws an alpha shape around given set of points.
-- ** This should be rewritten as an aggregate. **
----------------------------------------------------------
-CREATE OR REPLACE FUNCTION pgr_pointsAsPolygon(query varchar)
+CREATE OR REPLACE FUNCTION pgr_pointsAsPolygon(query varchar, alpha float8 DEFAULT 0)
RETURNS geometry AS
$$
DECLARE
r record;
- path_result record;
- i int;
+ geoms geometry[];
+ vertex_result record;
+ i int;
+ n int;
+ spos int;
q text;
x float8[];
y float8[];
- BEGIN
- i := 1;
- q := 'SELECT ST_GeometryFromText(''POLYGON((';
+ BEGIN
+ geoms := array[]::geometry[];
+ i := 1;
- FOR path_result IN EXECUTE 'SELECT x, y FROM pgr_alphashape('''|| query || ''')'
+ FOR vertex_result IN EXECUTE 'SELECT x, y FROM pgr_alphashape('''|| query || ''', ' || alpha || ')'
LOOP
- x[i] = path_result.x;
- y[i] = path_result.y;
+ x[i] = vertex_result.x;
+ y[i] = vertex_result.y;
i := i+1;
END LOOP;
- q := q || x[1] || ' ' || y[1];
- i := 2;
+ n := i;
+ IF n = 1 THEN
+ RAISE NOTICE 'n = 1';
+ RETURN NULL;
+ END IF;
- WHILE x[i] IS NOT NULL
- LOOP
- q := q || ', ' || x[i] || ' ' || y[i];
- i := i + 1;
+ spos := 1;
+ q := 'SELECT ST_GeometryFromText(''POLYGON((';
+ FOR i IN 1..n LOOP
+ IF x[i] IS NULL AND y[i] IS NULL THEN
+ q := q || ', ' || x[spos] || ' ' || y[spos] || '))'',0) AS geom;';
+ EXECUTE q INTO r;
+ geoms := geoms || array[r.geom];
+ q := '';
+ ELSE
+ IF q = '' THEN
+ spos := i;
+ q := 'SELECT ST_GeometryFromText(''POLYGON((';
+ END IF;
+ IF i = spos THEN
+ q := q || x[spos] || ' ' || y[spos];
+ ELSE
+ q := q || ', ' || x[i] || ' ' || y[i];
+ END IF;
+ END IF;
END LOOP;
- q := q || ', ' || x[1] || ' ' || y[1] || '))'',0) AS geom';
-
- EXECUTE q INTO r;
- RETURN r.geom;
+ RETURN ST_BuildArea(ST_Collect(geoms));
END;
$$
LANGUAGE 'plpgsql' VOLATILE STRICT;
diff --git a/src/driving_distance/src/CMakeLists.txt b/src/driving_distance/src/CMakeLists.txt
index a43056d..5292f1a 100644
--- a/src/driving_distance/src/CMakeLists.txt
+++ b/src/driving_distance/src/CMakeLists.txt
@@ -1,16 +1,10 @@
-SET(LIBRARY_OUTPUT_PATH ../../../lib/)
-LINK_LIBRARIES(${CGAL_LIBRARIES} ${GMP_LIBRARIES} ${BOOST_THREAD_LIBRARIES})
+ADD_LIBRARY(driving_distance OBJECT
+ alpha.c
+ alpha_drivedist.cpp
-ADD_LIBRARY(routing_dd ${LIBRARY_MODE_TARGET} alpha.c alpha_drivedist.cpp alpha.h boost_drivedist.cpp drivedist.c drivedist.h)
+ boost_interface_drivedist.cpp
-IF(WIN32)
- SET_TARGET_PROPERTIES(routing_dd PROPERTIES COMPILE_FLAGS "-DBOOST_THREAD_USE_LIB -DBoost_USE_STATIC_LIBS -DBOOST_USE_WINDOWS_H")
-ENDIF(WIN32)
+ drivedist.c
+ many_to_dist_driving_distance.c
+ )
-if(APPLE)
- set_target_properties(routing_dd
- PROPERTIES
- LINK_FLAGS "-bundle_loader ${POSTGRESQL_EXECUTABLE} -bundle")
-endif(APPLE)
-
-INSTALL(TARGETS routing_dd DESTINATION ${LIBRARY_INSTALL_PATH})
diff --git a/src/driving_distance/src/alpha.c b/src/driving_distance/src/alpha.c
index fda2d43..0d18ee0 100644
--- a/src/driving_distance/src/alpha.c
+++ b/src/driving_distance/src/alpha.c
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -33,7 +33,7 @@
#include "fmgr.h"
-#ifdef PG_MODULE_MAGIC
+#ifndef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
@@ -169,7 +169,7 @@ fetch_vertex(HeapTuple *tuple, TupleDesc *tupdesc,
target_vertex->y = DatumGetFloat8(binval);
}
-static int compute_alpha_shape(char* sql, vertex_t **res, int *res_count)
+static int compute_alpha_shape(char* sql, float8 alpha, vertex_t **res, int *res_count)
{
int SPIcode;
@@ -273,7 +273,7 @@ static int compute_alpha_shape(char* sql, vertex_t **res, int *res_count)
profstop("extract", prof_extract);
profstart(prof_alpha);
- ret = alpha_shape(vertices, total_tuples, res, res_count, &err_msg);
+ ret = alpha_shape(vertices, total_tuples, alpha, res, res_count, &err_msg);
profstop("alpha", prof_alpha);
profstart(prof_store);
@@ -302,7 +302,6 @@ Datum alphashape(PG_FUNCTION_ARGS)
{
MemoryContext oldcontext;
int res_count;
- int ret;
// XXX profiling messages are not thread safe
profstart(prof_total);
@@ -314,8 +313,8 @@ Datum alphashape(PG_FUNCTION_ARGS)
/* switch to memory context appropriate for multiple function calls */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- ret = compute_alpha_shape(text2char(PG_GETARG_TEXT_P(0)),
- &res, &res_count);
+ compute_alpha_shape(text2char(PG_GETARG_TEXT_P(0)),
+ PG_GETARG_FLOAT8(1), &res, &res_count);
/* total number of tuples to be returned */
DBG("Conting tuples number\n");
@@ -352,6 +351,8 @@ Datum alphashape(PG_FUNCTION_ARGS)
Datum result;
Datum *values;
char* nulls;
+ double x;
+ double y;
/* This will work for some compilers. If it crashes with segfault, try to change the following block with this one
@@ -369,10 +370,22 @@ Datum alphashape(PG_FUNCTION_ARGS)
values = palloc(2 * sizeof(Datum));
nulls = palloc(2 * sizeof(char));
- values[0] = Float8GetDatum(res[call_cntr].x);
- nulls[0] = ' ';
- values[1] = Float8GetDatum(res[call_cntr].y);
- nulls[1] = ' ';
+ x = res[call_cntr].x;
+ y = res[call_cntr].y;
+ if (x == DBL_MAX && y == DBL_MAX)
+ {
+ values[0] = 0;
+ values[1] = 0;
+ nulls[0] = 'n';
+ nulls[1] = 'n';
+ }
+ else
+ {
+ values[0] = Float8GetDatum(x);
+ values[1] = Float8GetDatum(y);
+ nulls[0] = ' ';
+ nulls[1] = ' ';
+ }
DBG("Heap making\n");
diff --git a/src/driving_distance/src/alpha.h b/src/driving_distance/src/alpha.h
index 467fdb4..3ee9c8e 100644
--- a/src/driving_distance/src/alpha.h
+++ b/src/driving_distance/src/alpha.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -25,7 +25,7 @@
#define ELOG_H
#endif
#include "postgres.h"
-#include "dijkstra.h"
+#include "../../common/src/pgr_types.h"
typedef struct vertex
{
@@ -39,7 +39,7 @@ extern "C"
{
#endif
- int alpha_shape(vertex_t *vertices, unsigned int count,
+ int alpha_shape(vertex_t *vertices, unsigned int count, double alpha,
vertex_t **res, int *res_count, char **err_msg);
#ifdef __cplusplus
diff --git a/src/driving_distance/src/alpha_drivedist.cpp b/src/driving_distance/src/alpha_drivedist.cpp
index 4b6c2e4..5167ac3 100644
--- a/src/driving_distance/src/alpha_drivedist.cpp
+++ b/src/driving_distance/src/alpha_drivedist.cpp
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*
* As a special exception, you have permission to link this program
@@ -45,9 +45,11 @@ namespace boost {
#include <vector>
#include <list>
+#include <cmath>
#include "alpha.h"
+#include <CGAL/Polygon_2.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_2.h>
#include <CGAL/Triangulation_hierarchy_vertex_base_2.h>
@@ -58,13 +60,15 @@ namespace boost {
#include <CGAL/Alpha_shape_face_base_2.h>
#include <CGAL/Alpha_shape_vertex_base_2.h>
+
typedef double coord_type;
typedef CGAL::Simple_cartesian<coord_type> SC;
typedef CGAL::Filtered_kernel<SC> K;
-
typedef K::Point_2 Point;
typedef K::Segment_2 Segment;
+typedef K::Vector_2 Vector;
+typedef CGAL::Polygon_2<K> Polygon_2;
typedef CGAL::Alpha_shape_vertex_base_2<K> Avb;
typedef CGAL::Triangulation_hierarchy_vertex_base_2<Avb> Av;
@@ -85,24 +89,84 @@ typedef Alpha_shape_2::Alpha_shape_edges_iterator Alpha_shape_edges_iterator;
//---------------------------------------------------------------------
+double get_angle(Point p, Point q, Point r)
+{
+ double m_pi(3.14159265358979323846);
+ Vector v1(q, p);
+ Vector v2(q, r);
+ double cross = v1.x() * v2.y() - v1.y() * v2.x();
+ double dot = v1.x() * v2.x() + v1.y() * v2.y();
+ double angle = atan2(cross, dot);
+ if (angle < 0.0) {
+ angle += 2 * m_pi;
+ }
+ return angle;
+}
+
+size_t prev_size = 0;
void find_next_edge(Segment s, std::vector<Segment>& segments,
- std::vector<Segment>& res)
+ std::set<int>& unusedIndexes, std::vector<Polygon_2>& rings)
{
- if(res.size() == segments.size())
+ if(unusedIndexes.empty()
+ || prev_size == unusedIndexes.size())
+ {
return;
-
- res.push_back(s);
-
+ }
+
+ prev_size = unusedIndexes.size();
+
+ Point start = s.source();
Point end = s.target();
+ rings.back().push_back(end);
- for(int i=0;i < segments.size(); i++)
+ std::vector<int> nextIndexes;
+ for(unsigned int i = 0;i < segments.size(); i++)
+ {
+ if (unusedIndexes.find(i) != unusedIndexes.end())
{
Point source = segments.at(i).source();
if(source == end)
- {
- find_next_edge(segments.at(i), segments, res);
- }
+ {
+ nextIndexes.push_back(i);
+ }
+ }
+ }
+ if (nextIndexes.size() == 1)
+ {
+ int i = nextIndexes.at(0);
+ unusedIndexes.erase(i);
+ find_next_edge(segments.at(i), segments, unusedIndexes, rings);
+ }
+ else if (nextIndexes.size() > 1)
+ {
+ std::vector< std::pair<double, int> > nextAngles;
+ for (unsigned int i = 0; i < nextIndexes.size(); i++)
+ {
+ int j = nextIndexes.at(i);
+ Point target = segments.at(j).target();
+ double angle = get_angle(start, end, target);
+ nextAngles.push_back(std::pair<double, int>(angle, j));
+ }
+ std::sort(nextAngles.begin(), nextAngles.end());
+ int i = nextAngles.begin()->second;
+ unusedIndexes.erase(i);
+ find_next_edge(segments.at(i), segments, unusedIndexes, rings);
+ }
+
+ if (!unusedIndexes.empty())
+ {
+ for (unsigned int i = 0; i < segments.size(); i++)
+ {
+ if (unusedIndexes.find(i) != unusedIndexes.end())
+ {
+ Polygon_2 ring;
+ ring.push_back(segments.at(i).source());
+ rings.push_back(ring);
+ unusedIndexes.erase(i);
+ find_next_edge(segments.at(i), segments, unusedIndexes, rings);
+ }
}
+ }
}
template <class OutputIterator>
@@ -119,7 +183,7 @@ alpha_edges( const Alpha_shape_2& A,
}
-int alpha_shape(vertex_t *vertices, unsigned int count,
+int alpha_shape(vertex_t *vertices, unsigned int count, double alpha,
vertex_t **res, int *res_count, char **err_msg)
{
std::list<Point> points;
@@ -127,41 +191,85 @@ int alpha_shape(vertex_t *vertices, unsigned int count,
//std::copy(begin(vertices), end(vertices), std::back_inserter(points));
for (std::size_t j = 0; j < count; ++j)
- {
- Point p(vertices[j].x, vertices[j].y);
- points.push_back(p);
- }
+ {
+ Point p(vertices[j].x, vertices[j].y);
+ points.push_back(p);
+ }
Alpha_shape_2 A(points.begin(), points.end(),
coord_type(10000),
- Alpha_shape_2::GENERAL);
+ Alpha_shape_2::REGULARIZED);
std::vector<Segment> segments;
- std::vector<Segment> result;
-
- Alpha_shape_2::Alpha_shape_vertices_iterator vit;
- Alpha_shape_2::Vertex_handle vertex;
- Alpha_shape_2::Alpha_shape_edges_iterator eit;
- Alpha_shape_2::Edge edge;
- Alpha_shape_2::Face_iterator fit;
- Alpha_shape_2::Face_handle face;
+// std::vector<Segment> result;
+
+// Alpha_shape_2::Alpha_shape_vertices_iterator vit;
+// Alpha_shape_2::Vertex_handle vertex;
+// Alpha_shape_2::Alpha_shape_edges_iterator eit;
+// Alpha_shape_2::Edge edge;
+// Alpha_shape_2::Face_iterator fit;
+// Alpha_shape_2::Face_handle face;
- A.set_alpha(*A.find_optimal_alpha(1)*6);
+ if (alpha <= 0.0)
+ {
+ alpha = *A.find_optimal_alpha(1);
+ }
+ A.set_alpha(alpha);
alpha_edges( A, std::back_inserter(segments));
- Segment s = segments.at(0);
- find_next_edge(s, segments, result);
+// Segment s = segments.at(0);
+// find_next_edge(s, segments, result);
+ if (segments.empty())
+ {
+ *res = NULL;
+ *res_count = 0;
+ }
+ else
+ {
+ std::set<int> unusedIndexes;
+ for (unsigned int i = 0; i < segments.size(); i++)
+ {
+ unusedIndexes.insert(i);
+ }
+
+ std::vector<Polygon_2> rings;
+ Polygon_2 ring;
+ ring.push_back(segments.at(0).source());
+ rings.push_back(ring);
+ unusedIndexes.erase(0);
+ find_next_edge(segments.at(0), segments, unusedIndexes, rings);
- *res = (vertex_t *) malloc(sizeof(vertex_t) * (result.size() + 1));
- *res_count = result.size();
+ int result_count = 0;
+ for (unsigned int i = 0; i < rings.size(); i++)
+ {
+ Polygon_2 ring = rings.at(i);
+ result_count += ring.size();
+ }
+ result_count += rings.size() - 1;
+ *res = (vertex_t *) malloc(sizeof(vertex_t) * result_count);
+ *res_count = result_count;
- for(int i=0;i < result.size(); i++)
+ int idx = 0;
+ for (unsigned int i = 0; i < rings.size(); i++)
{
- (*res)[i].x = result.at(i).target().x();
- (*res)[i].y = result.at(i).target().y();
+ if (i > 0)
+ {
+ (*res)[idx].x = DBL_MAX;
+ (*res)[idx].y = DBL_MAX;
+ idx++;
+ }
+ Polygon_2 ring = rings.at(i);
+ for(unsigned int j = 0; j < ring.size(); j++)
+ {
+ Point point = ring.vertex(j);
+ (*res)[idx].x = point.x();
+ (*res)[idx].y = point.y();
+ idx++;
+ }
}
+ }
return EXIT_SUCCESS;
}
diff --git a/src/driving_distance/src/boost_drivedist.cpp b/src/driving_distance/src/boost_drivedist.cpp
deleted file mode 100644
index cfa00b5..0000000
--- a/src/driving_distance/src/boost_drivedist.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Drivedist algorithm for PostgreSQL
- *
- * Copyright (c) 2006 Mario H. Basa, Orkney, Inc.
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-// Include C header first for windows build issue
-#include <exception>
-#include <math.h>
-#include "drivedist.h"
-
-#include <boost/config.hpp>
-
-#include <boost/graph/graph_traits.hpp>
-#include <boost/graph/adjacency_list.hpp>
-#include <boost/graph/dijkstra_shortest_paths.hpp>
-
-using namespace std;
-using namespace boost;
-
-#undef DEBUG
-//#define DEBUG
-
-#ifdef DEBUG
-#include <stdio.h>
-static FILE *dbg;
-#define DBG(format, arg...) \
- dbg = fopen("/tmp/sew-debug", "a"); \
- if (dbg) { \
- fprintf(dbg, format, ## arg); \
- fclose(dbg); \
- }
-#else
-#define DBG(format, arg...) do { ; } while (0)
-#endif
-
-
-// Maximal number of nodes in the path (to avoid infinite loops)
-#define MAX_NODES 1000000
-
-struct Edge
-{
- int id;
- float8 cost;
-};
-
-struct Vertex
-{
- int id;
- int edge_id;
-};
-
-template <class G, class E>
-static void
-graph_add_edge(G &graph, int id, int source, int target, float8 cost)
-{
- E e;
- bool inserted;
-
- if (cost < 0) // edges are not inserted in the graph if cost is negative
- return;
-
- DBG("Calling add_edge id: %d\n", id);
- tie(e, inserted) = add_edge(source, target, graph);
-
- graph[e].cost = cost;
- graph[e].id = id;
-
- DBG("creating sorce and target vertex\n");
- typedef typename graph_traits<G>::vertex_descriptor Vertex;
- Vertex s = vertex(source, graph);
- Vertex t = vertex(target, graph);
-
- DBG("updating graph\n");
- graph[s].id = source;
- graph[t].id = target;
- graph[s].edge_id = id;
- graph[t].edge_id = id;
-
-}
-
-int
-boost_dijkstra_dist(edge_t *edges, unsigned int count, int source_vertex_id,
- double rdistance, bool directed, bool has_reverse_cost,
- path_element_t **path, int *path_count, char **err_msg)
-{
- typedef adjacency_list < listS, vecS, directedS, Vertex, Edge > graph_t;
- typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
- typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
-
- // the maximum number of edges given V nodes if
- // E = (V**2 - V)/2 === V**2 - V -2E = 0
- // solving the quadradic equation
- // V = (2E + sqrt(8E + 1)) / 2
- const unsigned int num_nodes = (2.0*count + sqrt(8.0*count + 1.0)) / 2.0;
-try {
-
- DBG("Creating graph\n");
- graph_t graph( num_nodes );
-
- //property_map<graph_t, edge_weight_t>::type weightmap =
- // get(edge_weight, graph);
-
- DBG("Adding %d edges to graph.\n", count);
- for (std::size_t j = 0; j < count; ++j)
- {
- graph_add_edge<graph_t, edge_descriptor>
- (graph, edges[j].id, edges[j].source,
- edges[j].target, edges[j].cost);
-
- if (!directed || (directed && has_reverse_cost))
- {
- if (has_reverse_cost)
- {
- graph_add_edge<graph_t, edge_descriptor>
- (graph, edges[j].id, edges[j].target,
- edges[j].source, edges[j].reverse_cost);
- }
- else
- {
- graph_add_edge<graph_t, edge_descriptor>
- (graph, edges[j].id, edges[j].target,
- edges[j].source, edges[j].cost);
- }
- }
- }
-
- DBG("Geting source_vertex from graph.\n");
- vertex_descriptor source_vertex = vertex( source_vertex_id, graph );
-
- DBG("Allocating predecessors and distances vectors for %d vertices.\n", num_vertices(graph));
- std::vector<vertex_descriptor> predecessors(num_vertices(graph));
- std::vector<float8> distances(num_vertices(graph));
-
- DBG("Calling dijkstra_shortest_paths()\n");
- dijkstra_shortest_paths(graph, source_vertex,
- predecessor_map(&predecessors[0])
- .weight_map(get(&Edge::cost, graph))
- .distance_map(&distances[0]));
-
- DBG("Back from dijkstra_shortest_paths, creating path_vector.\n");
- graph_traits < graph_t >::vertex_iterator vi, vend;
- vector<path_element> path_vector;
- int j=0;
-
- for(tie(vi, vend) = vertices(graph); vi != vend; vi++) {
-
- if( (double)distances[*vi] <= rdistance ) {
-
- path_element pe;
-
- graph_traits<graph_t>::vertex_descriptor s;
-
- s = vertex(*vi, graph);
-
- pe.vertex_id = graph[s].id;
- pe.edge_id = graph[s].edge_id;
- pe.cost = distances[*vi];
-
- DBG("adding to path_vector[%d]\n", j++);
- path_vector.push_back( pe );
- }
- }
-
- if( path_vector.size() == 0 ) {
- *err_msg = (char *)"No path found";
- return 0;
- }
-
- vector<path_element>::iterator itr;
- *path = (path_element_t *) malloc( sizeof(path_element_t) *
- (path_vector.size() + 1) );
- *path_count = path_vector.size();
-
- for(j=0,itr=path_vector.begin();itr != path_vector.end();itr++,j++) {
- path_element pe = *itr;
- (*path)[j].vertex_id = pe.vertex_id;
- (*path)[j].edge_id = pe.edge_id;
- (*path)[j].cost = pe.cost;
- }
-
- return EXIT_SUCCESS;
- }
- catch(std::exception& e) {
- *err_msg = (char *) e.what();
- return -1;
- }
- catch(...) {
- *err_msg = (char *) "Unknown exception caught!";
- return -1;
- }
-}
-
diff --git a/src/driving_distance/src/boost_interface_drivedist.cpp b/src/driving_distance/src/boost_interface_drivedist.cpp
new file mode 100644
index 0000000..54397d6
--- /dev/null
+++ b/src/driving_distance/src/boost_interface_drivedist.cpp
@@ -0,0 +1,207 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
+#include "./../../dijkstra/src/pgr_dijkstra.hpp"
+
+#include "unistd.h"
+#include <sstream>
+#include <deque>
+#include <vector>
+
+#include "./boost_interface_drivedist.h"
+
+extern "C" {
+#include "postgres.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+}
+
+
+
+
+
+
+int do_pgr_driving_many_to_dist(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t *start_vertex, int s_len,
+ float8 distance,
+ bool directedFlag,
+ bool equiCostFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg) {
+ try {
+ // in c code this should this must have been checked:
+ // 1) end_vertex is in the data_edges
+
+ #if 0 // set to 1 if needed
+ std::ostringstream log;
+ #endif
+
+ graphType gType = directedFlag? DIRECTED: UNDIRECTED;
+ const int initial_size = 1;
+
+ std::deque< Path >paths;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ Pgr_dijkstra < DirectedGraph > digraph(gType, initial_size);
+ Pgr_dijkstra < UndirectedGraph > undigraph(gType, initial_size);
+
+ std::vector< int64_t > start_vertices(start_vertex, start_vertex + s_len);
+
+ if (directedFlag) {
+ digraph.initialize_graph(data_edges, total_tuples);
+ digraph.dijkstra_dd(paths, start_vertices, distance);
+ } else {
+ undigraph.initialize_graph(data_edges, total_tuples);
+ undigraph.dijkstra_dd(paths, start_vertices, distance);
+ }
+
+
+ if (equiCostFlag == false) {
+ int count(count_tuples(paths));
+ if (count == 0) {
+ *err_msg = strdup("NOTICE: No return values was found");
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ return 0;
+ }
+ *ret_path = pgr_get_memory3(count, (*ret_path));
+ int trueCount(collapse_paths(ret_path, paths));
+ *path_count = trueCount;
+ // assert (count == trueCount);
+
+ } else {
+ Path path = equi_cost(paths);
+ size_t count(path.size());
+ if (count == 0) {
+ *err_msg = strdup("NOTICE: No return values was found");
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ return 0;
+ }
+ int trueCount = 0;
+ *ret_path = pgr_get_memory3(count, (*ret_path));
+ path.dpPrint(ret_path, trueCount);
+ *path_count = trueCount;
+ // assert (count == trueCount);
+ }
+
+ #if 1
+ *err_msg = strdup("OK");
+ #else
+ *err_msg = strdup(log.str().c_str());
+ #endif
+ return EXIT_SUCCESS;
+ } catch ( ... ) {
+ *err_msg = strdup("Caught unknown expection!");
+ return -1;
+ }
+}
+
+
+
+
+
+
+
+int do_pgr_driving_distance(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t start_vertex, float8 distance,
+ bool directedFlag,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg) {
+ try {
+ // in c code this should have been checked:
+ // 1) start_vertex is in the data_edges DONE
+ // 2) end_vertex is in the data_edges DONE
+ // 3) start and end_vertex are different DONE
+ std::ostringstream log;
+
+ graphType gType = directedFlag? DIRECTED: UNDIRECTED;
+ const int initial_size = 1;
+
+ Path paths;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ Pgr_dijkstra < DirectedGraph > digraph(gType, initial_size);
+ Pgr_dijkstra < UndirectedGraph > undigraph(gType, initial_size);
+
+ if (directedFlag) {
+ digraph.initialize_graph(data_edges, total_tuples);
+ digraph.dijkstra_dd(paths, start_vertex, distance);
+ } else {
+ undigraph.initialize_graph(data_edges, total_tuples);
+ undigraph.dijkstra_dd(paths, start_vertex, distance);
+ }
+
+ if (paths.path.size() == 0) {
+ *err_msg = strdup(
+ "NOTICE: No driving distance node found");
+ *ret_path = noPathFound3(-1, path_count, (*ret_path));
+ return 0;
+ }
+
+ log << "NOTICE: Calculating the number of tuples \n";
+ int count = paths.path.size();
+
+ log << "NOTICE Count: " << count << " tuples\n";
+
+ // get the space required to store all the paths
+ *ret_path = NULL;
+ *ret_path = pgr_get_memory3(count, (*ret_path));
+
+ int sequence = 0;
+ paths.ddPrint(ret_path, sequence, 0);
+ *path_count = count;
+
+ #if 1
+ *err_msg = strdup("OK");
+ #else
+ *err_msg = strdup(log.str().c_str());
+ #endif
+
+ return EXIT_SUCCESS;
+ } catch ( ... ) {
+ *err_msg = strdup("Caught unknown expection!");
+ return -1;
+ }
+}
+
+#if 0
+// move around this lines to force a return with an empty path and the log msg
+// cool for debugging
+*err_msg = strdup(log.str().c_str());
+(*path_count) = 1;
+*path = noPathFound(start_vertex);
+return -1;
+#endif
diff --git a/src/driving_distance/src/boost_interface_drivedist.h b/src/driving_distance/src/boost_interface_drivedist.h
new file mode 100644
index 0000000..39adb88
--- /dev/null
+++ b/src/driving_distance/src/boost_interface_drivedist.h
@@ -0,0 +1,51 @@
+/*PGR
+
+file: KSPDriver.h
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_DRIVING_DISTANCE_SRC_BOOST_INTERFACE_DRIVEDIST_H_
+#define SRC_DRIVING_DISTANCE_SRC_BOOST_INTERFACE_DRIVEDIST_H_
+
+#include "./../../common/src/pgr_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int do_pgr_driving_many_to_dist(pgr_edge_t * edges, int64_t total_tuples,
+ int64_t *start_vertex, int s_len,
+ float8 distance,
+ bool directed,
+ bool equicost,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg);
+
+int do_pgr_driving_distance(pgr_edge_t * edges, int64_t total_tuples,
+ int64_t start_vertex, float8 distance,
+ bool directed,
+ pgr_path_element3_t **ret_path, int *path_count,
+ char ** err_msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SRC_DRIVING_DISTANCE_SRC_BOOST_INTERFACE_DRIVEDIST_H_
diff --git a/src/driving_distance/src/drivedist.c b/src/driving_distance/src/drivedist.c
index 2dde10f..383790f 100644
--- a/src/driving_distance/src/drivedist.c
+++ b/src/driving_distance/src/drivedist.c
@@ -1,7 +1,8 @@
/*
- * Finding the Driving Distance (isochrone/isodist) for PostgreSQL
+ * Shortest path algorithm for PostgreSQL
*
- * Copyright (c) 2006 Mario H. Basa, Orkney, Inc.
+ * Copyright (c) 2005 Sylvain Pasche
+ * 2015 Celia Virginia Vergara Castillo
*
* 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
@@ -15,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -27,452 +28,159 @@
#include "access/htup_details.h"
#endif
-#include "drivedist.h"
+#include "fmgr.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+#include "./boost_interface_drivedist.h"
-//---------------------------------------------------------------------------
-/*
- * Define this to have profiling enabled
- */
-//#define PROFILE
-
-#ifdef PROFILE
-#include <sys/time.h>
-
-struct timeval prof_dijkstra, prof_store, prof_extract, prof_total;
-long proftime[5];
-long profipts1, profipts2, profopts;
-#define profstart(x) do { gettimeofday(&x, NULL); } while (0);
-#define profstop(n, x) do { struct timeval _profstop; \
- long _proftime; \
- gettimeofday(&_profstop, NULL); \
- _proftime = ( _profstop.tv_sec*1000000+_profstop.tv_usec) - \
- ( x.tv_sec*1000000+x.tv_usec); \
- elog(NOTICE, \
- "PRF(%s) %lu (%f ms)", \
- (n), \
- _proftime, _proftime / 1000.0); \
- } while (0);
-
-#else
-
-#define profstart(x) do { } while (0);
-#define profstop(n, x) do { } while (0);
-
-#endif // PROFILE
-
-
-//----------------------------------------------------------------------------
-
-Datum driving_distance(PG_FUNCTION_ARGS);
-
-#undef DEBUG
-//#define DEBUG 1
-
-#ifdef DEBUG
-#define DBG(format, arg...) \
- elog(NOTICE, format , ## arg)
-#else
-#define DBG(format, arg...) do { ; } while (0)
-#endif
-
-// The number of tuples to fetch from the SPI cursor at each iteration
-#define TUPLIMIT 1000
-
-static char *
-text2char(text *in)
-{
- char *out = palloc(VARSIZE(in));
-
- memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
- out[VARSIZE(in) - VARHDRSZ] = '\0';
- return out;
-}
-
-static int
-finish(int code, int ret)
-{
- code = SPI_finish();
- if (code != SPI_OK_FINISH )
- {
- elog(ERROR,"couldn't disconnect from SPI");
- return -1 ;
- }
-
- return ret;
-}
-
-
-typedef struct edge_columns
-{
- int id;
- int source;
- int target;
- int cost;
- int reverse_cost;
-} edge_columns_t;
-
-static int
-fetch_edge_columns(SPITupleTable *tuptable, edge_columns_t *edge_columns,
- bool has_reverse_cost)
-{
- edge_columns->id = SPI_fnumber(SPI_tuptable->tupdesc, "id");
- edge_columns->source = SPI_fnumber(SPI_tuptable->tupdesc, "source");
- edge_columns->target = SPI_fnumber(SPI_tuptable->tupdesc, "target");
- edge_columns->cost = SPI_fnumber(SPI_tuptable->tupdesc, "cost");
-
- if (edge_columns->id == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->source == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->target == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->cost == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "Error, query must return columns "
- "'id', 'source', 'target' and 'cost'");
- return -1;
- }
-
- if (SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->source) != INT4OID ||
- SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->target) != INT4OID ||
- SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->cost) != FLOAT8OID) {
- elog(ERROR, "Error, columns 'source', 'target' must be of type int4, 'cost' must be of type float8");
- return -1;
- }
-
- DBG("columns: id %i source %i target %i cost %i",
- edge_columns->id, edge_columns->source,
- edge_columns->target, edge_columns->cost);
-
- if (has_reverse_cost) {
- edge_columns->reverse_cost = SPI_fnumber(SPI_tuptable->tupdesc,
- "reverse_cost");
-
- if (edge_columns->reverse_cost == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "Error, reverse_cost is used, but query did't return "
- "'reverse_cost' column");
- return -1;
- }
-
- if (SPI_gettypeid(SPI_tuptable->tupdesc,
- edge_columns->reverse_cost) != FLOAT8OID) {
- elog(ERROR, "Error, columns 'reverse_cost' must be of type float8");
- return -1;
- }
-
- DBG("columns: reverse_cost cost %i", edge_columns->reverse_cost);
- }
-
- return 0;
-}
-
-static void
-fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc, edge_columns_t *edge_columns,
- edge_t *target_edge)
-{
- Datum binval;
- bool isnull;
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->id, &isnull);
-
- if (isnull)
- elog(ERROR, "id contains a null value");
- target_edge->id = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->source, &isnull);
-
- if (isnull)
- elog(ERROR, "source contains a null value");
-
- target_edge->source = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->target, &isnull);
-
- if (isnull)
- elog(ERROR, "target contains a null value");
-
- target_edge->target = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->cost, &isnull);
-
- if (isnull)
- elog(ERROR, "cost contains a null value");
-
- target_edge->cost = DatumGetFloat8(binval);
-
- if (edge_columns->reverse_cost != -1) {
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->reverse_cost,
- &isnull);
-
- if (isnull)
- elog(ERROR, "reverse_cost contains a null value");
- target_edge->reverse_cost = DatumGetFloat8(binval);
- }
-}
-
-
-static int compute_driving_distance(char* sql, int source_vertex_id,
- float8 distance, bool directed,
- bool has_reverse_cost,
- path_element_t **path, int *path_count)
-{
+static int compute_driving_distance(char* sql, int64_t start_vertex,
+ float8 distance, bool directed,
+ bool has_rcost,
+ pgr_path_element3_t **path, int *path_count) {
int SPIcode;
- void *SPIplan;
- Portal SPIportal;
- bool moredata = TRUE;
- int ntuples;
- edge_t *edges = NULL;
- int total_tuples = 0;
- edge_columns_t edge_columns = {.id= -1, .source= -1, .target= -1,
- .cost= -1, .reverse_cost= -1};
-
- int v_max_id=0;
- int v_min_id=INT_MAX;
-
- char *err_msg;
- int ret = -1;
-
- int s_count = 0;
-
- register int z;
-
- DBG("start driving_distance\n");
-
- SPIcode = SPI_connect();
- if (SPIcode != SPI_OK_CONNECT) {
- elog(ERROR, "driving_distance: couldn't open a connection to SPI");
- return -1;
- }
-
- SPIplan = SPI_prepare(sql, 0, NULL);
+ pgr_edge_t *edges = NULL;
+ int64_t total_tuples = 0;
- if (SPIplan == NULL) {
- elog(ERROR, "driving_distance: couldn't create query plan via SPI");
- return -1;
- }
- if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL,
- NULL, true)) == NULL) {
- elog(ERROR, "driving_distance: SPI_cursor_open('%s') returns NULL", sql);
- return -1;
- }
+ char *err_msg = (char *)"";
+ int ret = -1;
- while (moredata == TRUE) {
- SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
+ PGR_DBG("Load data");
+ SPIcode = pgr_get_data(sql, &edges, &total_tuples, has_rcost,
+ start_vertex, start_vertex);
- if (edge_columns.id == -1) {
- if (fetch_edge_columns(SPI_tuptable, &edge_columns,
- has_reverse_cost) == -1)
- return finish(SPIcode, ret);
- }
+ if (SPIcode == -1) {
+ PGR_DBG("Error getting data\n");
+ return SPIcode;
+ }
- ntuples = SPI_processed;
- total_tuples += ntuples;
- if (!edges)
- edges = palloc(total_tuples * sizeof(edge_t));
- else
- edges = repalloc(edges, total_tuples * sizeof(edge_t));
+ PGR_DBG("Total %ld tuples in query:", total_tuples);
- if (edges == NULL) {
- elog(ERROR, "Out of memory");
- return finish(SPIcode, ret);
- }
+ ret = do_pgr_driving_distance(edges, total_tuples,
+ start_vertex, distance,
+ directed,
+ path, path_count, &err_msg);
- if (ntuples > 0) {
- int t;
- SPITupleTable *tuptable = SPI_tuptable;
- TupleDesc tupdesc = SPI_tuptable->tupdesc;
-
- for (t = 0; t < ntuples; t++) {
- HeapTuple tuple = tuptable->vals[t];
- fetch_edge(&tuple, &tupdesc, &edge_columns,
- &edges[total_tuples - ntuples + t]);
- }
- SPI_freetuptable(tuptable);
- }
- else {
- moredata = FALSE;
- }
+ if (ret < 0) {
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
}
+ PGR_DBG("total tuples found %i\n", *path_count);
+ PGR_DBG("Exist Status = %i\n", ret);
+ PGR_DBG("Returned message = %s\n", err_msg);
- //defining min and max vertex id
-
- DBG("Total %i tuples", total_tuples);
-
- for(z=0; z<total_tuples; z++)
- {
- if(edges[z].source<v_min_id)
- v_min_id=edges[z].source;
-
- if(edges[z].source>v_max_id)
- v_max_id=edges[z].source;
-
- if(edges[z].target<v_min_id)
- v_min_id=edges[z].target;
-
- if(edges[z].target>v_max_id)
- v_max_id=edges[z].target;
-
- DBG("%i <-> %i", v_min_id, v_max_id);
-
- }
- //::::::::::::::::::::::::::::::::::::
- //:: reducing vertex id (renumbering)
- //::::::::::::::::::::::::::::::::::::
- for(z=0; z<total_tuples; z++)
- {
- //check if edges[] contains source
- if(edges[z].source == source_vertex_id ||
- edges[z].target == source_vertex_id)
- ++s_count;
-
- edges[z].source-=v_min_id;
- edges[z].target-=v_min_id;
- DBG("%i - %i", edges[z].source, edges[z].target);
- }
- if(s_count == 0)
- {
- elog(ERROR, "Start vertex was not found.");
- return -1;
- }
-
- source_vertex_id -= v_min_id;
-
- profstop("extract", prof_extract);
- profstart(prof_dijkstra);
-
- DBG("Calling boost_dijkstra\n");
-
- ret = boost_dijkstra_dist(edges, total_tuples, source_vertex_id,
- distance, directed, has_reverse_cost,
- path, path_count, &err_msg);
-
- DBG("Back from boost_dijkstra\n");
-
if (ret < 0) {
- elog(ERROR, "Error computing path: %s", err_msg);
- }
-
- profstop("dijkstra", prof_dijkstra);
- profstart(prof_store);
-
- //::::::::::::::::::::::::::::::::
- //:: restoring original vertex id
- //::::::::::::::::::::::::::::::::
- for(z=0; z<*path_count; z++)
- {
- //DBG("vetex %i\n",(*path)[z].vertex_id);
- (*path)[z].vertex_id+=v_min_id;
- }
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
- return finish(SPIcode, ret);
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
}
+#ifndef _MSC_VER
+Datum driving_distance(PG_FUNCTION_ARGS);
+#else // _MSC_VER
+PGDLLEXPORT Datum driving_distance(PG_FUNCTION_ARGS);
+#endif // _MSC_VER
PG_FUNCTION_INFO_V1(driving_distance);
+
+#ifndef _MSC_VER
Datum
-driving_distance(PG_FUNCTION_ARGS)
-{
+#else // _MSC_VER
+PGDLLEXPORT Datum
+#endif
+driving_distance(PG_FUNCTION_ARGS) {
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tuple_desc;
- path_element_t *path = 0;
+ pgr_path_element3_t *ret_path = 0;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL()) {
- MemoryContext oldcontext;
- int path_count = 0;
- int ret;
-
- // XXX profiling messages are not thread safe
- profstart(prof_total);
- profstart(prof_extract);
-
- /* create a function context for cross-call persistence */
- funcctx = SRF_FIRSTCALL_INIT();
-
- /* switch to memory context appropriate for multiple function calls */
- oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
-
- ret = compute_driving_distance(text2char(PG_GETARG_TEXT_P(0)), // sql
- PG_GETARG_INT32(1), // source vertex
- PG_GETARG_FLOAT8(2), // distance or time
- PG_GETARG_BOOL(3),
- PG_GETARG_BOOL(4), &path, &path_count);
- if (ret < 0) {
- elog(ERROR, "Error computing path");
- }
-
-
-#ifdef DEBUG
- DBG("Ret is %i", ret);
- int i;
- for (i = 0; i < path_count; i++) {
- DBG("Step %i vertex_id %i ", i, path[i].vertex_id);
- DBG(" edge_id %i ", path[i].edge_id);
- DBG(" cost %f ", path[i].cost);
- }
-#endif
+ MemoryContext oldcontext;
+ int path_count = 0;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+
+ compute_driving_distance(pgr_text2char(
+ PG_GETARG_TEXT_P(0)), // sql
+ PG_GETARG_INT64(1), // source_id
+ PG_GETARG_FLOAT8(2), // distance
+ PG_GETARG_BOOL(3), // directed
+ PG_GETARG_BOOL(4), // has_rcost
+ &ret_path, &path_count);
- /* total number of tuples to be returned */
- funcctx->max_calls = path_count;
- funcctx->user_fctx = path;
+ /* total number of tuples to be returned */
+ funcctx->max_calls = path_count;
+ funcctx->user_fctx = ret_path;
- funcctx->tuple_desc = BlessTupleDesc(
- RelationNameGetTupleDesc("pgr_costResult"));
-
- MemoryContextSwitchTo(oldcontext);
+ 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);
}
-
+
/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
tuple_desc = funcctx->tuple_desc;
- path = (path_element_t*) funcctx->user_fctx;
-
- if (call_cntr < max_calls) { /* do when there is more left to send */
- HeapTuple tuple;
- Datum result;
- Datum *values;
- char* nulls;
-
- values = palloc(4 * sizeof(Datum));
- nulls = palloc(4 * sizeof(char));
-
- values[0] = Int32GetDatum(call_cntr);
- nulls[0] = ' ';
- values[1] = Int32GetDatum(path[call_cntr].vertex_id);
- nulls[1] = ' ';
- values[2] = Int32GetDatum(path[call_cntr].edge_id);
- nulls[2] = ' ';
- values[3] = Float8GetDatum(path[call_cntr].cost);
- nulls[3] = ' ';
-
- tuple = heap_formtuple(tuple_desc, values, nulls);
-
-
- /* make the tuple into a datum */
- result = HeapTupleGetDatum(tuple);
-
- /* clean up (this is not really necessary) */
- pfree(values);
- pfree(nulls);
-
- SRF_RETURN_NEXT(funcctx, result);
- }
- else { /* do when there is no more left */
- if (path) free(path);
- profstop("store", prof_store);
- profstop("total", prof_total);
-#ifdef PROFILE
- elog(NOTICE, "_________");
-#endif
- DBG("Returning value");
-
- SRF_RETURN_DONE(funcctx);
+ ret_path = (pgr_path_element3_t*) funcctx->user_fctx;
+
+ /* do when there is more left to send */
+ if (call_cntr < max_calls) {
+ HeapTuple tuple;
+ Datum result;
+ Datum *values;
+ char* nulls;
+
+ values = palloc(5 * sizeof(Datum));
+ nulls = palloc(5 * sizeof(char));
+
+ values[0] = Int32GetDatum(ret_path[call_cntr].seq + 1);
+ nulls[0] = ' ';
+ values[1] = Int64GetDatum(ret_path[call_cntr].vertex);
+ nulls[1] = ' ';
+ values[2] = Int64GetDatum(ret_path[call_cntr].edge);
+ nulls[2] = ' ';
+ values[3] = Float8GetDatum(ret_path[call_cntr].cost);
+ nulls[3] = ' ';
+ values[4] = Float8GetDatum(ret_path[call_cntr].tot_cost);
+ nulls[4] = ' ';
+
+ tuple = heap_formtuple(tuple_desc, values, nulls);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ /* clean up (this is not really necessary) */
+ pfree(values);
+ pfree(nulls);
+
+ SRF_RETURN_NEXT(funcctx, result);
+ } else {
+ /* do when there is no more left */
+ if (ret_path) free(ret_path);
+ SRF_RETURN_DONE(funcctx);
}
}
+
diff --git a/src/driving_distance/src/drivedist.h b/src/driving_distance/src/drivedist.h
deleted file mode 100644
index e85bdd7..0000000
--- a/src/driving_distance/src/drivedist.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Drivedist algorithm for PostgreSQL
- *
- * Copyright (c) 2005 Sylvain Pasche
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DRIVEDIST_H
-#define _DRIVEDIST_H
-
-#include "postgres.h"
-#include "dijkstra.h"
-
-#ifdef __cplusplus
-extern "C"
-#endif
-
-int boost_dijkstra_dist(edge_t *edges, unsigned int count,
- int source_vertex_id, double rdistance,
- bool directed, bool has_reverse_cost,
- path_element_t **path, int *path_count, char **err_msg);
-
-#endif
diff --git a/src/driving_distance/src/many_to_dist_driving_distance.c b/src/driving_distance/src/many_to_dist_driving_distance.c
new file mode 100644
index 0000000..9cfe810
--- /dev/null
+++ b/src/driving_distance/src/many_to_dist_driving_distance.c
@@ -0,0 +1,191 @@
+/*pgRouting
+ *
+ * File: many_to_1_dijkstra.c
+ * Copyright (c) 2015 Celia Virginia Vergara Castillo
+ *
+ * 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.
+ *
+ */
+// #define DEBUG
+#include "postgres.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "utils/array.h"
+#include "catalog/pg_type.h"
+#if PGSQL_VERSION > 92
+#include "access/htup_details.h"
+#endif
+
+#include "fmgr.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+#include "./boost_interface_drivedist.h"
+
+#ifndef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+
+static int driving_many_to_dist_driver(
+ char* sql, int64_t *start_vertex, int num,
+ float8 distance,
+ bool directed, bool equicost, bool has_rcost,
+ pgr_path_element3_t **path, int *path_count) {
+ int SPIcode;
+ pgr_edge_t *edges = NULL;
+ int64_t total_tuples = 0;
+
+
+ char *err_msg = (char *)"";
+ int ret = -1;
+
+
+ SPIcode = pgr_get_data(sql, &edges, &total_tuples, has_rcost, -1, -1);
+
+ if (SPIcode == -1) {
+ return SPIcode;
+ }
+
+ ret = do_pgr_driving_many_to_dist(edges, total_tuples,
+ start_vertex, num, distance,
+ directed, equicost,
+ path, path_count, &err_msg);
+
+ if (ret < 0) {
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
+
+ if (ret < 0) {
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
+
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
+}
+
+
+#ifndef _MSC_VER
+Datum driving_many_to_dist(PG_FUNCTION_ARGS);
+#else // _MSC_VER
+PGDLLEXPORT Datum driving_many_to_dist(PG_FUNCTION_ARGS);
+#endif // _MSC_VER
+
+
+PG_FUNCTION_INFO_V1(driving_many_to_dist);
+#ifndef _MSC_VER
+Datum
+#else // _MSC_VER
+PGDLLEXPORT Datum
+#endif
+driving_many_to_dist(PG_FUNCTION_ARGS) {
+ FuncCallContext *funcctx;
+ int call_cntr;
+ int max_calls;
+ TupleDesc tuple_desc;
+ pgr_path_element3_t *ret_path = 0;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL()) {
+ MemoryContext oldcontext;
+ int path_count = 0;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ int64_t* sourcesArr;
+ int num;
+
+ sourcesArr = (int64_t*) pgr_get_bigIntArray(&num, PG_GETARG_ARRAYTYPE_P(1));
+ PGR_DBG("sourcesArr size %d ", num);
+
+ PGR_DBG("Calling driving_many_to_dist_driver");
+ driving_many_to_dist_driver(
+ pgr_text2char(PG_GETARG_TEXT_P(0)), // sql
+ sourcesArr, num, // array of sources
+ PG_GETARG_FLOAT8(2), // distance
+ PG_GETARG_BOOL(3), // directed
+ PG_GETARG_BOOL(4), // equicost
+ PG_GETARG_BOOL(5), // has_rcost
+ &ret_path, &path_count);
+
+ free(sourcesArr);
+
+ /* total number of tuples to be returned */
+ funcctx->max_calls = path_count;
+ funcctx->user_fctx = ret_path;
+ 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);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ call_cntr = funcctx->call_cntr;
+ max_calls = funcctx->max_calls;
+ tuple_desc = funcctx->tuple_desc;
+ ret_path = (pgr_path_element3_t*) funcctx->user_fctx;
+
+ /* do when there is more left to send */
+ if (call_cntr < max_calls) {
+ HeapTuple tuple;
+ Datum result;
+ Datum *values;
+ char* nulls;
+
+ values = palloc(6 * sizeof(Datum));
+ nulls = palloc(6 * sizeof(char));
+ // id, start_v, node, edge, cost, tot_cost
+ values[0] = Int32GetDatum(call_cntr + 1);
+ nulls[0] = ' ';
+ values[1] = Int64GetDatum(ret_path[call_cntr].from);
+ nulls[1] = ' ';
+ values[2] = Int64GetDatum(ret_path[call_cntr].vertex);
+ nulls[2] = ' ';
+ values[3] = Int64GetDatum(ret_path[call_cntr].edge);
+ nulls[3] = ' ';
+ values[4] = Float8GetDatum(ret_path[call_cntr].cost);
+ nulls[4] = ' ';
+ values[5] = Float8GetDatum(ret_path[call_cntr].tot_cost);
+ nulls[5] = ' ';
+
+ tuple = heap_formtuple(tuple_desc, values, nulls);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ /* clean up (this is not really necessary) */
+ pfree(values);
+ pfree(nulls);
+
+ SRF_RETURN_NEXT(funcctx, result);
+ } else {
+ /* do when there is no more left */
+ if (ret_path) free(ret_path);
+ SRF_RETURN_DONE(funcctx);
+ }
+}
+
diff --git a/src/driving_distance/test/drivingdistance-any-00.rest b/src/driving_distance/test/drivingdistance-any-00.rest
deleted file mode 100644
index 5774530..0000000
--- a/src/driving_distance/test/drivingdistance-any-00.rest
+++ /dev/null
@@ -1,11 +0,0 @@
-0|1
-1|4
-2|8
-3|12
-4|16
-5|20
-6|24
-7|28
-8|32
-9|36
-10|40
diff --git a/src/driving_distance/test/drivingdistance-any-00.result b/src/driving_distance/test/drivingdistance-any-00.result
new file mode 100644
index 0000000..f42a346
--- /dev/null
+++ b/src/driving_distance/test/drivingdistance-any-00.result
@@ -0,0 +1,44 @@
+0|1
+1|4
+2|8
+3|12
+4|16
+5|20
+6|24
+7|28
+8|32
+9|36
+10|40
+0|1
+1|4
+2|8
+3|12
+4|16
+5|20
+6|24
+7|28
+8|32
+9|36
+10|40
+0|1
+1|2
+2|3
+3|4
+4|5
+5|6
+6|7
+7|8
+8|9
+9|10
+10|11
+0|1
+1|2
+2|3
+3|4
+4|5
+5|6
+6|7
+7|8
+8|9
+9|10
+10|11
diff --git a/src/driving_distance/test/drivingdistance-any-00.test b/src/driving_distance/test/drivingdistance-any-00.test
deleted file mode 100644
index c102809..0000000
--- a/src/driving_distance/test/drivingdistance-any-00.test
+++ /dev/null
@@ -1,8 +0,0 @@
--- each ring will increas by 4 because it is on a square grid
--- to find the start node number
--- select *, st_distance(st_makepoint(25,25), the_geom) from vertices_tmp where st_dwithin(st_makepoint(25,25), the_geom, 1.0) order by st_distance(st_makepoint(25,25), the_geom) limit 1;
-
-select cost, count(*) from (
- select * from pgr_drivingdistance('select id, source, target, 1.0::float8 as cost from ddnoded2', 1274, 10, false, false)
-) as foo group by cost order by cost asc;
-
diff --git a/src/driving_distance/test/drivingdistance-any-00.test.sql b/src/driving_distance/test/drivingdistance-any-00.test.sql
new file mode 100644
index 0000000..b7af8c1
--- /dev/null
+++ b/src/driving_distance/test/drivingdistance-any-00.test.sql
@@ -0,0 +1,22 @@
+-- each ring will increas by 4 because it is on a square grid
+-- to find the start node number
+-- select *, st_distance(st_makepoint(25,25), the_geom) from vertices_tmp where st_dwithin(st_makepoint(25,25), the_geom, 1.0) order by st_distance(st_makepoint(25,25), the_geom) limit 1;
+
+
+--this are equivalent
+select cost, count(*) from (
+ select * from pgr_drivingdistance('select id, source, target, 1.0::float8 as cost from ddnoded2', 1274, 10, false, false)
+) as foo group by cost order by cost asc;
+
+select agg_cost, count(*) from (
+ select * from pgr_drivingdistance('select id, source, target, 1 as cost from ddnoded2', 1274, 10, false)
+) as foo group by agg_cost order by agg_cost asc;
+
+--- this ones are equivalent
+select agg_cost, count(*) from (
+ select * from pgr_drivingdistance('select id, source, target, 1 as cost from ddnoded2', 1274, 10, true)
+) as foo group by agg_cost order by agg_cost asc;
+
+select agg_cost, count(*) from (
+ select * from pgr_drivingdistance('select id, source, target, 1 as cost from ddnoded2', 1274, 10)
+) as foo group by agg_cost order by agg_cost asc;
diff --git a/src/driving_distance/test/drivingdistance-doc-v2.result b/src/driving_distance/test/drivingdistance-doc-v2.result
new file mode 100644
index 0000000..78030bc
--- /dev/null
+++ b/src/driving_distance/test/drivingdistance-doc-v2.result
@@ -0,0 +1,4 @@
+7|0
+8|1
+7|0
+8|1
diff --git a/doc/test/drivingDistance-any.test b/src/driving_distance/test/drivingdistance-doc-v2.test.sql
similarity index 81%
rename from doc/test/drivingDistance-any.test
rename to src/driving_distance/test/drivingdistance-doc-v2.test.sql
index 383cf50..c3e1b34 100644
--- a/doc/test/drivingDistance-any.test
+++ b/src/driving_distance/test/drivingdistance-doc-v2.test.sql
@@ -3,15 +3,14 @@
-- PGR_drivingDistance
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
-SELECT seq, id1 AS node, cost
+SELECT id1 AS node, cost
FROM pgr_drivingDistance(
'SELECT id, source, target, cost FROM edge_table',
- 6, 1.5, false, false
- );
+ 7, 1.5, false, false
+ ) ;
-SELECT seq, id1 AS node, cost
+SELECT id1 AS node, cost
FROM pgr_drivingDistance(
'SELECT id, source, target, cost, reverse_cost FROM edge_table',
- 6, 1.5, true, true
- );
-
+ 7, 1.5, true, true
+ ) ;
diff --git a/src/driving_distance/test/drivingdistance-doc-v3.result b/src/driving_distance/test/drivingdistance-doc-v3.result
new file mode 100644
index 0000000..e2821ba
--- /dev/null
+++ b/src/driving_distance/test/drivingdistance-doc-v3.result
@@ -0,0 +1,173 @@
+1|1|1|1|1
+1|2|-1|0|0
+1|5|4|1|1
+1|6|8|1|2
+1|7|6|1|3
+1|8|7|1|2
+1|9|9|1|3
+1|10|10|1|2
+1|11|12|1|3
+1|13|14|1|3
+2|2|4|1|3
+2|5|10|1|2
+2|6|8|1|3
+2|8|7|1|3
+2|10|14|1|1
+2|11|12|1|2
+2|12|13|1|3
+2|13|-1|0|0
+3|1|1|1|1
+3|2|-1|0|0
+3|5|4|1|1
+3|6|8|1|2
+3|7|6|1|3
+3|8|7|1|2
+3|9|9|1|3
+3|10|10|1|2
+3|11|12|1|3
+3|13|14|1|3
+3|2|4|1|3
+3|5|10|1|2
+3|6|8|1|3
+3|8|7|1|3
+3|10|14|1|1
+3|11|12|1|2
+3|12|13|1|3
+3|13|-1|0|0
+4|1|1|1|1
+4|2|-1|0|0
+4|5|4|1|1
+4|6|8|1|2
+4|7|6|1|3
+4|8|7|1|2
+4|9|9|1|3
+4|10|10|1|2
+4|11|12|1|3
+4|12|13|1|3
+4|13|-1|0|0
+5|1|1|1|1
+5|2|-1|0|0
+5|3|2|1|1
+5|4|3|1|2
+5|5|4|1|1
+5|6|8|1|2
+5|7|6|1|3
+5|8|7|1|2
+5|9|16|1|3
+5|10|10|1|2
+5|11|12|1|3
+5|13|14|1|3
+6|2|1|3
+6|5|1|2
+6|6|1|3
+6|8|1|3
+6|10|1|1
+6|11|1|2
+6|12|1|3
+6|13|0|0
+7|2|1|1|1
+7|2|2|0|0
+7|2|3|1|1
+7|2|4|1|2
+7|2|5|1|1
+7|2|6|1|2
+7|2|7|1|3
+7|2|8|1|2
+7|2|9|1|3
+7|2|10|1|2
+7|2|11|1|3
+7|2|13|1|3
+7|13|2|1|3
+7|13|5|1|2
+7|13|6|1|3
+7|13|8|1|3
+7|13|10|1|1
+7|13|11|1|2
+7|13|12|1|3
+7|13|13|0|0
+8|2|1|1|1|1
+8|2|2|-1|0|0
+8|2|3|2|1|1
+8|2|4|3|1|2
+8|2|5|4|1|1
+8|2|6|8|1|2
+8|2|7|6|1|3
+8|2|8|7|1|2
+8|2|9|16|1|3
+8|2|10|10|1|2
+8|2|11|12|1|3
+8|13|12|13|1|3
+8|13|13|-1|0|0
+9|2|-1|0|0
+9|5|4|1|1
+9|6|8|1|2
+9|9|9|1|3
+9|10|10|1|2
+9|11|11|1|3
+9|13|14|1|3
+10|13|-1|0|0
+11|2|2|-1|0|0
+11|2|5|4|1|1
+11|2|6|8|1|2
+11|2|9|9|1|3
+11|2|10|10|1|2
+11|2|11|11|1|3
+11|2|13|14|1|3
+11|13|13|-1|0|0
+12|2|2|-1|0|0
+12|2|5|4|1|1
+12|2|6|8|1|2
+12|2|9|9|1|3
+12|2|10|10|1|2
+12|2|11|11|1|3
+12|13|13|-1|0|0
+13|1|1|1|1
+13|2|-1|0|0
+13|3|5|1|3
+13|5|4|1|1
+13|6|8|1|2
+13|7|6|1|3
+13|8|7|1|2
+13|9|9|1|3
+13|10|10|1|2
+13|11|12|1|3
+13|13|14|1|3
+14|2|1|3
+14|5|1|2
+14|6|1|3
+14|8|1|3
+14|10|1|1
+14|11|1|2
+14|12|1|3
+14|13|0|0
+15|2|1|1|1
+15|2|2|0|0
+15|2|3|1|3
+15|2|5|1|1
+15|2|6|1|2
+15|2|7|1|3
+15|2|8|1|2
+15|2|9|1|3
+15|2|10|1|2
+15|2|11|1|3
+15|2|13|1|3
+15|13|2|1|3
+15|13|5|1|2
+15|13|6|1|3
+15|13|8|1|3
+15|13|10|1|1
+15|13|11|1|2
+15|13|12|1|3
+15|13|13|0|0
+16|2|1|1|1|1
+16|2|2|-1|0|0
+16|2|3|5|1|3
+16|2|5|4|1|1
+16|2|6|8|1|2
+16|2|7|6|1|3
+16|2|8|7|1|2
+16|2|9|9|1|3
+16|2|10|10|1|2
+16|2|11|12|1|3
+16|13|12|13|1|3
+16|13|13|-1|0|0
diff --git a/src/driving_distance/test/drivingdistance-doc-v3.test.sql b/src/driving_distance/test/drivingdistance-doc-v3.test.sql
new file mode 100644
index 0000000..c592643
--- /dev/null
+++ b/src/driving_distance/test/drivingdistance-doc-v3.test.sql
@@ -0,0 +1,91 @@
+------------------------------------------------------------------------------------------------------
+------------------------------------------------------------------------------------------------------
+-- PGR_drivingDistance V3
+------------------------------------------------------------------------------------------------------
+------------------------------------------------------------------------------------------------------
+
+
+SELECT 1, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3
+ ) order by node;
+
+SELECT 2, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 13, 3
+ ) order by node;
+
+SELECT 3, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3
+ ) order by from_v, node;
+
+SELECT 4, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3, equicost:=true
+ ) order by from_v, node;
+--------------------------------------------------------------
+SELECT 5, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 3, false
+ ) order by node;
+
+SELECT 6, node, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 13, 3, false
+ ) order by node;
+
+SELECT 7, from_v, node, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3, false
+ ) order by from_v, node;
+
+SELECT 8, from_v, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ array[2,13], 3, false, equicost:=true
+ ) order by from_v, node;
+
+---------------------------------------------------------------
+
+SELECT 9, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3
+ ) order by node;
+
+SELECT 10, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 13, 3
+ ) order by node;
+
+SELECT 11, from_v, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3
+ ) order by from_v, node;
+
+SELECT 12, from_v, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3, equicost:=true
+ ) order by from_v, node;
+--------------------------------------------------------------
+SELECT 13, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, false
+ ) order by node;
+
+SELECT 14, node, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 13, 3, false
+ ) order by node;
+
+SELECT 15, from_v, node, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3, false
+ ) order by from_v, node;
+
+SELECT 16, from_v, node, edge, cost, agg_cost FROM pgr_drivingDistance(
+ 'SELECT id, source, target, cost FROM edge_table',
+ array[2,13], 3, false, equicost:=true
+ ) order by from_v, node;
+
+---------------------------------------------------------------
+
diff --git a/doc/test/sampledata.data b/src/driving_distance/test/sampledata.data
similarity index 97%
copy from doc/test/sampledata.data
copy to src/driving_distance/test/sampledata.data
index a5e899c..db6f2cb 100644
--- a/doc/test/sampledata.data
+++ b/src/driving_distance/test/sampledata.data
@@ -4,6 +4,7 @@
-- SAMPLE DATA
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
+drop table if exists edge_table;
CREATE TABLE edge_table (
id serial,
@@ -46,6 +47,7 @@ UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
select pgr_createTopology('edge_table',0.001);
+drop table if exists vertex_table;
CREATE TABLE vertex_table (
id serial,
x double precision,
diff --git a/src/driving_distance/test/test.conf b/src/driving_distance/test/test.conf
index c988afc..870ee1d 100644
--- a/src/driving_distance/test/test.conf
+++ b/src/driving_distance/test/test.conf
@@ -3,8 +3,12 @@
%main::tests = (
'any' => {
'comment' => 'Driving Distance test for any versions.',
- 'data' => ['drivingdistance-any-00.data'],
- 'tests' => [qw(drivingdistance-any-00)]
+ 'data' => ['drivingdistance-any-00.data','sampledata.data'],
+ 'tests' => [qw(
+drivingdistance-any-00
+drivingdistance-doc-v2
+drivingdistance-doc-v3
+)]
},
# 'vpg-vpgis' => {}, # for version specific tests
# '8-1' => {}, # for pg 8.x and postgis 1.x
diff --git a/src/index.rst b/src/index.rst
index 8928f86..7997061 100644
--- a/src/index.rst
+++ b/src/index.rst
@@ -18,8 +18,9 @@ Routing Functions
- :ref:`pgr_bdAstar<bd_astar>` - Bi-directional A* Shortest Path
- :ref:`pgr_bdDijkstra<bd_dijkstra>` - Bi-directional Dijkstra Shortest Path
- :ref:`pgr_dijkstra<pgr_dijkstra>` - Shortest Path Dijkstra
+ - :ref:`pgr_drivingDistance<pgr_driving_distance>` - Driving distamce
- :ref:`pgr_kDijkstra<pgr_kdijkstra>` - Mutliple destination Shortest Path Dijkstra
- - :ref:`pgr_ksp<ksp>` - K-Shortest Path
+ - :ref:`pgr_ksp<pgr_ksp>` - K-Shortest Path
- :ref:`pgr_tsp<pgr_tsp>` - Traveling Sales Person
- :ref:`pgr_trsp<trsp>` - Turn Restriction Shortest Path (TRSP)
@@ -32,6 +33,7 @@ Routing Functions
bd_astar/doc/index
bd_dijkstra/doc/index
dijkstra/doc/index
+ driving_distance/doc/index
kdijkstra/doc/index
ksp/doc/index
tsp/doc/index
diff --git a/src/kdijkstra/doc/index.rst b/src/kdijkstra/doc/index.rst
index 9959f58..5084032 100644
--- a/src/kdijkstra/doc/index.rst
+++ b/src/kdijkstra/doc/index.rst
@@ -15,7 +15,6 @@ pgr_kDijkstra - Mutliple destination Shortest Path Dijkstra
.. index::
single: pgr_kDijkstraCost(text,integer,integer[],boolean,boolean)
single: pgr_kDijkstraPath(text,integer,integer[],boolean,boolean)
- module: dijkstra
Name
-------------------------------------------------------------------------------
@@ -27,7 +26,7 @@ Name
Synopsis
-------------------------------------------------------------------------------
-These functions allow you to have a single start node and multiple destination nodes and will compute the routes to all the destinations from the source node. Returns a set of :ref:`pgr_costResult3 <type_cost_result3>` or :ref:`pgr_costResult3 <type_cost_result3>`. ``pgr_kdijkstraCost`` returns one record for each destination node and the cost is the total code of the route to that node. ``pgr_kdijkstraPath`` returns one record for every edge in that path from source to destination and t [...]
+These functions allow you to have a single start node and multiple destination nodes and will compute the routes to all the destinations from the source node. Returns a set of :ref:`pgr_costResult <type_cost_result>` or :ref:`pgr_costResult3 <type_cost_result3>`. ``pgr_kdijkstraCost`` returns one record for each destination node and the cost is the total code of the route to that node. ``pgr_kdijkstraPath`` returns one record for every edge in that path from source to destination and the [...]
.. code-block:: sql
diff --git a/src/kdijkstra/sql/kdijkstra.sql b/src/kdijkstra/sql/kdijkstra.sql
index df3fa3e..303ea93 100644
--- a/src/kdijkstra/sql/kdijkstra.sql
+++ b/src/kdijkstra/sql/kdijkstra.sql
@@ -35,8 +35,8 @@ CREATE OR REPLACE FUNCTION pgr_kdijkstracost(
directed boolean,
has_reverse_cost boolean)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting', 'onetomany_dijkstra_dist'
- LANGUAGE C IMMUTABLE STRICT;
+ AS '$libdir/librouting-2.1', 'onetomany_dijkstra_dist'
+ LANGUAGE C STABLE STRICT;
CREATE OR REPLACE FUNCTION pgr_kdijkstrapath(
sql text,
@@ -45,7 +45,11 @@ CREATE OR REPLACE FUNCTION pgr_kdijkstrapath(
directed boolean,
has_reverse_cost boolean)
RETURNS SETOF pgr_costResult3
- AS '$libdir/librouting', 'onetomany_dijkstra_path'
- LANGUAGE C IMMUTABLE STRICT;
-
+ AS '$libdir/librouting-2.1', 'onetomany_dijkstra_path'
+ LANGUAGE C STABLE STRICT;
+CREATE OR REPLACE FUNCTION pgr_vidsToDMatrix(sql text,
+ vids integer[], dir bool, has_rcost bool, want_symmetric bool)
+ RETURNS float8[]
+ AS '$libdir/librouting-2.1', 'manytomany_dijkstra_dmatrix'
+ LANGUAGE C STABLE STRICT;
diff --git a/src/kdijkstra/src/k_targets_boost_wrapper.cpp b/src/kdijkstra/src/k_targets_boost_wrapper.cpp
index 28bc8d4..02e965b 100644
--- a/src/kdijkstra/src/k_targets_boost_wrapper.cpp
+++ b/src/kdijkstra/src/k_targets_boost_wrapper.cpp
@@ -15,10 +15,15 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#include <exception>
#include <vector>
#include <sstream>
@@ -73,9 +78,9 @@ graph_add_edge(G &graph, E &e, int id, int source, int target, float8 cost)
graph[e].cost = cost;
graph[e].id = id;
- typedef typename graph_traits<G>::vertex_descriptor Vertex;
- Vertex s = vertex(source, graph);
- Vertex t = vertex(target, graph);
+ // typedef typename graph_traits<G>::vertex_descriptor Vertex;
+ // Vertex s = vertex(source, graph);
+ // Vertex t = vertex(target, graph);
}
@@ -94,7 +99,7 @@ int onetomany_dijkstra_boostdist(edge_t *edges, unsigned int count,
typedef adjacency_list < listS, vecS, directedS, no_property, Vertex> graph_t;
typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
- typedef std::pair<int, int> Edge;
+ // typedef std::pair<int, int> Edge;
// FIXME: compute this value
const unsigned int num_nodes = ((directed && has_reverse_cost ? 2 : 1) * count) + 100;
@@ -240,9 +245,9 @@ int onetomany_dijkstra_boostdist(edge_t *edges, unsigned int count,
for (tie(out_i, out_end) = out_edges(v_src, graph); out_i != out_end; ++out_i)
{
- graph_traits < graph_t >::vertex_descriptor v, targ;
+ graph_traits < graph_t >::vertex_descriptor targ; // v set but not used
e = *out_i;
- v = source(e, graph);
+ // v = source(e, graph);
targ = target(e, graph);
if (targ == v_targ) {
@@ -302,7 +307,7 @@ try {
typedef adjacency_list < listS, vecS, directedS, no_property, Vertex> graph_t;
typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
- typedef std::pair<int, int> Edge;
+ // typedef std::pair<int, int> Edge;
// FIXME: compute this value
const unsigned int num_nodes = ((directed && has_reverse_cost ? 2 : 1) * count) + 100;
diff --git a/src/kdijkstra/src/k_targets_sp.c b/src/kdijkstra/src/k_targets_sp.c
index 14799b0..c4405a0 100644
--- a/src/kdijkstra/src/k_targets_sp.c
+++ b/src/kdijkstra/src/k_targets_sp.c
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -23,6 +23,7 @@
#include "executor/spi.h"
#include "funcapi.h"
#include "utils/array.h"
+#include "utils/lsyscache.h"
#include "catalog/pg_type.h"
#if PGSQL_VERSION > 92
#include "access/htup_details.h"
@@ -66,6 +67,7 @@ typedef struct edge_columns
+#if 0
static text * charl2text(char *in, int len)
{
text *out = (text *) palloc(len + VARHDRSZ);
@@ -74,12 +76,11 @@ static text * charl2text(char *in, int len)
return out;
}
-
static text * char2text(char *in)
{
return charl2text(in, strlen(in));
}
-
+#endif
static char * text2char(text *in)
{
@@ -94,7 +95,7 @@ static char * text2char(text *in)
static DTYPE *get_pgarray(int *num, ArrayType *input)
{
- int ndims, *dims, *lbs;
+ int ndims, *dims; // , *lbs;
bool *nulls;
Oid i_eltype;
int16 i_typlen;
@@ -124,7 +125,7 @@ static DTYPE *get_pgarray(int *num, ArrayType *input)
/* get various pieces of data from the input array */
ndims = ARR_NDIM(input);
dims = ARR_DIMS(input);
- lbs = ARR_LBOUND(input);
+ // lbs = ARR_LBOUND(input);
if (ndims != 1) {
elog(ERROR, "target must be integer[]");
@@ -518,10 +519,10 @@ Datum onetomany_dijkstra_dist(PG_FUNCTION_ARGS)
int source_ID = PG_GETARG_INT32(1);
int i;
- HeapTuple tuple;
- Datum result;
- Datum *values;
- char* nulls;
+ // HeapTuple tuple;
+ // Datum result;
+ // Datum *values;
+ // char* nulls;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL()) {
@@ -869,10 +870,10 @@ onetomany_dijkstra_path(PG_FUNCTION_ARGS)
int *myTargets = (int *)PG_GETARG_POINTER(2);
int i;
- HeapTuple tuple;
- Datum result;
- Datum *values;
- char* nulls;
+ // HeapTuple tuple;
+ // Datum result;
+ // Datum *values;
+ // char* nulls;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL()) {
@@ -991,3 +992,249 @@ onetomany_dijkstra_path(PG_FUNCTION_ARGS)
SRF_RETURN_DONE(funcctx);
}
+
+static int many2many_dijkstra_dm(char *sql, int *vids, int num, bool directed,
+ bool has_reverse_cost, bool symmetric, float8 *dm)
+{
+ int SPIcode;
+ void *SPIplan;
+ Portal SPIportal;
+ bool moredata = TRUE;
+ int ntuples;
+ edge_t *edges = NULL;
+ int total_tuples = 0;
+ edge_columns_t edge_columns = {.id= -1, .source= -1, .target= -1,
+ .cost= -1, .reverse_cost= -1};
+ int v_max_id = 0;
+ int v_min_id = INT_MAX;
+
+ // int sumFoundVids = 0;
+
+ int i, j;
+ int zcnt = 0;
+
+ int vvids[num];
+ int v_count[num];
+ for (i=0; i<num; i++)
+ v_count[i] = 0;
+
+ char *err_msg;
+ int ret = -1;
+
+ pgr_cost_t *dists;
+
+ DBG("start many2many_dijkstra_dm");
+
+ SPIcode = SPI_connect();
+ if (SPIcode != SPI_OK_CONNECT) {
+ elog(ERROR, "many2many_dijkstra_dm: couldn't open an SPI connection");
+ return -1;
+ }
+
+ DBG("Calling SPI_prepare");
+ SPIplan = SPI_prepare(sql, 0, NULL);
+ if (SPIplan == NULL) {
+ elog(ERROR, "many2many_dijkstra_dm: SPI_prepare failed for (%s)", sql);
+ return -1;
+ }
+
+ DBG("Calling SPI_cursor_open");
+ SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true);
+ if (SPIportal == NULL) {
+ elog(ERROR, "many2many_dijkstra_dm: SPI_cursor_open(%s) failed!", sql);
+ return -1;
+ }
+
+ DBG("Starting while loop to collect edges ...");
+
+ while (moredata == TRUE) {
+ DBG("Calling SPI_cursor_fetch");
+ SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
+
+ if (fetch_edge_columns(SPI_tuptable, &edge_columns,
+ has_reverse_cost) == -1) {
+ return finish(SPIcode, ret);
+ }
+
+ ntuples = SPI_processed;
+ DBG("ntuples=%d", ntuples);
+ if (ntuples > 0) {
+ SPITupleTable *tuptable = SPI_tuptable;
+ TupleDesc tupdesc = SPI_tuptable->tupdesc;
+ int t;
+
+ total_tuples += ntuples;
+
+ if (!edges)
+ edges = palloc(total_tuples * sizeof(edge_t));
+ else
+ edges = repalloc(edges, total_tuples * sizeof(edge_t));
+
+ if (edges == NULL) {
+ elog(ERROR, "Out of memory!");
+ return finish(SPIcode, ret);
+ }
+
+ for (t=0; t < ntuples; t++) {
+ HeapTuple tuple = tuptable->vals[t];
+ fetch_edge(&tuple, &tupdesc, &edge_columns,
+ &edges[total_tuples - ntuples + t]);
+ }
+ SPI_freetuptable(tuptable);
+ }
+ else {
+ moredata = FALSE;
+ }
+ }
+ DBG("Total %d edges!", total_tuples);
+
+ // find min and max vertex ids
+
+ for (i=0; i<total_tuples; i++) {
+ if (edges[i].source < v_min_id) v_min_id = edges[i].source;
+ if (edges[i].source > v_max_id) v_max_id = edges[i].source;
+ if (edges[i].target < v_min_id) v_min_id = edges[i].target;
+ if (edges[i].target > v_max_id) v_max_id = edges[i].target;
+ }
+ DBG("v_min_id: %d, v_max_id: %d", v_min_id, v_max_id);
+
+ // renumber vertices
+
+ for (i=0; i<total_tuples; i++) {
+ // check if edge contains vids[]
+ for (j=0; j<num; j++) {
+ if (edges[i].source == vids[j] || edges[i].target == vids[j])
+ v_count[j]++;
+ }
+ edges[i].source -= v_min_id;
+ edges[i].target -= v_min_id;
+ }
+
+ for (j=0; j< num; j++) {
+ if (v_count[j] == 0) zcnt++;
+ DBG("vids[%d]: %d, cnt: %d", j, vids[j], v_count[j]);
+ vvids[j] = vids[j] - v_min_id;
+ }
+
+ if (zcnt > 0) {
+ elog(ERROR, "%d vid(s) were not found in the edges!", zcnt);
+ return -1;
+ }
+
+ DBG("Starting loop to build dmatrix!");
+
+ for (j=0; j<num; j++) {
+ DBG("Calling onetomany_dijkstra_boostdist j=%d", j);
+
+ ret = onetomany_dijkstra_boostdist(edges, total_tuples, vvids[j],
+ vvids, num, directed, has_reverse_cost, &dists, &err_msg);
+
+ if (ret < 0) {
+ elog(ERROR, "onetomany_dijkstra_boostdist failed on j=%d", j);
+ }
+
+ // ASSUMING: results are in order of vvids array
+ for (i=0; i<num; i++) {
+ dm[j*num + i] = dists[i].cost;
+ }
+
+ free(dists);
+ dists = NULL;
+ }
+
+ DBG("Making the matrix symmertic if requested!");
+
+ // if symmetric requsted, then average cells to make it symmetric
+
+ if (symmetric) {
+ for (i=0; i<num; i++) {
+ dm[i * num + i] = 0.0;
+ for (j=i+1; j<num; j++) {
+ if (dm[j*num + i] < 0.0 && dm[i*num + j] > 0.0)
+ dm[j*num + i] = dm[i*num + j];
+ else if (dm[i*num + j] < 0.0 && dm[j*num + i] > 0.0)
+ dm[i*num + j] = dm[j*num + i];
+ else if (dm[j*num + i] < 0.0 && dm[i*num + j] < 0.0)
+ dm[i*num + j] = dm[j*num + i] = -1.0;
+ else
+ dm[j*num + i] = dm[i*num + j] = (dm[j*num + i] + dm[i*num + j]) / 2.0;
+ }
+ }
+ }
+
+ DBG("Leaving many2many_dijkstra_dm");
+
+ return finish(SPIcode, ret);
+}
+
+/*
+ create or replace function pgr_vidsToDMatrix(sql text,
+ vids integer[], dir bool, has_rcost bool, symmetric bool)
+ return real8[]
+ as '', 'manytomany_dijkstra_dmatrix' language C stable strict;
+
+*/
+
+PG_FUNCTION_INFO_V1(manytomany_dijkstra_dmatrix);
+
+Datum manytomany_dijkstra_dmatrix(PG_FUNCTION_ARGS)
+{
+ ArrayType *result;
+ Datum *result_data;
+ // Datum *values;
+ bool *nulls;
+ int i;
+ int num;
+ int ret;
+ float8 *dm;
+
+ Oid o_eltype = FLOAT8OID;
+ int16 o_typlen;
+ bool o_typbyval;
+ char o_typalign;
+
+ int ndims = 2;
+ int dims[2];
+ int lbs[2] = {1, 1};;
+
+ char *sql = text2char(PG_GETARG_TEXT_P(0));
+ int *vids = get_pgarray(&num, PG_GETARG_ARRAYTYPE_P(1));
+
+ dm = (float8 *)palloc(num * num * sizeof(float8));
+
+ ret = many2many_dijkstra_dm(sql, vids, num,
+ PG_GETARG_BOOL(2), PG_GETARG_BOOL(3), PG_GETARG_BOOL(4),
+ dm);
+
+ if (ret) {
+ elog(ERROR, "Error computing distance matrix!");
+ }
+
+ result_data = (Datum *)palloc(num * num * sizeof(Datum));
+ nulls = (bool *)palloc(num * num * sizeof(bool));
+
+ for (i=0; i<num*num; i++) {
+ if (dm[i] < 0.0) {
+ nulls[i] = true;
+ result_data[i] = PointerGetDatum(NULL);
+ }
+ else {
+ nulls[i] = false;
+ result_data[i] = Float8GetDatum((float8)dm[i]);
+ }
+ }
+
+ pfree(dm);
+
+ dims[0] = dims[1] = num;
+ get_typlenbyvalalign(o_eltype, &o_typlen, &o_typbyval, &o_typalign);
+
+ result = construct_md_array((void *)result_data, nulls, ndims, dims,
+ lbs, o_eltype, o_typlen, o_typbyval, o_typalign);
+
+ pfree(result_data);
+ pfree(nulls);
+
+ PG_RETURN_ARRAYTYPE_P(result);
+}
+
diff --git a/src/kdijkstra/src/k_targets_sp.h b/src/kdijkstra/src/k_targets_sp.h
index 6b4851a..757094a 100644
--- a/src/kdijkstra/src/k_targets_sp.h
+++ b/src/kdijkstra/src/k_targets_sp.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef _TOMANYSP_H
diff --git a/src/kdijkstra/test/kdijkstra-any-01.data b/src/kdijkstra/test/kdijkstra-any-01.data
new file mode 100644
index 0000000..7e6e628
--- /dev/null
+++ b/src/kdijkstra/test/kdijkstra-any-01.data
@@ -0,0 +1,73 @@
+BEGIN;
+
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = off;
+SET check_function_bodies = false;
+SET client_min_messages = warning;
+SET escape_string_warning = off;
+
+SET search_path = public, pg_catalog;
+
+SET default_tablespace = '';
+
+SET default_with_oids = false;
+
+--
+-- Name: edges5; Type: TABLE; Schema: public; Owner: -; Tablespace:
+--
+
+DROP TABLE IF EXISTS edges5 CASCADE;
+
+CREATE TABLE edges5 (
+ eid integer NOT NULL,
+ dir character varying,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ to_cost double precision,
+ rule text,
+ the_geom geometry,
+ CONSTRAINT enforce_dims_the_geom CHECK ((st_ndims(the_geom) = 2)),
+ CONSTRAINT enforce_geotype_the_geom CHECK (((geometrytype(the_geom) = 'LINESTRING'::text) OR (the_geom IS NULL)))
+-- , CONSTRAINT enforce_srid_the_geom CHECK ((st_srid(the_geom) = (0)))
+);
+
+
+--
+-- Data for Name: edges5; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY edges5 (eid, dir, source, target, cost, reverse_cost, x1, y1, x2, y2, to_cost, rule, the_geom) FROM stdin WITH NULL '__NULL__';
+1 B 1 2 1 1 2 0 2 1 __NULL__ __NULL__ 010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2 TF 2 3 -1 1 2 1 3 1 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3 TF 3 4 -1 1 3 1 4 1 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4 B 2 7 1 1 2 1 2 2 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5 FT 3 8 1 -1 3 1 3 2 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6 B 5 6 1 1 0 2 1 2 __NULL__ __NULL__ 01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7 B 6 7 1 1 1 2 2 2 __NULL__ __NULL__ 010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8 B 7 8 1 1 2 2 3 2 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9 B 8 9 1 1 3 2 4 2 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10 B 7 10 1 1 2 2 2 3 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11 FT 8 11 1 -1 3 2 3 3 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12 FT 10 11 1 -1 2 3 3 3 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13 FT 11 12 1 -1 3 3 4 3 __NULL__ __NULL__ 0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14 B 10 13 1 1 2 3 2 4 __NULL__ __NULL__ 0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15 B 9 12 1 1 4 2 4 3 __NULL__ __NULL__ 0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16 B 4 9 1 1 4 1 4 2 __NULL__ __NULL__ 0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+\.
+
+
+--
+-- Name: edges5_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
+--
+
+ALTER TABLE ONLY edges5
+ ADD CONSTRAINT edges5_pkey PRIMARY KEY (eid);
+
+
+COMMIT;
diff --git a/src/kdijkstra/test/kdijkstra-any-01.rest b/src/kdijkstra/test/kdijkstra-any-01.result
similarity index 100%
rename from src/kdijkstra/test/kdijkstra-any-01.rest
rename to src/kdijkstra/test/kdijkstra-any-01.result
diff --git a/src/kdijkstra/test/kdijkstra-any-01.test b/src/kdijkstra/test/kdijkstra-any-01.test.sql
similarity index 100%
rename from src/kdijkstra/test/kdijkstra-any-01.test
rename to src/kdijkstra/test/kdijkstra-any-01.test.sql
diff --git a/src/kdijkstra/test/kdijkstra-any-02.rest b/src/kdijkstra/test/kdijkstra-any-02.result
similarity index 100%
rename from src/kdijkstra/test/kdijkstra-any-02.rest
rename to src/kdijkstra/test/kdijkstra-any-02.result
diff --git a/src/kdijkstra/test/kdijkstra-any-02.test b/src/kdijkstra/test/kdijkstra-any-02.test.sql
similarity index 100%
rename from src/kdijkstra/test/kdijkstra-any-02.test
rename to src/kdijkstra/test/kdijkstra-any-02.test.sql
diff --git a/src/kdijkstra/test/kdijkstra-any-03.rest b/src/kdijkstra/test/kdijkstra-any-03.result
similarity index 100%
rename from src/kdijkstra/test/kdijkstra-any-03.rest
rename to src/kdijkstra/test/kdijkstra-any-03.result
diff --git a/src/kdijkstra/test/kdijkstra-any-03.test b/src/kdijkstra/test/kdijkstra-any-03.test.sql
similarity index 100%
rename from src/kdijkstra/test/kdijkstra-any-03.test
rename to src/kdijkstra/test/kdijkstra-any-03.test.sql
diff --git a/src/kdijkstra/test/test.conf b/src/kdijkstra/test/test.conf
index e091e6b..79f6faa 100644
--- a/src/kdijkstra/test/test.conf
+++ b/src/kdijkstra/test/test.conf
@@ -2,9 +2,9 @@
%main::tests = (
'any' => {
- 'comment' => 'Dijkstra test for any versions.',
- 'data' => ['kdijkstra-any-00.data'],
- 'tests' => [qw(kdijkstra-any-01 kdijkstra-any-02 kdijkstra-any-03)]
+ 'comment' => 'KDijkstra test for any versions.',
+ 'data' => [qw(kdijkstra-any-00.data kdijkstra-any-01.data)],
+ 'tests' => [qw(kdijkstra-any-01 kdijkstra-any-02 kdijkstra-any-03 vidstodmatrix-any-01 vidstodmatrix-any-02)]
},
# 'vpg-vpgis' => {}, # for version specific tests
# '8-1' => {}, # for pg 8.x and postgis 1.x
diff --git a/src/kdijkstra/test/vidstodmatrix-any-01.result b/src/kdijkstra/test/vidstodmatrix-any-01.result
new file mode 100644
index 0000000..e8b9888
--- /dev/null
+++ b/src/kdijkstra/test/vidstodmatrix-any-01.result
@@ -0,0 +1 @@
+{{0,4,4,4,5,5},{4,0,4,4,5,5},{4,4,0,2,3,5},{6,6,6,0,1,3},{5,5,5,3,0,2},{3,5,5,3,2,0}}
diff --git a/src/kdijkstra/test/vidstodmatrix-any-01.test.sql b/src/kdijkstra/test/vidstodmatrix-any-01.test.sql
new file mode 100644
index 0000000..93b4001
--- /dev/null
+++ b/src/kdijkstra/test/vidstodmatrix-any-01.test.sql
@@ -0,0 +1 @@
+select * from pgr_vidsToDMatrix('select eid as id, source, target, cost, reverse_cost from edges5', array[1,5,13,11,12,4], true, true, false);
diff --git a/src/kdijkstra/test/vidstodmatrix-any-02.result b/src/kdijkstra/test/vidstodmatrix-any-02.result
new file mode 100644
index 0000000..a5c1108
--- /dev/null
+++ b/src/kdijkstra/test/vidstodmatrix-any-02.result
@@ -0,0 +1 @@
+{{0,4,4,5,5,4},{4,0,4,5,5,5},{4,4,0,4,4,5},{5,5,4,0,2,3},{5,5,4,2,0,2},{4,5,5,3,2,0}}
diff --git a/src/kdijkstra/test/vidstodmatrix-any-02.test.sql b/src/kdijkstra/test/vidstodmatrix-any-02.test.sql
new file mode 100644
index 0000000..9a26d4c
--- /dev/null
+++ b/src/kdijkstra/test/vidstodmatrix-any-02.test.sql
@@ -0,0 +1 @@
+select * from pgr_vidsToDMatrix('select eid as id, source, target, cost, reverse_cost from edges5', array[1,5,13,11,12,4], true, true, true);
diff --git a/src/ksp/devdata/issue285.data b/src/ksp/devdata/issue285.data
new file mode 100644
index 0000000..b56abae
--- /dev/null
+++ b/src/ksp/devdata/issue285.data
@@ -0,0 +1,7 @@
+1
+1 1 2 1 1
+2 2 3 2 2
+3 2 3 3 3
+4 2 3 4 4
+5 3 4 1 1
+-1
diff --git a/src/ksp/devdata/sampledata.data b/src/ksp/devdata/sampledata.data
new file mode 100644
index 0000000..912aeea
--- /dev/null
+++ b/src/ksp/devdata/sampledata.data
@@ -0,0 +1,20 @@
+18
+1 1 2 1 1
+2 2 3 -1 1
+3 3 4 -1 1
+4 2 5 1 1
+5 3 6 1 -1
+6 7 8 1 1
+7 8 5 1 1
+8 5 6 1 1
+9 6 9 1 1
+10 5 10 1 1
+11 6 11 1 -1
+12 10 11 1 -1
+13 11 12 1 -1
+14 10 13 1 1
+15 9 12 1 1
+16 4 9 1 1
+17 14 15 1 1
+18 16 17 1 1
+-1
diff --git a/src/ksp/doc/index.rst b/src/ksp/doc/index.rst
index ec25e76..6b47cff 100644
--- a/src/ksp/doc/index.rst
+++ b/src/ksp/doc/index.rst
@@ -3,136 +3,29 @@
pgRouting Manual
Copyright(c) pgRouting Contributors
- This documentation is licensed under a Creative Commons Attribution-Share
+ This documentation is licensed under a Creative Commons Attribution-Share
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
-.. _ksp:
+.. _pgr_ksp:
-pgr_ksp - K-Shortest Path
+pgr_ksp - Multiple shortest Paths based on Dijkstra
===============================================================================
-.. index::
- single: pgr_ksp(text,integer,integer,integer,boolean)
- module: ksp
+Version 2.0 (deprecated)
+------------------------
-Name
--------------------------------------------------------------------------------
+ - :ref:`pgr_ksp<pgr_ksp_v2>` - Multiple shortest Paths based on Dijkstra
-``pgr_ksp`` — Returns the "K" shortest paths.
+Version 2.1
+------------------
+ - :ref:`pgr_ksp<pgr_ksp_v3>` - Multiple shortest Paths based on Dijkstra
-Synopsis
--------------------------------------------------------------------------------
+.. toctree::
+ :hidden:
-The K shortest path routing algorithm based on Yen's algorithm. "K" is the number of shortest paths desired. Returns a set of :ref:`pgr_costResult3 <type_cost_result3>` (seq, id1, id2, id3, cost) rows, that make up a path.
+ ./ksp_v2
+ ./ksp_v3
-.. code-block:: sql
- pgr_costResult3[] pgr_ksp(sql text, source integer, target integer,
- paths integer, has_rcost boolean);
-
-
-Description
--------------------------------------------------------------------------------
-
-:sql: a SQL query, which should return a set of rows with the following columns:
-
- .. code-block:: sql
-
- SELECT id, source, target, cost, [,reverse_cost] FROM edge_table
-
-
- :id: ``int4`` identifier of the edge
- :source: ``int4`` identifier of the source vertex
- :target: ``int4`` identifier of the target vertex
- :cost: ``float8`` value, of the edge traversal cost. A negative cost will prevent the edge from being inserted in the graph.
- :reverse_cost: (optional) the cost for the reverse traversal of the edge. This is only used when ``has_rcost`` the parameter is ``true`` (see the above remark about negative costs).
-
-:source: ``int4`` id of the start point
-:target: ``int4`` id of the end point
-:paths: ``int4`` number of alternative routes
-:has_rcost: if ``true``, the ``reverse_cost`` column of the SQL generated set of rows will be used for the cost of the traversal of the edge in the opposite direction.
-
-Returns set of :ref:`type_cost_result`:
-
-:seq: sequence for ording the results
-:id1: route ID
-:id2: node ID
-:id3: edge ID (``0`` for the last row)
-:cost: cost to traverse from ``id2`` using ``id3``
-
-KSP code base taken from http://code.google.com/p/k-shortest-paths/source.
-
-
-.. rubric:: History
-
-* New in version 2.0.0
-
-
-Examples
--------------------------------------------------------------------------------
-
-* Without ``reverse_cost``
-
-.. code-block:: sql
-
- SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
- FROM pgr_ksp(
- 'SELECT id, source, target, cost FROM edge_table',
- 7, 12, 2, false
- );
-
- seq | route | node | edge | cost
- -----+-------+------+------+------
- 0 | 0 | 7 | 6 | 1
- 1 | 0 | 8 | 7 | 1
- 2 | 0 | 5 | 8 | 1
- 3 | 0 | 6 | 11 | 1
- 4 | 0 | 11 | 13 | 1
- 5 | 0 | 12 | 0 | 0
- 6 | 1 | 7 | 6 | 1
- 7 | 1 | 8 | 7 | 1
- 8 | 1 | 5 | 8 | 1
- 9 | 1 | 6 | 9 | 1
- 10 | 1 | 9 | 15 | 1
- 11 | 1 | 12 | 0 | 0
- (12 rows)
-
-
-
-* With ``reverse_cost``
-
-.. code-block:: sql
-
- SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
- FROM pgr_ksp(
- 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
- 7, 12, 2, true
- );
-
- seq | route | node | edge | cost
- -----+-------+------+------+------
- 0 | 0 | 7 | 6 | 1
- 1 | 0 | 8 | 7 | 1
- 2 | 0 | 5 | 8 | 1
- 3 | 0 | 6 | 11 | 1
- 4 | 0 | 11 | 13 | 1
- 5 | 0 | 12 | 0 | 0
- 6 | 1 | 7 | 6 | 1
- 7 | 1 | 8 | 7 | 1
- 8 | 1 | 5 | 8 | 1
- 9 | 1 | 6 | 9 | 1
- 10 | 1 | 9 | 15 | 1
- 11 | 1 | 12 | 0 | 0
- (12 rows)
-
-
-The queries use the :ref:`sampledata` network.
-
-
-See Also
--------------------------------------------------------------------------------
-
-* :ref:`type_cost_result3`
-* http://en.wikipedia.org/wiki/K_shortest_path_routing
diff --git a/src/ksp/doc/index.rst b/src/ksp/doc/ksp_v2.rst
similarity index 67%
copy from src/ksp/doc/index.rst
copy to src/ksp/doc/ksp_v2.rst
index ec25e76..c9303c6 100644
--- a/src/ksp/doc/index.rst
+++ b/src/ksp/doc/ksp_v2.rst
@@ -7,14 +7,13 @@
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
-.. _ksp:
+.. _pgr_ksp_v2:
-pgr_ksp - K-Shortest Path
+pgr_ksp (V 2.0) - K-Shortest Path
===============================================================================
.. index::
- single: pgr_ksp(text,integer,integer,integer,boolean)
- module: ksp
+ single: ksp(text,integer,integer,integer,boolean) -- deprecated
Name
-------------------------------------------------------------------------------
@@ -32,6 +31,17 @@ The K shortest path routing algorithm based on Yen's algorithm. "K" is the numbe
pgr_costResult3[] pgr_ksp(sql text, source integer, target integer,
paths integer, has_rcost boolean);
+.. warning:: This signature is being deprecated in version 2.1, Please use it
+ without the ``has_rcost`` flag instead.
+
+ - for undirected graph.
+ ``pgr_ksp(sql, source, target, distance, directed:=false)``
+ - for directed graph.
+ ``pgr_ksp(sql, source, target, distance, directed:=true)``
+
+ See :ref:`pgr_ksp_v3`
+
+
Description
-------------------------------------------------------------------------------
@@ -82,22 +92,21 @@ Examples
'SELECT id, source, target, cost FROM edge_table',
7, 12, 2, false
);
-
- seq | route | node | edge | cost
- -----+-------+------+------+------
- 0 | 0 | 7 | 6 | 1
- 1 | 0 | 8 | 7 | 1
- 2 | 0 | 5 | 8 | 1
- 3 | 0 | 6 | 11 | 1
- 4 | 0 | 11 | 13 | 1
- 5 | 0 | 12 | 0 | 0
- 6 | 1 | 7 | 6 | 1
- 7 | 1 | 8 | 7 | 1
- 8 | 1 | 5 | 8 | 1
- 9 | 1 | 6 | 9 | 1
- 10 | 1 | 9 | 15 | 1
- 11 | 1 | 12 | 0 | 0
- (12 rows)
+ seq | route | node | edge | cost
+ -----+-------+------+------+------
+ 0 | 0 | 7 | 6 | 1
+ 1 | 0 | 8 | 7 | 1
+ 2 | 0 | 5 | 8 | 1
+ 3 | 0 | 6 | 9 | 1
+ 4 | 0 | 9 | 15 | 1
+ 5 | 0 | 12 | -1 | 0
+ 6 | 1 | 7 | 6 | 1
+ 7 | 1 | 8 | 7 | 1
+ 8 | 1 | 5 | 8 | 1
+ 9 | 1 | 6 | 11 | 1
+ 10 | 1 | 11 | 13 | 1
+ 11 | 1 | 12 | -1 | 0
+ (12 rows)
@@ -110,22 +119,21 @@ Examples
'SELECT id, source, target, cost, reverse_cost FROM edge_table',
7, 12, 2, true
);
-
- seq | route | node | edge | cost
- -----+-------+------+------+------
- 0 | 0 | 7 | 6 | 1
- 1 | 0 | 8 | 7 | 1
- 2 | 0 | 5 | 8 | 1
- 3 | 0 | 6 | 11 | 1
- 4 | 0 | 11 | 13 | 1
- 5 | 0 | 12 | 0 | 0
- 6 | 1 | 7 | 6 | 1
- 7 | 1 | 8 | 7 | 1
- 8 | 1 | 5 | 8 | 1
- 9 | 1 | 6 | 9 | 1
- 10 | 1 | 9 | 15 | 1
- 11 | 1 | 12 | 0 | 0
- (12 rows)
+ seq | route | node | edge | cost
+ -----+-------+------+------+------
+ 0 | 0 | 7 | 6 | 1
+ 1 | 0 | 8 | 7 | 1
+ 2 | 0 | 5 | 8 | 1
+ 3 | 0 | 6 | 9 | 1
+ 4 | 0 | 9 | 15 | 1
+ 5 | 0 | 12 | -1 | 0
+ 6 | 1 | 7 | 6 | 1
+ 7 | 1 | 8 | 7 | 1
+ 8 | 1 | 5 | 8 | 1
+ 9 | 1 | 6 | 11 | 1
+ 10 | 1 | 11 | 13 | 1
+ 11 | 1 | 12 | -1 | 0
+ (12 rows)
The queries use the :ref:`sampledata` network.
diff --git a/src/ksp/doc/ksp_v3.rst b/src/ksp/doc/ksp_v3.rst
new file mode 100644
index 0000000..27b8900
--- /dev/null
+++ b/src/ksp/doc/ksp_v3.rst
@@ -0,0 +1,431 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_ksp_v3:
+
+pgr_ksp - K-Shortest Path
+===============================================================================
+
+Name
+-------------------------------------------------------------------------------
+
+``pgr_ksp`` — Returns the "K" shortest paths.
+
+
+.. figure:: ../../../doc/src/introduction/images/boost-inside.jpeg
+ :target: http://www.boost.org/libs/graph
+
+ Boost Graph Inside
+
+
+Synopsis
+-------------------------------------------------------------------------------
+
+The K shortest path routing algorithm based on Yen's algorithm. "K" is the number of shortest paths desired.
+
+.. index::
+ single: ksp(edges_sql, start_vid, end_vid, k)
+
+.. rubric:: The minimal signature:
+
+.. code-block:: sql
+
+ pgr_ksp(TEXT sql_q, BIGINT start_vid, BIGINT end_vid, INTEGER k);
+ RETURNS SET OF (seq, path_id, path_seq, node, edge, cost, agg_cost) or EMPTY SET
+
+
+.. index::
+ single: ksp(edges_sql, start_vid, end_vid, k, directed, heap_paths)
+
+.. rubric:: The full signature:
+
+.. code-block:: sql
+
+ pgr_ksp(TEXT edges_sql, BIGINT start_vid, BIGINT end_vid, INTEGER k,
+ BOOLEAN directed:=true, BOOLEAN heap_paths:=false);
+ RETURNS SET OF (seq, path_id, path_seq, node, edge, cost, agg_cost) or EMPTY SET
+
+
+Description of the SQL query
+-------------------------------------------------------------------------------
+
+General description of the ``edges_sql``
+
+.. code-block:: sql
+
+ SELECT id, source, target, cost [,reverse_cost] FROM ...
+
+:sql_q: a SQL query, which returns a set of rows with the following columns:
+
+ :id: ``ANY-INTEGER`` identifier of the edge.
+ :source: ``ANY-INTEGER`` identifier of the source vertex of the edge.
+ :target: ``ANY-INTEGER`` identifier of the target vertex of the edge.
+ :cost: ``ANY-NUMERICAL`` value of the edge traversal cost. A negative cost will prevent the edge (``source``, ``target``) from being inserted in the graph.
+ :reverse_cost: ``ANY-NUMERICAL`` (optional) the value for the reverse traversal of the edge. A negative cost will prevent the edge (``target``, ``source``) from being inserted in the graph.
+
+Where:
+
+:ANY-INTEGER: smallint, int, bigint
+:ANY-NUMERICAL: smallint, int, bigint, real, float
+
+
+Description of the parameters of the signatures
+-------------------------------------------------------------------------------
+
+:sql_q: ``TEXT`` SQL query as decribed above.
+:start_vid: ``BIGINT`` id of the starting vertex.
+:end_vid: ``BIGINT`` id of the ending vertex.
+:k: ``INTEGER`` The desiered number of paths.
+:directed: ``BOOLEAN`` (optional). When ``false`` the graph is considered as Undirected. Default is ``true`` which considers the graph as Directed.
+:heap_paths: ``BOOLEAN`` (optional). When ``true`` returns all the paths stored in the process heap. Default is ``false`` which only returns ``k`` pahts.
+
+Roughly, if the shortest path has ``N`` edges, the heap will contain about than ``N * k`` paths for small value of ``k`` and ``k > 1``.
+
+
+
+Description of the return values
+-------------------------------------------------------------------------------
+
+Returns set of ``(seq, path_seq, path_id, node, edge, cost, agg_cost)``
+
+:seq: ``INT`` sequential number starting from **1**.
+:path_seq: ``INT`` relative position in the pathi of ``node`` and ``edge``. Has value **1** for the begining of a path.
+:path_id: ``BIGINT`` path identifier. The ordering of the paths For two paths i, j if i < j then agg_cost(i) <= agg_cost(j).
+:node: ``BIGINT`` id of the node in the path.
+:edge: ``BIGINT`` id of the edge used to go from ``node`` to the next node in the path sequence. ``-1`` for the last node of the route.
+:cost: ``FLOAT`` cost to traverse from ``node`` using ``edge`` to the next node in the path sequence.
+:agg_cost: ``FLOAT`` total cost from ``start_vid`` to ``node``.
+
+
+.. warning:: During the transition to 3.0, because pgr_ksp version 2.0 doesn't have defined a directed flag nor a heap_path flag, when pgr_ksp is used with only one flag version 2.0 will be used.
+
+
+Examples to handle the one flag to choose signatures
+------------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig1`
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2,
+ true -- takes the (V2.0) signature (has_rcost = true and works on directed graph)
+ );
+ seq | id1 | id2 | id3 | cost
+ -----+-----+-----+-----+------
+ 0 | 0 | 2 | 4 | 1
+ 1 | 0 | 5 | 8 | 1
+ 2 | 0 | 6 | 9 | 1
+ 3 | 0 | 9 | 15 | 1
+ 4 | 0 | 12 | -1 | 0
+ 5 | 1 | 2 | 4 | 1
+ 6 | 1 | 5 | 8 | 1
+ 7 | 1 | 6 | 11 | 1
+ 8 | 1 | 11 | 13 | 1
+ 9 | 1 | 12 | -1 | 0
+ (10 rows)
+
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2,
+ directed:=true -- takes the new signature
+ );
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 0 | 1 | 2 | 4 | 1 | 0
+ 2 | 0 | 2 | 5 | 8 | 1 | 1
+ 3 | 0 | 3 | 6 | 9 | 1 | 2
+ 4 | 0 | 4 | 9 | 15 | 1 | 3
+ 5 | 0 | 5 | 12 | -1 | 0 | 4
+ 6 | 1 | 1 | 2 | 4 | 1 | 0
+ 7 | 1 | 2 | 5 | 8 | 1 | 1
+ 8 | 1 | 3 | 6 | 11 | 1 | 2
+ 9 | 1 | 4 | 11 | 13 | 1 | 3
+ 10 | 1 | 5 | 12 | -1 | 0 | 4
+ (10 rows)
+
+
+
+Examples for queries marked as ``directed`` with ``cost`` and ``reverse_cost`` columns
+--------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig1`
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 1 | 2 | 5 | 8 | 1 | 1
+ 3 | 1 | 3 | 6 | 9 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 11 | 1 | 2
+ 9 | 2 | 4 | 11 | 13 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ (10 rows)
+
+
+
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, heap_paths:=true
+ );
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, true, true
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 1 | 2 | 5 | 8 | 1 | 1
+ 3 | 1 | 3 | 6 | 9 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 11 | 1 | 2
+ 9 | 2 | 4 | 11 | 13 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ 11 | 3 | 1 | 2 | 4 | 1 | 0
+ 12 | 3 | 2 | 5 | 10 | 1 | 1
+ 13 | 3 | 3 | 10 | 12 | 1 | 2
+ 14 | 3 | 4 | 11 | 13 | 1 | 3
+ 15 | 3 | 5 | 12 | -1 | 0 | 4
+ (15 rows)
+
+
+
+
+Examples for queries marked as ``undirected`` with ``cost`` and ``reverse_cost`` columns
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig2`
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, directed:=false
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 2 | 1 | 0
+ 2 | 1 | 2 | 3 | 3 | 1 | 1
+ 3 | 1 | 3 | 4 | 16 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 9 | 1 | 2
+ 9 | 2 | 4 | 9 | 15 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ (10 rows)
+
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, directed:=false, heap_paths:=true
+ );
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, false, true
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 2 | 1 | 0
+ 2 | 1 | 2 | 3 | 3 | 1 | 1
+ 3 | 1 | 3 | 4 | 16 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 9 | 1 | 2
+ 9 | 2 | 4 | 9 | 15 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ 11 | 3 | 1 | 2 | 4 | 1 | 0
+ 12 | 3 | 2 | 5 | 10 | 1 | 1
+ 13 | 3 | 3 | 10 | 12 | 1 | 2
+ 14 | 3 | 4 | 11 | 13 | 1 | 3
+ 15 | 3 | 5 | 12 | -1 | 0 | 4
+ 16 | 4 | 1 | 2 | 4 | 1 | 0
+ 17 | 4 | 2 | 5 | 10 | 1 | 1
+ 18 | 4 | 3 | 10 | 12 | 1 | 2
+ 19 | 4 | 4 | 11 | 11 | 1 | 3
+ 20 | 4 | 5 | 6 | 9 | 1 | 4
+ 21 | 4 | 6 | 9 | 15 | 1 | 5
+ 22 | 4 | 7 | 12 | -1 | 0 | 6
+ (22 rows)
+
+
+
+Examples for queries marked as ``directed`` with ``cost`` column
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig3`
+
+
+Empty path representation
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, 2
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ (0 rows)
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 1 | 2 | 5 | 8 | 1 | 1
+ 3 | 1 | 3 | 6 | 9 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 11 | 1 | 2
+ 9 | 2 | 4 | 11 | 13 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ (10 rows)
+
+
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, heap_paths:=true
+ );
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, true, true
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 1 | 2 | 5 | 8 | 1 | 1
+ 3 | 1 | 3 | 6 | 9 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 11 | 1 | 2
+ 9 | 2 | 4 | 11 | 13 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ 11 | 3 | 1 | 2 | 4 | 1 | 0
+ 12 | 3 | 2 | 5 | 10 | 1 | 1
+ 13 | 3 | 3 | 10 | 12 | 1 | 2
+ 14 | 3 | 4 | 11 | 13 | 1 | 3
+ 15 | 3 | 5 | 12 | -1 | 0 | 4
+ (15 rows)
+
+
+
+Examples for queries marked as ``undirected`` with ``cost`` column
+----------------------------------------------------------------------------------------
+
+The examples in this section use the following :ref:`fig4`
+
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, directed:=false
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 1 | 2 | 5 | 8 | 1 | 1
+ 3 | 1 | 3 | 6 | 9 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 11 | 1 | 2
+ 9 | 2 | 4 | 11 | 13 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ (10 rows)
+
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, directed:=false, heap_paths:=true
+ );
+
+ SELECT * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, false, true
+ );
+ seq | path_id | path_seq | node | edge | cost | agg_cost
+ -----+---------+----------+------+------+------+----------
+ 1 | 1 | 1 | 2 | 4 | 1 | 0
+ 2 | 1 | 2 | 5 | 8 | 1 | 1
+ 3 | 1 | 3 | 6 | 9 | 1 | 2
+ 4 | 1 | 4 | 9 | 15 | 1 | 3
+ 5 | 1 | 5 | 12 | -1 | 0 | 4
+ 6 | 2 | 1 | 2 | 4 | 1 | 0
+ 7 | 2 | 2 | 5 | 8 | 1 | 1
+ 8 | 2 | 3 | 6 | 11 | 1 | 2
+ 9 | 2 | 4 | 11 | 13 | 1 | 3
+ 10 | 2 | 5 | 12 | -1 | 0 | 4
+ 11 | 3 | 1 | 2 | 4 | 1 | 0
+ 12 | 3 | 2 | 5 | 10 | 1 | 1
+ 13 | 3 | 3 | 10 | 12 | 1 | 2
+ 14 | 3 | 4 | 11 | 13 | 1 | 3
+ 15 | 3 | 5 | 12 | -1 | 0 | 4
+ (15 rows)
+
+
+The queries use the :ref:`sampledata` network.
+
+
+
+.. rubric:: History
+
+* New in version 2.0.0
+* Added functionality version 2.1
+
+See Also
+-------------------------------------------------------------------------------
+
+* http://en.wikipedia.org/wiki/K_shortest_path_routing
+
+.. rubric:: Indices and tables
+
+* :ref:`genindex`
+* :ref:`search`
+
diff --git a/src/ksp/sql/CMakeLists.txt b/src/ksp/sql/CMakeLists.txt
index dd5c7d9..50d23db 100644
--- a/src/ksp/sql/CMakeLists.txt
+++ b/src/ksp/sql/CMakeLists.txt
@@ -1,6 +1,7 @@
# Append in local scope
LIST(APPEND PACKAGE_SQL_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/routing_ksp.sql)
+ ${CMAKE_CURRENT_SOURCE_DIR}/routing_ksp.sql
+)
# set in parent scope
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
diff --git a/src/ksp/sql/routing_ksp.sql b/src/ksp/sql/routing_ksp.sql
index 24c31c2..dad78a6 100644
--- a/src/ksp/sql/routing_ksp.sql
+++ b/src/ksp/sql/routing_ksp.sql
@@ -1,9 +1,76 @@
------------------------------------------------------------------------
--- Function for k shortest_path computation
--- See README for description
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION pgr_ksp(sql text, source_id integer, target_id integer, no_paths integer, has_reverse_cost boolean)
- RETURNS SETOF pgr_costResult3
- AS '$libdir/librouting_ksp', 'kshortest_path'
- LANGUAGE c IMMUTABLE STRICT;
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+
+CREATE OR REPLACE FUNCTION _pgr_ksp(sql text, start_vid bigint, end_vid bigint, k integer, has_rcost boolean, directed boolean,
+ OUT seq integer, OUT path_id integer, OUT path_seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ '$libdir/librouting-2.1', 'kshortest_path'
+ LANGUAGE c STABLE STRICT;
+
+
+-- V2 the graph is directed and there are no heap paths
+CREATE OR REPLACE FUNCTION pgr_ksp(sql text, start_vid integer, end_vid integer, k integer, has_rcost boolean)
+ RETURNS SETOF pgr_costresult3 AS
+ $BODY$
+ DECLARE
+ has_reverse boolean;
+ BEGIN
+ has_reverse =_pgr_parameter_check('ksp', sql::text, false);
+
+ if (has_reverse != has_rcost) then
+ if (has_reverse) then -- raise NOTICE 'has_reverse_cost set to false but reverse_cost column found, Ignoring';
+ else raise EXCEPTION 'has_reverse_cost set to true but reverse_cost not found';
+ end if;
+ end if;
+
+ return query SELECT ((row_number() over()) -1)::integer as seq, (path_id-1)::integer as id1, node::integer as id2, edge::integer as id3, cost
+ FROM _pgr_ksp(sql::text, start_vid, end_vid, k, has_reverse, true) where path_id <= k;
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
+--V3 DEFAULTS directed:=true heap_paths:=false
+CREATE OR REPLACE FUNCTION pgr_ksp(sql text, start_vid bigint, end_vid bigint, k integer,
+ directed boolean default true, heap_paths boolean default false,
+ OUT seq integer, OUT path_id integer, OUT path_seq integer, OUT node bigint, OUT edge bigint, OUT cost float, OUT agg_cost float)
+ RETURNS SETOF RECORD AS
+ $BODY$
+ DECLARE
+ has_rcost boolean;
+ BEGIN
+ has_rcost =_pgr_parameter_check('ksp', sql::text, true);
+ if heap_paths = false then
+ return query SELECT *
+ FROM _pgr_ksp(sql::text, start_vid, end_vid, k, has_rcost, directed) a where a.path_id <= k;
+ else
+ return query SELECT *
+ FROM _pgr_ksp(sql::text, start_vid, end_vid, k, has_rcost, directed);
+ end if;
+ END
+ $BODY$
+ LANGUAGE plpgsql VOLATILE
+ COST 100
+ ROWS 1000;
+
diff --git a/src/ksp/src/BaseGraph.cpp b/src/ksp/src/BaseGraph.cpp
deleted file mode 100644
index 8968d02..0000000
--- a/src/ksp/src/BaseGraph.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// BaseGraph.cpp
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 6/6/2010
-///
-/// $Id: BaseGraph.cpp 52 2010-06-14 06:53:06Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#include <limits>
-#include <string>
-#include <algorithm>
-#include "BaseGraph.h"
-
-const double BaseGraph::DISCONNECT = (std::numeric_limits<double>::max)();
-
-void BaseGraph::clear()
-{
- m_nEdgeNum = 0;
- m_nVertexNum = 0;
-
- for(std::map<BaseVertex*, std::set<BaseVertex*>*>::const_iterator pos=m_mpFaninVertices.begin();
- pos!=m_mpFaninVertices.end(); ++pos)
- {
- delete pos->second;
- }
- m_mpFaninVertices.clear();
-
- for(std::map<BaseVertex*, std::set<BaseVertex*>*>::const_iterator pos=m_mpFanoutVertices.begin();
- pos!=m_mpFanoutVertices.end(); ++pos)
- {
- delete pos->second;
- }
- m_mpFanoutVertices.clear();
-
-
- m_mpEdgeCodeWeight.clear();
-
- /*m_stVertices.clear();*/
- /*m_mpVertexIndex.clear();*/
-
- //clear the list of vertices objects
- for_each(m_vtVertices.begin(), m_vtVertices.end(), DeleteFunc<BaseVertex>());
- m_vtVertices.clear();
-}
diff --git a/src/ksp/src/BaseGraph.h b/src/ksp/src/BaseGraph.h
deleted file mode 100644
index 780088a..0000000
--- a/src/ksp/src/BaseGraph.h
+++ /dev/null
@@ -1,116 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// BaseGraph.h
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 6/6/2010
-///
-/// $Id: BaseGraph.h 57 2010-08-16 07:03:32Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __BaseGraph_h
-#define __BaseGraph_h
-
-#include <set>
-#include <vector>
-#include <map>
-#include "GraphElements.h"
-
-class BaseGraph
-{
-public: // members
-
- const static double DISCONNECT;
-
- typedef std::set<BaseVertex*>::iterator VertexPtSetIterator;
- typedef std::map<BaseVertex*, std::set<BaseVertex*>*>::iterator BaseVertexPt2SetMapIterator;
-
-protected: // members
-
- std::map<BaseVertex*, std::set<BaseVertex*>*> m_mpFanoutVertices;
- std::map<BaseVertex*, std::set<BaseVertex*>*> m_mpFaninVertices;
- std::map<int, double> m_mpEdgeCodeWeight;
- std::vector<BaseVertex*> m_vtVertices;
- int m_nEdgeNum;
- int m_nVertexNum;
-
-
-public: // methods
-
- BaseGraph(){}; //default constructor
- BaseGraph(const BaseGraph& graph) /// copy constructor
- {
- m_nVertexNum = graph.m_nVertexNum;
- m_nEdgeNum = graph.m_nEdgeNum;
- m_vtVertices.assign(graph.m_vtVertices.begin(),graph.m_vtVertices.end());
- m_mpFaninVertices.insert(graph.m_mpFaninVertices.begin(),graph.m_mpFaninVertices.end());
- m_mpFanoutVertices.insert(graph.m_mpFanoutVertices.begin(),graph.m_mpFanoutVertices.end());
- m_mpEdgeCodeWeight.insert(graph.m_mpEdgeCodeWeight.begin(),graph.m_mpEdgeCodeWeight.end());
- }
- virtual ~BaseGraph(void){clear();}
-
- void clear();
-
-protected: // methods
-
- int get_edge_code(const BaseVertex* start_vertex_pt, const BaseVertex* end_vertex_pt) const
- {
- /// Note that the computation below works only if
- /// the result is smaller than the maximum of an integer!
- return start_vertex_pt->getID()*m_nVertexNum+end_vertex_pt->getID();
- }
-
-public:
-
- virtual double get_edge_weight(const BaseVertex* start_vertex_pt, const BaseVertex* end_vertex_pt) const
- {
- std::map<int, double>::const_iterator pos =
- m_mpEdgeCodeWeight.find(get_edge_code(start_vertex_pt, end_vertex_pt));
-
- if (pos != m_mpEdgeCodeWeight.end())
- {
- return pos->second;
- }
-
- return DISCONNECT;
- }
-
- virtual std::set<BaseVertex*>* get_precedent_vertex_set(BaseVertex* vertex)
- {
- return get_vertex_set_pt(vertex, m_mpFaninVertices);
- }
-
- virtual std::set<BaseVertex*>* get_adjacent_vertex_set(BaseVertex* vertex)
- {
- return get_vertex_set_pt(vertex, m_mpFanoutVertices);
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Non-virtual methods
- //////////////////////////////////////////////////////////////////////////
- BaseVertex* get_vertex_by_ID(size_t id) const
- {
- return m_vtVertices.at(id);
- }
-
- std::set<BaseVertex*>* get_vertex_set_pt(BaseVertex* vertex_,
- std::map<BaseVertex*, std::set<BaseVertex*>*>& vertex_container_index)
- {
- BaseVertexPt2SetMapIterator pos = vertex_container_index.find(vertex_);
-
- if(pos == vertex_container_index.end())
- {
- std::set<BaseVertex*>* vertex_set = new std::set<BaseVertex*>();
- std::pair<BaseVertexPt2SetMapIterator,bool> ins_pos =
- vertex_container_index.insert(std::make_pair(vertex_, vertex_set));
-
- pos = ins_pos.first;
- }
-
- return pos->second;
- }
-};
-
-#endif
diff --git a/src/ksp/src/BasePath.cpp b/src/ksp/src/BasePath.cpp
deleted file mode 100644
index 30cd3a5..0000000
--- a/src/ksp/src/BasePath.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// BasePath.cpp
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 6/6/2010
-///
-/// $Id: BasePath.cpp 47 2010-06-07 06:45:09Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#include <vector>
-#include "GraphElements.h"
-#include "BasePath.h"
-//
-// BasePath::BasePath(void)
-// {
-// }
-//
-// BasePath::~BasePath(void)
-// {
-// }
diff --git a/src/ksp/src/BasePath.h b/src/ksp/src/BasePath.h
deleted file mode 100644
index 1ed9b9e..0000000
--- a/src/ksp/src/BasePath.h
+++ /dev/null
@@ -1,79 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// BasePath.h
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 6/6/2010
-///
-/// $Id: BasePath.h 60 2010-08-30 06:44:26Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __BasePath_h
-#define __BasePath_h
-
-#include <vector>
-#include <iostream>
-#include "GraphElements.h"
-
-class BasePath
-{
-protected:
-
- size_t m_nLength;
- double m_dWeight;
- std::vector<BaseVertex*> m_vtVertexList;
-
-public:
- BasePath(const std::vector<BaseVertex*>& vertex_list, double weight)
- :m_dWeight(weight)
- {
- m_vtVertexList.assign(vertex_list.begin(), vertex_list.end());
- m_nLength = m_vtVertexList.size();
- }
- ~BasePath(void){}
-
- double Weight() const { return m_dWeight; }
- void Weight(double val) { m_dWeight = val; }
-
- size_t length() const { return m_nLength; }
-
- BaseVertex* GetVertex(size_t i)
- {
- return m_vtVertexList.at(i);
- }
-
- bool SubPath(std::vector<BaseVertex*>& sub_path, BaseVertex* ending_vertex_pt)
- {
-
- for (std::vector<BaseVertex*>::const_iterator pos = m_vtVertexList.begin();
- pos != m_vtVertexList.end(); ++pos)
- {
- if (*pos != ending_vertex_pt)
- {
- sub_path.push_back(*pos);
- }else
- {
- //break;
- return true;
- }
- }
-
- return false;
- }
-
- // display the content
- void PrintOut(std::ostream& out_stream) const
- {
- out_stream << "BasePath Cost: " << m_dWeight << " Length: " << m_vtVertexList.size() << std::endl;
- //std::copy(m_vtVertexList.begin(), m_vtVertexList.end(), std::ostream_iterator<int>(out_stream, " "));
- for(std::vector<BaseVertex*>::const_iterator pos=m_vtVertexList.begin(); pos!=m_vtVertexList.end();++pos)
- {
- (*pos)->PrintOut(out_stream);
- out_stream << "->";
- }
- out_stream << std::endl << "*********************************************" << std::endl;
- }
-};
-#endif
diff --git a/src/ksp/src/CMakeLists.txt b/src/ksp/src/CMakeLists.txt
index 8c6b331..f2398f5 100644
--- a/src/ksp/src/CMakeLists.txt
+++ b/src/ksp/src/CMakeLists.txt
@@ -1,28 +1,4 @@
-set(LIBRARY_OUTPUT_PATH ../../../lib/)
+ADD_LIBRARY(ksp OBJECT
+ ksp.c
+ ksp_driver.cpp)
-include_directories(${PGROUTING_INCLUDE_DIRECTORIES} ${POSTGRESQL_INCLUDE_DIR})
-if(WIN32)
- include_directories(${POSTGRESQL_INCLUDE_DIR}/port/win32)
-endif(WIN32)
-
-if(APPLE)
- set(LIBRARY_MODE_TARGET "MODULE")
-else(APPLE)
- set(LIBRARY_MODE_TARGET "SHARED")
-endif(APPLE)
-
-add_library(routing_ksp ${LIBRARY_MODE_TARGET} BaseGraph.cpp BaseGraph.h BasePath.cpp BasePath.h DijkstraShortestPathAlg.cpp DijkstraShortestPathAlg.h DynamicGraph.h Graph.cpp GraphElements.h Graph.h HeaderTest.cpp TGraph.h TPath.h YenTopKShortestPathsAlg.cpp YenTopKShortestPathsAlg.h ksp.c KSPDriver.cpp KSPGraph.h KSPGraph.cpp )
-
-if(WIN32)
- if(MSVC)
- set_target_properties(routing_ksp PROPERTIES COMPILE_FLAGS "-DHAVE_GETHOSTNAME")
- endif(MSVC)
-endif(WIN32)
-
-if(APPLE)
- set_target_properties(routing_ksp
- PROPERTIES
- LINK_FLAGS "-bundle_loader ${POSTGRESQL_EXECUTABLE} -bundle")
-endif(APPLE)
-
-install(TARGETS routing_ksp DESTINATION ${LIBRARY_INSTALL_PATH})
diff --git a/src/ksp/src/DijkstraShortestPathAlg.cpp b/src/ksp/src/DijkstraShortestPathAlg.cpp
deleted file mode 100644
index 5739aa3..0000000
--- a/src/ksp/src/DijkstraShortestPathAlg.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// DijkstraShortestPathAlg.cpp
-/// The implementation of Dijkstra algorithm to get the shortest path of
-/// a pair of vertices in a graph.
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 5/30/2010
-///
-/// $Id: DijkstraShortestPathAlg.cpp 65 2010-09-08 06:48:36Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#include "GraphElements.h"
-#include "Graph.h"
-#include "DijkstraShortestPathAlg.h"
-
-BasePath* DijkstraShortestPathAlg::get_shortest_path( BaseVertex* source, BaseVertex* sink )
-{
- determine_shortest_paths(source, sink, true);
-
- std::vector<BaseVertex*> vertex_list;
- std::map<BaseVertex*, double>::const_iterator pos =
- m_mpStartDistanceIndex.find(sink);
- double weight = pos != m_mpStartDistanceIndex.end() ? pos->second : Graph::DISCONNECT;
-
- if (weight < Graph::DISCONNECT)
- {
- BaseVertex* cur_vertex_pt = sink;
- do
- {
- vertex_list.insert(vertex_list.begin(), cur_vertex_pt);
-
- std::map<BaseVertex*, BaseVertex*>::const_iterator pre_pos =
- m_mpPredecessorVertex.find(cur_vertex_pt);
-
- if (pre_pos == m_mpPredecessorVertex.end()) break;
-
- cur_vertex_pt = pre_pos->second;
-
- } while (cur_vertex_pt != source);
-
- vertex_list.insert(vertex_list.begin(), source);
- }
- return new BasePath(vertex_list, weight);
-}
-
-void DijkstraShortestPathAlg::determine_shortest_paths( BaseVertex* source, BaseVertex* sink, bool is_source2sink )
-{
- //1. clear the intermediate variables
- clear();
-
- //2. initiate the local variables
- BaseVertex* end_vertex = is_source2sink ? sink : source;
- BaseVertex* start_vertex = is_source2sink ? source : sink;
- m_mpStartDistanceIndex[start_vertex] = 0;
- start_vertex->Weight(0);
- m_quCandidateVertices.insert(start_vertex);
-
- //3. start searching for the shortest path
- while (!m_quCandidateVertices.empty())
- {
- std::multiset<BaseVertex*, WeightLess<BaseVertex> >::const_iterator pos = m_quCandidateVertices.begin();
-
- BaseVertex* cur_vertex_pt = *pos; //m_quCandidateVertices.top();
- m_quCandidateVertices.erase(pos);
-
- if (cur_vertex_pt == end_vertex) break;
-
-// if(cur_vertex_pt->getID() == 31)
-// {
-// int i = 1;
-// i = 100;
-// }
- m_stDeterminedVertices.insert(cur_vertex_pt->getID());
-
- improve2vertex(cur_vertex_pt, is_source2sink);
- }
-}
-
-void DijkstraShortestPathAlg::improve2vertex( BaseVertex* cur_vertex_pt, bool is_source2sink )
-{
- // 1. get the neighboring vertices
- std::set<BaseVertex*>* neighbor_vertex_list_pt = new std::set<BaseVertex*>();
-
- if(is_source2sink)
- {
- m_pDirectGraph->get_adjacent_vertices(cur_vertex_pt, *neighbor_vertex_list_pt);
- }else
- {
- m_pDirectGraph->get_precedent_vertices(cur_vertex_pt, *neighbor_vertex_list_pt);
- }
-
- // 2. update the distance passing on the current vertex
- for(std::set<BaseVertex*>::iterator cur_neighbor_pos=neighbor_vertex_list_pt->begin();
- cur_neighbor_pos!=neighbor_vertex_list_pt->end(); ++cur_neighbor_pos)
- {
- //2.1 skip if it has been visited before
- if (m_stDeterminedVertices.find((*cur_neighbor_pos)->getID())!=m_stDeterminedVertices.end())
- {
- continue;
- }
-
- //2.2 calculate the distance
- std::map<BaseVertex*, double>::const_iterator cur_pos = m_mpStartDistanceIndex.find(cur_vertex_pt);
- double distance = cur_pos != m_mpStartDistanceIndex.end() ? cur_pos->second : Graph::DISCONNECT;
-
- distance += is_source2sink ? m_pDirectGraph->get_edge_weight(cur_vertex_pt, *cur_neighbor_pos) :
- m_pDirectGraph->get_edge_weight(*cur_neighbor_pos, cur_vertex_pt);
-
- //2.3 update the distance if necessary
- cur_pos = m_mpStartDistanceIndex.find(*cur_neighbor_pos);
- if (cur_pos == m_mpStartDistanceIndex.end() || cur_pos->second > distance)
- {
- m_mpStartDistanceIndex[*cur_neighbor_pos] = distance;
- m_mpPredecessorVertex[*cur_neighbor_pos] = cur_vertex_pt;
-
- (*cur_neighbor_pos)->Weight(distance);
-
- std::multiset<BaseVertex*, WeightLess<BaseVertex> >::const_iterator pos = m_quCandidateVertices.begin();
- for(; pos != m_quCandidateVertices.end(); ++pos)
- {
- if ((*pos)->getID() == (*cur_neighbor_pos)->getID())
- {
- break;
- }
- }
- if(pos != m_quCandidateVertices.end())
- {
- m_quCandidateVertices.erase(pos);
- }
- m_quCandidateVertices.insert(*cur_neighbor_pos);
- }
- }
-}
-
-void DijkstraShortestPathAlg::clear()
-{
- m_stDeterminedVertices.clear();
- m_mpPredecessorVertex.clear();
- m_mpStartDistanceIndex.clear();
- m_quCandidateVertices.clear();
-}
-
-BasePath* DijkstraShortestPathAlg::update_cost_forward( BaseVertex* vertex )
-{
- double cost = Graph::DISCONNECT;
-
- // 1. get the set of successors of the input vertex
- std::set<BaseVertex*>* adj_vertex_set = new std::set<BaseVertex*>();
- m_pDirectGraph->get_adjacent_vertices(vertex, *adj_vertex_set);
-
- // 2. make sure the input vertex exists in the index
- std::map<BaseVertex*, double>::iterator pos4vertexInStartDistIndex = m_mpStartDistanceIndex.find(vertex);
- if(pos4vertexInStartDistIndex == m_mpStartDistanceIndex.end())
- {
- pos4vertexInStartDistIndex =
- (m_mpStartDistanceIndex.insert(std::make_pair(vertex, Graph::DISCONNECT))).first;
- }
-
- // 3. update the distance from the root to the input vertex if necessary
- for(std::set<BaseVertex*>::const_iterator pos=adj_vertex_set->begin(); pos!=adj_vertex_set->end();++pos)
- {
- // 3.1 get the distance from the root to one successor of the input vertex
- std::map<BaseVertex*, double>::const_iterator cur_vertex_pos = m_mpStartDistanceIndex.find(*pos);
- double distance = cur_vertex_pos == m_mpStartDistanceIndex.end() ?
- Graph::DISCONNECT : cur_vertex_pos->second;
-
- // 3.2 calculate the distance from the root to the input vertex
- distance += m_pDirectGraph->get_edge_weight(vertex, *pos);
-
- // 3.3 update the distance if necessary
- double cost_of_vertex = pos4vertexInStartDistIndex->second;
- if(cost_of_vertex > distance)
- {
- m_mpStartDistanceIndex[vertex] = distance;
- m_mpPredecessorVertex[vertex] = cur_vertex_pos->first;
- cost = distance;
- }
- }
-
- // 4. create the sub_path if exists
- BasePath* sub_path = NULL;
- if(cost < Graph::DISCONNECT)
- {
- std::vector<BaseVertex*> vertex_list;
- vertex_list.push_back(vertex);
-
- std::map<BaseVertex*, BaseVertex*>::const_iterator pos4PredVertexMap =
- m_mpPredecessorVertex.find(vertex);
-
- while(pos4PredVertexMap != m_mpPredecessorVertex.end())
- {
- BaseVertex* pred_vertex_pt = pos4PredVertexMap->second;
- vertex_list.push_back(pred_vertex_pt);
- pos4PredVertexMap = m_mpPredecessorVertex.find(pred_vertex_pt);
- }
-
- sub_path = new BasePath(vertex_list, cost);
- }
- return sub_path;
-}
-
-void DijkstraShortestPathAlg::correct_cost_backward( BaseVertex* vertex )
-{
- // 1. initialize the list of vertex to be updated
- std::vector<BaseVertex*> vertex_pt_list;
- vertex_pt_list.push_back(vertex);
-
- // 2. update the cost of relevant precedents of the input vertex
- while(!vertex_pt_list.empty())
- {
- BaseVertex* cur_vertex_pt = *(vertex_pt_list.begin());
- vertex_pt_list.erase(vertex_pt_list.begin());
-
- double cost_of_cur_vertex = m_mpStartDistanceIndex[cur_vertex_pt];
-
- std::set<BaseVertex*> pre_vertex_set;
- m_pDirectGraph->get_precedent_vertices(cur_vertex_pt, pre_vertex_set);
- for(std::set<BaseVertex*>::const_iterator pos=pre_vertex_set.begin(); pos!=pre_vertex_set.end();++pos)
- {
- std::map<BaseVertex*,double>::const_iterator pos4StartDistIndexMap =
- m_mpStartDistanceIndex.find(*pos);
- double cost_of_pre_vertex = m_mpStartDistanceIndex.end() == pos4StartDistIndexMap ?
- Graph::DISCONNECT : pos4StartDistIndexMap->second;
-
- double fresh_cost = cost_of_cur_vertex + m_pDirectGraph->get_edge_weight(*pos, cur_vertex_pt);
- if(cost_of_pre_vertex > fresh_cost)
- {
- m_mpStartDistanceIndex[*pos] = fresh_cost;
- m_mpPredecessorVertex[*pos] = cur_vertex_pt;
- vertex_pt_list.push_back(*pos);
- }
- }
- }
-}
diff --git a/src/ksp/src/DijkstraShortestPathAlg.h b/src/ksp/src/DijkstraShortestPathAlg.h
deleted file mode 100644
index 2f90d72..0000000
--- a/src/ksp/src/DijkstraShortestPathAlg.h
+++ /dev/null
@@ -1,78 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// DijkstraShortestPathAlg.h
-/// The implementation of Dijkstra algorithm to get the shortest path of
-/// a pair of vertices in a graph.
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 5/30/2010
-///
-/// $Id: DijkstraShortestPathAlg.h 65 2010-09-08 06:48:36Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __DijkstraShortestPathAlg_h
-#define __DijkstraShortestPathAlg_h
-
-#include <map>
-#include <set>
-
-class Graph;
-class BaseVertex;
-class BasePath;
-template < class T > class WeightLess;
-
-class DijkstraShortestPathAlg
-{
-private: // members
-
- Graph* m_pDirectGraph;
-
- std::map<BaseVertex*, double> m_mpStartDistanceIndex;
- std::map<BaseVertex*, BaseVertex*> m_mpPredecessorVertex;
-
- std::set<int> m_stDeterminedVertices;
-
- std::multiset<BaseVertex*, WeightLess<BaseVertex> > m_quCandidateVertices;
-
-public:
- DijkstraShortestPathAlg(Graph* pGraph):m_pDirectGraph(pGraph){}
- ~DijkstraShortestPathAlg(void){clear();}
-
- void clear();
-
- BasePath* get_shortest_path(BaseVertex* source, BaseVertex* sink);
-
- void set_predecessor_vertex(BaseVertex* vt1, BaseVertex* vt2)
- {
- m_mpPredecessorVertex[vt1] = vt2;
- }
-
- double get_start_distance_at(BaseVertex* vertex)
- {
- return m_mpStartDistanceIndex.find(vertex)->second;
- }
-
- void set_start_distance_at(BaseVertex* vertex, double weight)
- {
- m_mpStartDistanceIndex[vertex] = weight;
- }
-
- void get_shortest_path_flower(BaseVertex* root)
- {
- determine_shortest_paths(NULL, root, false);
- }
-
- // The following two methods are prepared for the top-k shortest paths algorithm
- BasePath* update_cost_forward(BaseVertex* vertex);
- void correct_cost_backward(BaseVertex* vertex);
-
-protected:
-
- void determine_shortest_paths(BaseVertex* source, BaseVertex* sink, bool is_source2sink);
-
- void improve2vertex(BaseVertex* cur_vertex_pt, bool is_source2sink);
-
-};
-
-#endif
diff --git a/src/ksp/src/DynamicGraph.h b/src/ksp/src/DynamicGraph.h
deleted file mode 100644
index 1dc14aa..0000000
--- a/src/ksp/src/DynamicGraph.h
+++ /dev/null
@@ -1,88 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// VariableGraph.h
-/// Depict a graph that can change dynamically!
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 6/13/2010
-///
-/// $Id: DynamicGraph.h 58 2010-08-19 07:11:58Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __DynamicGraph_h
-#define __DynamicGraph_h
-
-#include "Graph.h"
-
-using namespace std;
-
-class DynamicGraph : public Graph
-{
- set<int> m_stRemovedVertexIds;
- set<pair<int,int> > m_stRemovedEdge;
-
-public:
- /*DynamicGraph(void){}*/
- DynamicGraph(const string graph_file_name):Graph(graph_file_name){}
- DynamicGraph(const Graph& rGraph):Graph(rGraph){}
- ~DynamicGraph(void){}
-
- void remove_edge(const pair<int,int> edge)
- {
- //m_stRemovedEdge.erase(m_stRemovedEdge.find(edge));
- m_stRemovedEdge.insert(edge);
- }
-
- void remove_vertex(const int vertex_id)
- {
- m_stRemovedVertexIds.insert(vertex_id);
- }
-
- void recover_removed_edges()
- {
- m_stRemovedEdge.clear();
- }
-
- void recover_removed_vertices()
- {
- m_stRemovedVertexIds.clear();
- }
-
- void recover_removed_edge(const pair<int,int> edge)
- {
- m_stRemovedEdge.erase(m_stRemovedEdge.find(edge));
- }
-
- void recover_removed_vertex(int vertex_id)
- {
- m_stRemovedVertexIds.erase(m_stRemovedVertexIds.find(vertex_id));
- }
-
- double get_edge_weight_of_graph(const BaseVertex* source, const BaseVertex* sink)
- {
- return Graph::get_edge_weight(source, sink);
- }
-
- BaseVertex* get_vertex(int id)
- {
- if (m_stRemovedVertexIds.find(id) != m_stRemovedVertexIds.end())
- {
- return NULL;
- }else
- {
- return Graph::get_vertex(id);
- }
- }
-
- void get_vertex_list(vector<BaseVertex*>& vertex_list);
-
- virtual double get_edge_weight(const BaseVertex* source, const BaseVertex* sink);
-
- virtual void get_adjacent_vertices(BaseVertex* vertex, set<BaseVertex*>& vertex_set);
-
- virtual void get_precedent_vertices(BaseVertex* vertex, set<BaseVertex*>& vertex_set);
-
-};
-
-#endif
diff --git a/src/ksp/src/Graph.cpp b/src/ksp/src/Graph.cpp
deleted file mode 100644
index 65f64d6..0000000
--- a/src/ksp/src/Graph.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// Graph.cpp
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 8/18/2010
-///
-/// $Id: Graph.cpp 65 2010-09-08 06:48:36Z yan.qi.asu $
-///////////////////////////////////////////////////////////////////////////////
-
-#include <limits>
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <algorithm>
-#include "GraphElements.h"
-#include "Graph.h"
-
-
-const double Graph::DISCONNECT = (std::numeric_limits<double>::max)();
-
-Graph::Graph(void){
-}
-Graph::Graph( const std::string& file_name )
-{
- _import_from_file(file_name);
-}
-
-Graph::Graph( const Graph& graph )
-{
- m_nVertexNum = graph.m_nVertexNum;
- m_nEdgeNum = graph.m_nEdgeNum;
- m_vtVertices.assign(graph.m_vtVertices.begin(),graph.m_vtVertices.end());
- m_mpFaninVertices.insert(graph.m_mpFaninVertices.begin(),graph.m_mpFaninVertices.end());
- m_mpFanoutVertices.insert(graph.m_mpFanoutVertices.begin(),graph.m_mpFanoutVertices.end());
- m_mpEdgeCodeWeight.insert(graph.m_mpEdgeCodeWeight.begin(),graph.m_mpEdgeCodeWeight.end());
- m_mpVertexIndex.insert(graph.m_mpVertexIndex.begin(),graph.m_mpVertexIndex.end());
-}
-
-Graph::~Graph(void)
-{
- clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// public _import_from_file
-/// Construct the graph by importing the edges from the input file.
-///
-/// @param [in] file_name const std::string & The input graph file
-///
-/// This function doesn't return a value
-///
-/// @remarks The format of the file is as follows:
-/// 1. The first line has an integer as the number of vertices of the graph
-/// 2. Each line afterwards contains a directed edge in the graph:
-/// starting point, ending point and the weight of the edge.
-/// These values are separated by 'white space'.
-///
-/// @see <TODO: insert text here>
-///
-/// @author Yan Qi @date 5/29/2010
-///////////////////////////////////////////////////////////////////////////////
-void Graph::_import_from_file( const std::string& input_file_name )
-{
- std::cout << input_file_name << std::endl;
- const char* file_name = input_file_name.c_str();
-
- //1. Check the validity of the file
- std::ifstream ifs(file_name);
- if (!ifs)
- {
- std::cerr << "The file " << file_name << " can not be opened!" << std::endl;
- exit(1);
- }
-
- //2. Reset the members of the class
- clear();
-
- //3. Start to read information from the input file.
- /// Note the format of the data in the graph file.
- //3.1 The first line has an integer as the number of vertices of the graph
- ifs >> m_nVertexNum;
-
- //3.2 In the following lines, each line contains a directed edge in the graph:
- /// the id of starting point, the id of ending point, the weight of the edge.
- /// These values are separated by 'white space'.
- int start_vertex, end_vertex;
- double edge_weight;
-
- while(ifs >> start_vertex)
- {
- if (start_vertex == -1)
- {
- break;
- }
- ifs >> end_vertex;
- ifs >> edge_weight;
-
- ///3.2.1 construct the vertices
- BaseVertex* start_vertex_pt = get_vertex(start_vertex);
- BaseVertex* end_vertex_pt = get_vertex(end_vertex);
-
- ///3.2.2 add the edge weight
- //// note that the duplicate edge would overwrite the one occurring before.
- m_mpEdgeCodeWeight[get_edge_code(start_vertex_pt, end_vertex_pt)] = edge_weight;
-
- ///3.2.3 update the fan-in or fan-out variables
- //// Fan-in
- get_vertex_set_pt(end_vertex_pt, m_mpFaninVertices)->insert(start_vertex_pt);
-
- //// Fan-out
- get_vertex_set_pt(start_vertex_pt, m_mpFanoutVertices)->insert(end_vertex_pt);
-
- }
-
- m_nVertexNum = m_vtVertices.size();
- m_nEdgeNum = m_mpEdgeCodeWeight.size();
-
- ifs.close();
-}
-
-BaseVertex* Graph::get_vertex( int node_id )
-{
- if (m_stRemovedVertexIds.find(node_id) != m_stRemovedVertexIds.end())
- {
- return NULL;
- }else
- {
- BaseVertex* vertex_pt = NULL;
- const std::map<int, BaseVertex*>::iterator pos = m_mpVertexIndex.find(node_id);
- if (pos == m_mpVertexIndex.end())
- {
- vertex_pt = new BaseVertex();
- vertex_pt->setID(node_id);
- m_mpVertexIndex[node_id] = vertex_pt;
-
- m_vtVertices.push_back(vertex_pt);
- }else
- {
- vertex_pt = pos->second;
- }
-
- return vertex_pt;
- }
-}
-
-void Graph::clear()
-{
- m_nEdgeNum = 0;
- m_nVertexNum = 0;
-
- for(std::map<BaseVertex*, std::set<BaseVertex*>*>::const_iterator pos=m_mpFaninVertices.begin();
- pos!=m_mpFaninVertices.end(); ++pos)
- {
- delete pos->second;
- }
- m_mpFaninVertices.clear();
-
- for(std::map<BaseVertex*, std::set<BaseVertex*>*>::const_iterator pos=m_mpFanoutVertices.begin();
- pos!=m_mpFanoutVertices.end(); ++pos)
- {
- delete pos->second;
- }
- m_mpFanoutVertices.clear();
-
-
- m_mpEdgeCodeWeight.clear();
-
- //clear the list of vertices objects
- for_each(m_vtVertices.begin(), m_vtVertices.end(), DeleteFunc<BaseVertex>());
- m_vtVertices.clear();
- m_mpVertexIndex.clear();
-
- m_stRemovedVertexIds.clear();
- m_stRemovedEdge.clear();
-}
-
-int Graph::get_edge_code( const BaseVertex* start_vertex_pt, const BaseVertex* end_vertex_pt ) const
-{
- /// Note that the computation below works only if
- /// the result is smaller than the maximum of an integer!
- return start_vertex_pt->getID()*m_nVertexNum+end_vertex_pt->getID();
-}
-
-
-std::set<BaseVertex*>* Graph::get_vertex_set_pt( BaseVertex* vertex_, std::map<BaseVertex*, std::set<BaseVertex*>*>& vertex_container_index )
-{
- BaseVertexPt2SetMapIterator pos = vertex_container_index.find(vertex_);
-
- if(pos == vertex_container_index.end())
- {
- std::set<BaseVertex*>* vertex_set = new std::set<BaseVertex*>();
- std::pair<BaseVertexPt2SetMapIterator,bool> ins_pos =
- vertex_container_index.insert(make_pair(vertex_, vertex_set));
-
- pos = ins_pos.first;
- }
-
- return pos->second;
-}
-
-
-double Graph::get_edge_weight( const BaseVertex* source, const BaseVertex* sink )
-{
- int source_id = source->getID();
- int sink_id = sink->getID();
-
- if (m_stRemovedVertexIds.find(source_id) != m_stRemovedVertexIds.end()
- || m_stRemovedVertexIds.find(sink_id) != m_stRemovedVertexIds.end()
- || m_stRemovedEdge.find(std::make_pair(source_id, sink_id)) != m_stRemovedEdge.end())
- {
- return DISCONNECT;
- }else
- {
- return get_original_edge_weight(source, sink);
- }
-}
-
-
-void Graph::get_adjacent_vertices( BaseVertex* vertex, std::set<BaseVertex*>& vertex_set )
-{
- int starting_vt_id = vertex->getID();
-
- if (m_stRemovedVertexIds.find(starting_vt_id) == m_stRemovedVertexIds.end())
- {
- std::set<BaseVertex*>* vertex_pt_set = get_vertex_set_pt(vertex, m_mpFanoutVertices);
- for(std::set<BaseVertex*>::const_iterator pos=(*vertex_pt_set).begin();
- pos != (*vertex_pt_set).end(); ++pos)
- {
- int ending_vt_id = (*pos)->getID();
- if (m_stRemovedVertexIds.find(ending_vt_id) != m_stRemovedVertexIds.end()
- || m_stRemovedEdge.find(std::make_pair(starting_vt_id, ending_vt_id)) != m_stRemovedEdge.end())
- {
- continue;
- }
- //
- vertex_set.insert(*pos);
- }
- }
-}
-
-void Graph::get_precedent_vertices( BaseVertex* vertex, std::set<BaseVertex*>& vertex_set )
-{
- if (m_stRemovedVertexIds.find(vertex->getID()) == m_stRemovedVertexIds.end())
- {
- int ending_vt_id = vertex->getID();
- std::set<BaseVertex*>* pre_vertex_set = get_vertex_set_pt(vertex, m_mpFaninVertices);
- for(std::set<BaseVertex*>::const_iterator pos=(*pre_vertex_set).begin();
- pos != (*pre_vertex_set).end(); ++pos)
- {
- int starting_vt_id = (*pos)->getID();
- if (m_stRemovedVertexIds.find(starting_vt_id) != m_stRemovedVertexIds.end()
- || m_stRemovedEdge.find(std::make_pair(starting_vt_id, ending_vt_id)) != m_stRemovedEdge.end())
- {
- continue;
- }
- //
- vertex_set.insert(*pos);
- }
- }
-}
-
-double Graph::get_original_edge_weight( const BaseVertex* source, const BaseVertex* sink )
-{
- std::map<int, double>::const_iterator pos =
- m_mpEdgeCodeWeight.find(get_edge_code(source, sink));
-
- if (pos != m_mpEdgeCodeWeight.end())
- {
- return pos->second;
- }else
- {
- return DISCONNECT;
- }
-}
diff --git a/src/ksp/src/Graph.h b/src/ksp/src/Graph.h
deleted file mode 100644
index 0ca8cde..0000000
--- a/src/ksp/src/Graph.h
+++ /dev/null
@@ -1,124 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// Graph.h
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 8/18/2010
-///
-/// $Id: Graph.h 65 2010-09-08 06:48:36Z yan.qi.asu $
-///////////////////////////////////////////////////////////////////////////////
-
-
-#ifndef __Graph_h
-#define __Graph_h
-
-#include <set>
-#include <map>
-#include <vector>
-
-#include "BasePath.h"
-
-class BaseVertex;
-
-class Path : public BasePath
-{
-public:
-
- Path(const std::vector<BaseVertex*>& vertex_list, double weight):BasePath(vertex_list,weight){}
-
- // display the content
- void PrintOut(std::ostream& out_stream) const
- {
- out_stream << "Graph Cost: " << m_dWeight << " Length: " << m_vtVertexList.size() << std::endl;
- for(std::vector<BaseVertex*>::const_iterator pos=m_vtVertexList.begin(); pos!=m_vtVertexList.end();++pos)
- {
- out_stream << (*pos)->getID() << " ";
- }
- out_stream << std::endl << "*********************************************" << std::endl;
- }
-};
-
-class Graph
-{
-public: // members
-
- const static double DISCONNECT;
-
- typedef std::set<BaseVertex*>::iterator VertexPtSetIterator;
- typedef std::map<BaseVertex*, std::set<BaseVertex*>*>::iterator BaseVertexPt2SetMapIterator;
-
-protected: // members
-
- // Basic information
- std::map<BaseVertex*, std::set<BaseVertex*>*> m_mpFanoutVertices;
- std::map<BaseVertex*, std::set<BaseVertex*>*> m_mpFaninVertices;
- std::map<int, double> m_mpEdgeCodeWeight;
- std::vector<BaseVertex*> m_vtVertices;
- int m_nEdgeNum;
- int m_nVertexNum;
-
- std::map<int, BaseVertex*> m_mpVertexIndex;
-
- // Members for graph modification
- std::set<int> m_stRemovedVertexIds;
- std::set<std::pair<int,int> > m_stRemovedEdge;
-
-public:
-
- // Constructors and Destructor
- Graph(const std::string& file_name);
- Graph(const Graph& rGraph);
- Graph();
- ~Graph(void);
-
- void clear();
-
- BaseVertex* get_vertex(int node_id);
-
- int get_edge_code(const BaseVertex* start_vertex_pt, const BaseVertex* end_vertex_pt) const;
- std::set<BaseVertex*>* get_vertex_set_pt(BaseVertex* vertex_, std::map<BaseVertex*, std::set<BaseVertex*>*>& vertex_container_index);
-
- double get_original_edge_weight(const BaseVertex* source, const BaseVertex* sink);
-
- double get_edge_weight(const BaseVertex* source, const BaseVertex* sink);
- void get_adjacent_vertices(BaseVertex* vertex, std::set<BaseVertex*>& vertex_set);
- void get_precedent_vertices(BaseVertex* vertex, std::set<BaseVertex*>& vertex_set);
-
- /// Methods for changing graph
- void remove_edge(const std::pair<int,int> edge)
- {
- m_stRemovedEdge.insert(edge);
- }
-
- void remove_vertex(const int vertex_id)
- {
- m_stRemovedVertexIds.insert(vertex_id);
- }
-
- void recover_removed_edges()
- {
- m_stRemovedEdge.clear();
- }
-
- void recover_removed_vertices()
- {
- m_stRemovedVertexIds.clear();
- }
-
- void recover_removed_edge(const std::pair<int,int> edge)
- {
- m_stRemovedEdge.erase(m_stRemovedEdge.find(edge));
- }
-
- void recover_removed_vertex(int vertex_id)
- {
- m_stRemovedVertexIds.erase(m_stRemovedVertexIds.find(vertex_id));
- }
-
-private:
- void _import_from_file(const std::string& file_name);
-
-};
-
-#endif
diff --git a/src/ksp/src/GraphElements.h b/src/ksp/src/GraphElements.h
deleted file mode 100644
index e07b3f6..0000000
--- a/src/ksp/src/GraphElements.h
+++ /dev/null
@@ -1,92 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// GraphElements.h
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 5/28/2010
-///
-/// $Id: GraphElements.h 65 2010-09-08 06:48:36Z yan.qi.asu $
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __GraphElements_h
-#define __GraphElements_h
-
-#include <string>
-#include <iostream>
-
-template<class T>
-class WeightGreater
-{
-public:
- // Determine priority.
- bool operator()(const T& a, const T& b) const
- {
- return a.Weight() > b.Weight();
- }
-
- bool operator()(const T* a, const T* b) const
- {
- return a->Weight() > b->Weight();
- }
-};
-
-template<class T>
-class WeightLess
-{
-public:
- // Determine priority.
- bool operator()(const T& a, const T& b) const
- {
- return a.Weight() < b.Weight();
- }
-
- bool operator()(const T* a, const T* b) const
- {
- return a->Weight() < b->Weight();
- }
-};
-
-//////////////////////////////////////////////////////////////////////////
-// A class for the object deletion
-//////////////////////////////////////////////////////////////////////////
-template<class T>
-class DeleteFunc
-{
-public:
- void operator()(const T* it) const
- {
- delete it;
- }
-};
-
-
-
-/**************************************************************************
-* BaseVertex
-* <TODO: insert class description here>
-*
-*
-* @remarks <TODO: insert remarks here>
-*
-* @author Yan Qi @date 6/6/2010
-**************************************************************************/
-class BaseVertex
-{
- size_t m_nID;
- double m_dWeight;
-
-public:
-
- size_t getID() const { return m_nID; }
- void setID(size_t ID_) { m_nID = ID_; }
-
- double Weight() const { return m_dWeight; }
- void Weight(double val) { m_dWeight = val; }
-
- void PrintOut(std::ostream& out_stream)
- {
- out_stream << m_nID;
- }
-};
-#endif
diff --git a/src/ksp/src/HeaderTest.cpp b/src/ksp/src/HeaderTest.cpp
deleted file mode 100644
index baf4406..0000000
--- a/src/ksp/src/HeaderTest.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <cstdlib>
-#include "BaseGraph.h"
-#include "BasePath.h"
-#include "DijkstraShortestPathAlg.h"
-#include "GraphElements.h"
-#include "Graph.h"
-#include "YenTopKShortestPathsAlg.h"
-
-int main()
-{
- return EXIT_SUCCESS;
-}
diff --git a/src/ksp/src/KSPDriver.cpp b/src/ksp/src/KSPDriver.cpp
deleted file mode 100644
index b822af1..0000000
--- a/src/ksp/src/KSPDriver.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <map>
-#include "KSPGraph.h"
-#include "YenTopKShortestPathsAlg.h"
-#include "ksp.h"
-#include "KSPDriver.h"
-static ksp_path_element_t * dpPrint(KSPGraph *theGraph,BasePath *thePath, ksp_path_element_t *ksp_path, int *path_count,int,int *);
-
-#define MEM_OSET 10
-
-int doKpaths(ksp_edge_t * edges,int total_tuples,int start_vertex,int end_vertex,
- int no_paths, bool has_reverse_cost,
- ksp_path_element_t **path, int *path_count,
- char ** err_msg){
- int i;
- int mem_offset;
- ksp_path_element_t *ksp_path;
- bool no_reverse=false;
-
- std::map<int,int>vertexs;
- KSPGraph theGraph = KSPGraph();
- // Only include routes who have a cost great or equal zero
- // represent one way values
- for(i=0; i<total_tuples; i++) {
- // count the total number of vertexs
- if(edges[i].cost >=0 ){
- vertexs[edges[i].source]=1;
- vertexs[edges[i].target]=1;
- }
- }
-
-
-
- theGraph.StartLoad(vertexs.size());
-
-
- for(i=0;i<total_tuples;i++){
- if(edges[i].cost >= 0 ){
- theGraph.AddData(edges[i].source,edges[i].target,edges[i].cost,edges[i].id);
- if( has_reverse_cost && edges[i].reverse_cost >= 0){
- theGraph.AddData(edges[i].target,edges[i].source,edges[i].reverse_cost,edges[i].id);
- no_reverse=true;
- }
- }
-
- }
- // avoid a nasty bug, if no reverse paths are define and reverse mode
- // is set, an endless loop is entered.
- if(no_reverse == false && has_reverse_cost){
- *err_msg = (char *) "No reverse paths defined and reverse cost selected";
- return -1;
- }
- theGraph.EndLoad();
- YenTopKShortestPathsAlg yenAlg(theGraph, theGraph.get_vertex(start_vertex),theGraph.get_vertex(end_vertex));
-
- i=0;
-
- ksp_path=0;
- mem_offset=MEM_OSET;
- ksp_path=get_ksp_memory(mem_offset,ksp_path);
-
- *path_count=0;
- if( no_paths <= 0 ) { // print all paths
-
- while(yenAlg.has_next()) {
- i++;
- ksp_path=dpPrint(&theGraph,yenAlg.next(),ksp_path,path_count,i,&mem_offset);
- }
- } else {
- std::vector< BasePath* > paths;
- yenAlg.get_shortest_paths( theGraph.get_vertex(start_vertex), theGraph.get_vertex(end_vertex), no_paths, paths );
- std::vector< BasePath* >::const_iterator it = paths.begin();
- int i=0;
- while( it != paths.end() ) {
-
- ksp_path=dpPrint(&theGraph,*it,ksp_path,path_count,i,&mem_offset);
- ++it;
- i++;
- }
-
- }
-
- *path=ksp_path;
- return 1;
-}
-
-static ksp_path_element_t* dpPrint(KSPGraph *theGraph,BasePath *thePath, ksp_path_element_t *path, int *path_count,int cnt,int *memCnt){
-
- int i;
- for(i=0;i<thePath->length();i++){
-
- if((*path_count)+1 >= *memCnt){
- (*memCnt) += MEM_OSET;
- path=get_ksp_memory(*memCnt,path);
- }
- BaseVertex bv= *thePath->GetVertex(i);
- path[*path_count].route_id= cnt;
- path[*path_count].cost= 0.0;
- path[*path_count].edge_id= -1;
- path[*path_count].vertex_id= bv.getID();
- if((i+1 )< thePath->length()){
- BaseVertex destbv= *thePath->GetVertex(i+1);
- (path)[*path_count].cost= theGraph->get_original_edge_weight(&bv, &destbv);
- (path)[*path_count].edge_id= theGraph->get_edge_value(&bv, &destbv);
-
- }
- (*path_count)++;
- }
- return path;
-}
diff --git a/src/ksp/src/KSPDriver.h b/src/ksp/src/KSPDriver.h
deleted file mode 100644
index 6b41c0a..0000000
--- a/src/ksp/src/KSPDriver.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifdef __cplusplus
-
-extern "C" {
-
-#endif
-int doKpaths(ksp_edge_t * edges, int total_tuples,int start_vertex,int end_vertex,
- int no_paths, bool has_reverse_cost,
- ksp_path_element_t **ksp_path, int *path_count,
- char ** err_msg);
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/ksp/src/KSPGraph.cpp b/src/ksp/src/KSPGraph.cpp
deleted file mode 100644
index f5b9858..0000000
--- a/src/ksp/src/KSPGraph.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include <limits>
-#include <set>
-#include <map>
-#include <queue>
-#include <string>
-#include <vector>
-#include <fstream>
-#include <iostream>
-#include <algorithm>
-#include "GraphElements.h"
-#include "KSPGraph.h"
-#include "Graph.h"
-#include "YenTopKShortestPathsAlg.h"
-extern "C" {
-#include "postgres.h"
-#include "executor/spi.h"
-#include "funcapi.h"
-#include "catalog/pg_type.h"
-#include "fmgr.h"
-#include "ksp.h"
- extern void DBG(const char *format, ...);
-}
-#undef DEBUG
-/*#define DEBUG 1*/
-
-#ifndef _MSC_VER
-#ifdef DEBUG
-#define DBG(format, arg...) \
- elog(NOTICE, format , ## arg)
-#else
-#define DBG(format, arg...) do { ; } while (0)
-#endif
-#else // _MSC_VER
-extern void DBG(const char *format, ...)
-{
-#if DEBUG
- va_list ap;
- char msg[256];
- va_start(ap, format);
- _vsprintf_p(msg, 256, format, ap);
- va_end(ap);
- elog(NOTICE, msg);
-#endif
-}
-#endif // _MSC_VER
-
-KSPGraph::KSPGraph(void){
-}
-KSPGraph::~KSPGraph(void){
-}
-KSPGraph::KSPGraph(const Graph& g):Graph(g){
-}
-KSPGraph::KSPGraph(const std::string & f):Graph(f){
-}
-
-void KSPGraph::clear(void){
- Graph::clear();
- m_mpEdgeValues.clear();;
-
-}
-void KSPGraph::StartLoad(const int len ){
- clear();
- m_nVertexNum=len;
-}
-/*
- * a rewrite of input_from file, but one line at the time
- */
-void KSPGraph::AddData(const int start_vertex,const int end_vertex ,const float edge_weight,const int edge_id){
-
- DBG("Start %d Target %d Edge %f",start_vertex,end_vertex, edge_weight);
- ///3.2.1 construct the vertices
- BaseVertex* start_vertex_pt = get_vertex(start_vertex);
- BaseVertex* end_vertex_pt = get_vertex(end_vertex);
-
- ///3.2.2 add the edge weight
- //// note that the duplicate edge would overwrite the one occurring before.
-
- m_mpEdgeCodeWeight[get_edge_code(start_vertex_pt, end_vertex_pt)] = edge_weight;
-
- ///3.2.3 update the fan-in or fan-out variables
- //// Fan-in
- get_vertex_set_pt(end_vertex_pt, m_mpFaninVertices)->insert(start_vertex_pt);
-
- //// Fan-out
- get_vertex_set_pt(start_vertex_pt, m_mpFanoutVertices)->insert(end_vertex_pt);
-
- m_mpEdgeValues[get_edge_code(start_vertex_pt, end_vertex_pt)] = edge_id;
-}
-void KSPGraph::EndLoad(void){
- m_nVertexNum = m_vtVertices.size();
- m_nEdgeNum = m_mpEdgeCodeWeight.size();
-}
-
-int KSPGraph::get_edge_value( const BaseVertex* source, const BaseVertex* sink )
-{
- std::map<int, int>::const_iterator pos =
- m_mpEdgeValues.find(get_edge_code(source, sink));
-
- if (pos != m_mpEdgeValues.end())
- {
- return pos->second;
- }else
- {
- return DISCONNECT;
- }
-}
diff --git a/src/ksp/src/KSPGraph.h b/src/ksp/src/KSPGraph.h
deleted file mode 100644
index 1aade7f..0000000
--- a/src/ksp/src/KSPGraph.h
+++ /dev/null
@@ -1,23 +0,0 @@
-
-#ifndef __KSPGraph_h
-#define __KSPGraph_h
-
-#include "Graph.h"
-
-class KSPGraph : public Graph {
-public:
- ~KSPGraph();
- KSPGraph(const Graph&);
- KSPGraph();
- KSPGraph(const std::string &);
- void AddData(const int source , const int target , const float cost,const int id);
- void StartLoad(const int );
- void EndLoad();
- void clear();
-
- int get_edge_value(const BaseVertex* source, const BaseVertex* sink ) ;
-protected:
- std::map <int,int> m_mpEdgeValues;
-
-};
-#endif //__KSPGraph
diff --git a/src/ksp/src/TGraph.h b/src/ksp/src/TGraph.h
deleted file mode 100644
index 1e4f136..0000000
--- a/src/ksp/src/TGraph.h
+++ /dev/null
@@ -1,154 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// TGraph.h
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 5/29/2010
-///
-/// $Id: TGraph.h 47 2010-06-07 06:45:09Z yan.qi.asu $
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __TGraph_h
-#define __TGraph_h
-
-using namespace std;
-
-template<typename T>
-class TGraph
-{
-public: // members
-
- const static double DISCONNECT;
-
- typedef GVertex<T> TVertex;
- typedef typename set<TVertex*>::iterator VertexPtSetIterator;
- typedef typename map<TVertex*, set<TVertex*>*>::iterator TVertexPt2SetMapIterator;
-
-protected: // members
-
- map<TVertex*, set<TVertex*>*> m_mpFanoutVertices;
- map<TVertex*, set<TVertex*>*> m_mpFaninVertices;
- map<int, double> m_mpEdgeCodeWeight;
- //set<T> m_stVertices;
- map<T, TVertex*> m_mpVertexIndex;
- vector<TVertex*> m_vtVertices;
- int m_nEdgeNum;
- int m_nVertexNum;
-
-
-public: // methods
-
- virtual ~TGraph(void){clear();}
-
- void clear()
- {
- m_nEdgeNum = 0;
- m_nVertexNum = 0;
-
- for(map<TVertex*, set<TVertex*>*>::const_iterator pos=m_mpFaninVertices.begin();
- pos!=m_mpFaninVertices.end(); ++pos)
- {
- delete pos->second;
- }
- m_mpFaninVertices.clear();
-
- for(map<TVertex*, set<TVertex*>*>::const_iterator pos=m_mpFanoutVertices.begin();
- pos!=m_mpFanoutVertices.end(); ++pos)
- {
- delete pos->second;
- }
- m_mpFanoutVertices.clear();
-
-
- m_mpEdgeCodeWeight.clear();
-
- /*m_stVertices.clear();*/
- m_mpVertexIndex.clear();
-
- //clear the list of vertices objects
- for_each(m_vtVertices.begin(), m_vtVertices.end(), DeleteFunc<TVertex>());
- m_vtVertices.clear();
- }
-
-protected: // methods
-
- int get_edge_code(const TVertex* start_vertex_pt, const TVertex* end_vertex_pt) const
- {
- /// Note that the computation below works only if
- /// the result is smaller than the maximum of an integer!
- return start_vertex_pt->getID()*m_nVertexNum+end_vertex_pt->getID();
- }
-
-public:
-
- double get_edge_weight(const TVertex* start_vertex_pt, const TVertex* end_vertex_pt) const
- {
- map<int, double>::const_iterator pos =
- m_mpEdgeCodeWeight.find(get_edge_code(start_vertex_pt, end_vertex_pt));
-
- if (pos != m_mpEdgeCodeWeight.end())
- {
- return pos->second;
- }
-
- return DISCONNECT;
- }
-
- TVertex* get_vertex_by_ID(int id) const
- {
- return m_vtVertices.at(id);
- }
-
- TVertex* get_vertex(T node_)
- {
- TVertex* vertex_pt = NULL;
- const map<T, TVertex*>::iterator pos = m_mpVertexIndex.find(node_);
- if (pos == m_mpVertexIndex.end())
- {
- int vertex_id = m_vtVertices.size();
- vertex_pt = new TVertex(node_);
- vertex_pt->setID(vertex_id);
- m_vtVertices.push_back(vertex_pt);
- m_mpVertexIndex.insert(make_pair(node_, vertex_pt));
- }else
- {
- vertex_pt = m_vtVertices.at(pos->second->getID());
- }
-
- return vertex_pt;
- }
-
- set<TVertex*>* get_precedent_vertex_set(TVertex* vertex)
- {
- return get_vertex_set_pt(vertex, m_mpFaninVertices);
- }
-
- set<TVertex*>* get_adjacent_vertex_set(TVertex* vertex)
- {
- return get_vertex_set_pt(vertex, m_mpFanoutVertices);
- }
-
- set<TVertex*>* get_vertex_set_pt(TVertex* vertex_,
- map<TVertex*, set<TVertex*>*>& vertex_container_index)
- {
- TVertexPt2SetMapIterator pos = vertex_container_index.find(vertex_);
-
- if(pos == vertex_container_index.end())
- {
- set<TVertex*>* vertex_set = new set<TVertex*>();
- pair<TVertexPt2SetMapIterator,bool> ins_pos =
- vertex_container_index.insert(make_pair(vertex_, vertex_set));
-
- pos = ins_pos.first;
- }
-
- return pos->second;
- }
-
-};
-
-template<typename T>
-const double TGraph<T>::DISCONNECT = (numeric_limits<double>::max)();
-
-#endif
diff --git a/src/ksp/src/TPath.h b/src/ksp/src/TPath.h
deleted file mode 100644
index ac938ca..0000000
--- a/src/ksp/src/TPath.h
+++ /dev/null
@@ -1,46 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// TPath.h
-/// <TODO: insert file description here>
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 5/30/2010
-///
-/// $Id: TPath.h 40 2010-05-31 07:15:39Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __TPath_h
-#define __TPath_h
-
-template<typename T>
-class TPath
-{
- int m_nLength;
- double m_dWeight;
- std::vector<GVertex<T>*> m_vtVertexList;
-
-public:
- TPath(const std::vector<GVertex<T>*> vertex_list, double weight):m_dWeight(weight)
- {
- m_vtVertexList.assign(vertex_list.begin(), vertex_list.end());
- m_nLength = m_vtVertexList.size();
- };
- ~TPath(void){}
-
- double Weight() const { return m_dWeight; }
- void Weight(double val) { m_dWeight = val; }
-
- // display the content
- void PrintOut(std::ostream& out_stream) const
- {
- out_stream << "Tpath Cost: " << m_dWeight << " Length: " << m_vtVertexList.size() << std::endl;
- //std::copy(m_vtVertexList.begin(), m_vtVertexList.end(), std::ostream_iterator<int>(out_stream, " "));
- for(std::vector<GVertex<T>*>::const_iterator pos=m_vtVertexList.begin(); pos!=m_vtVertexList.end();++pos)
- {
- out_stream << (*pos)->getNode() << " ";
- }
- out_stream << std::endl << "*********************************************" << std::endl;
- }
-};
-#endif
diff --git a/src/ksp/src/VspGraph.h b/src/ksp/src/VspGraph.h
deleted file mode 100644
index 4a74347..0000000
--- a/src/ksp/src/VspGraph.h
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-using namespace std;
-
-class VspGraph : public Graph {
-
-
-};
diff --git a/src/ksp/src/YenTopKShortestPathsAlg.cpp b/src/ksp/src/YenTopKShortestPathsAlg.cpp
deleted file mode 100644
index 56d0a35..0000000
--- a/src/ksp/src/YenTopKShortestPathsAlg.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// YenTopKShortestPathsAlg.cpp
-/// The implementation of Yen's algorithm to get the top k shortest paths
-/// connecting a pair of vertices in a graph.
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 7/10/2010
-///
-/// $Id: YenTopKShortestPathsAlg.cpp 65 2010-09-08 06:48:36Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#include <set>
-#include <map>
-#include <queue>
-#include <vector>
-#include "GraphElements.h"
-#include "Graph.h"
-#include "DijkstraShortestPathAlg.h"
-#include "YenTopKShortestPathsAlg.h"
-
-void YenTopKShortestPathsAlg::clear()
-{
- m_nGeneratedPathNum = 0;
- m_mpDerivationVertexIndex.clear();
- m_vResultList.clear();
- m_quPathCandidates.clear();
-}
-
-void YenTopKShortestPathsAlg::_init()
-{
- clear();
- if (m_pSourceVertex != NULL && m_pTargetVertex != NULL)
- {
- BasePath* pShortestPath = get_shortest_path(m_pSourceVertex, m_pTargetVertex);
- if (pShortestPath != NULL && pShortestPath->length() > 1)
- {
- m_quPathCandidates.insert(pShortestPath);
- m_mpDerivationVertexIndex[pShortestPath] = m_pSourceVertex;
- }
- }
-}
-
-BasePath* YenTopKShortestPathsAlg::get_shortest_path( BaseVertex* pSource, BaseVertex* pTarget )
-{
- DijkstraShortestPathAlg dijkstra_alg(m_pGraph);
- return dijkstra_alg.get_shortest_path(pSource, pTarget);
-}
-
-bool YenTopKShortestPathsAlg::has_next()
-{
- return !m_quPathCandidates.empty();
-}
-
-BasePath* YenTopKShortestPathsAlg::next()
-{
- //1. Prepare for removing vertices and arcs
- BasePath* cur_path = *(m_quPathCandidates.begin());//m_quPathCandidates.top();
-
- //m_quPathCandidates.pop();
- m_quPathCandidates.erase(m_quPathCandidates.begin());
- m_vResultList.push_back(cur_path);
-
- size_t count = m_vResultList.size();
-
- BaseVertex* cur_derivation_pt = m_mpDerivationVertexIndex.find(cur_path)->second;
- std::vector<BaseVertex*> sub_path_of_derivation_pt;
- cur_path->SubPath(sub_path_of_derivation_pt, cur_derivation_pt);
- size_t sub_path_length = sub_path_of_derivation_pt.size();
-
- //2. Remove the vertices and arcs in the graph
- for (size_t ii=0; ii<count-1; ++ii)
- {
- BasePath* cur_result_path = m_vResultList.at(ii);
- std::vector<BaseVertex*> cur_result_sub_path_of_derivation_pt;
-
- if (!cur_result_path->SubPath(cur_result_sub_path_of_derivation_pt, cur_derivation_pt)) continue;
-
- if (sub_path_length != cur_result_sub_path_of_derivation_pt.size()) continue;
-
- bool is_equal = true;
- for (size_t i=0; i<sub_path_length; ++i)
- {
- if (sub_path_of_derivation_pt.at(i) != cur_result_sub_path_of_derivation_pt.at(i))
- {
- is_equal = false;
- break;
- }
- }
- if (!is_equal) continue;
-
- //
- BaseVertex* cur_succ_vertex = cur_result_path->GetVertex(sub_path_length+1);
- m_pGraph->remove_edge(std::make_pair(cur_derivation_pt->getID(), cur_succ_vertex->getID()));
- }
-
- //2.1 remove vertices and edges along the current result
- int path_length = cur_path->length();
- for(int i=0; i<path_length-1; ++i)
- {
- m_pGraph->remove_vertex(cur_path->GetVertex(i)->getID());
- m_pGraph->remove_edge(std::make_pair(
- cur_path->GetVertex(i)->getID(), cur_path->GetVertex(i+1)->getID()));
- }
-
- //3. Calculate the shortest tree rooted at target vertex in the graph
- DijkstraShortestPathAlg reverse_tree(m_pGraph);
- reverse_tree.get_shortest_path_flower(m_pTargetVertex);
-
- //4. Recover the deleted vertices and update the cost and identify the new candidates results
- bool is_done = false;
- for(int i=path_length-2; i>=0 && !is_done; --i)
- {
- //4.1 Get the vertex to be recovered
- BaseVertex* cur_recover_vertex = cur_path->GetVertex(i);
- m_pGraph->recover_removed_vertex(cur_recover_vertex->getID());
-
- //4.2 Check if we should stop continuing in the next iteration
- if (cur_recover_vertex->getID() == cur_derivation_pt->getID())
- {
- is_done = true;
- }
-
- //4.3 Calculate cost using forward star form
- BasePath* sub_path = reverse_tree.update_cost_forward(cur_recover_vertex);
-
- //4.4 Get one candidate result if possible
- if (sub_path != NULL)
- {
- ++m_nGeneratedPathNum;
-
- //4.4.1 Get the prefix from the concerned path
- double cost = 0;
- reverse_tree.correct_cost_backward(cur_recover_vertex);
-
- std::vector<BaseVertex*> pre_path_list;
- for (int j=0; j<path_length; ++j)
- {
- BaseVertex* cur_vertex = cur_path->GetVertex(j);
- if (cur_vertex->getID() == cur_recover_vertex->getID())
- {
- //j = path_length;
- break;
- }else
- {
- cost += m_pGraph->get_original_edge_weight(
- cur_path->GetVertex(j), cur_path->GetVertex(1+j));
- pre_path_list.push_back(cur_vertex);
- }
- }
- //
- for (size_t j=0; j<sub_path->length(); ++j)
- {
- pre_path_list.push_back(sub_path->GetVertex(j));
- }
-
- //4.4.2 Compose a candidate
- sub_path = new Path(pre_path_list, cost+sub_path->Weight());
-
- //4.4.3 Put it in the candidate pool if new
- if (m_mpDerivationVertexIndex.find(sub_path) == m_mpDerivationVertexIndex.end())
- {
- m_quPathCandidates.insert(sub_path);
- m_mpDerivationVertexIndex[sub_path] = cur_recover_vertex;
- }
- }
-
- //4.5 Restore the edge
- BaseVertex* succ_vertex = cur_path->GetVertex(i+1);
- m_pGraph->recover_removed_edge(std::make_pair(cur_recover_vertex->getID(), succ_vertex->getID()));
-
- //4.6 Update cost if necessary
- double cost_1 = m_pGraph->get_edge_weight(cur_recover_vertex, succ_vertex)
- + reverse_tree.get_start_distance_at(succ_vertex);
-
- if (reverse_tree.get_start_distance_at(cur_recover_vertex) > cost_1)
- {
- reverse_tree.set_start_distance_at(cur_recover_vertex, cost_1);
- reverse_tree.set_predecessor_vertex(cur_recover_vertex, succ_vertex);
- reverse_tree.correct_cost_backward(cur_recover_vertex);
- }
- }
-
- //5. Restore everything
- m_pGraph->recover_removed_edges();
- m_pGraph->recover_removed_vertices();
-
- return cur_path;
-}
-
-void YenTopKShortestPathsAlg::get_shortest_paths( BaseVertex* pSource,
- BaseVertex* pTarget, int top_k, std::vector<BasePath*>& result_list)
-{
- m_pSourceVertex = pSource;
- m_pTargetVertex = pTarget;
-
- _init();
- int count = 0;
- while (has_next() && count < top_k)
- {
- next();
- ++count;
- }
-
- result_list.assign(m_vResultList.begin(),m_vResultList.end());
-}
diff --git a/src/ksp/src/YenTopKShortestPathsAlg.h b/src/ksp/src/YenTopKShortestPathsAlg.h
deleted file mode 100644
index 010b0db..0000000
--- a/src/ksp/src/YenTopKShortestPathsAlg.h
+++ /dev/null
@@ -1,67 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-/// YenTopKShortestPathsAlg.h
-/// The implementation of Yen's algorithm to get the top k shortest paths
-/// connecting a pair of vertices in a graph.
-///
-/// @remarks <TODO: insert remarks here>
-///
-/// @author Yan Qi @date 7/10/2010
-///
-/// $Id: YenTopKShortestPathsAlg.h 65 2010-09-08 06:48:36Z yan.qi.asu $
-///
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __YenTopKShortestPathsAlg_h
-#define __YenTopKShortestPathsAlg_h
-
-#include <vector>
-#include <map>
-#include <set>
-
-class Graph;
-class BasePath;
-template < class T > class WeightLess;
-
-class YenTopKShortestPathsAlg
-{
- Graph* m_pGraph;
-
- std::vector<BasePath*> m_vResultList;
- std::map<BasePath*, BaseVertex*> m_mpDerivationVertexIndex;
- std::multiset<BasePath*, WeightLess<BasePath> > m_quPathCandidates;
-
- BaseVertex* m_pSourceVertex;
- BaseVertex* m_pTargetVertex;
-
- int m_nGeneratedPathNum;
-
-private:
-
- void _init();
-
-public:
-
- YenTopKShortestPathsAlg(const Graph& graph)
- {
- YenTopKShortestPathsAlg(graph, NULL, NULL);
- }
-
- YenTopKShortestPathsAlg(const Graph& graph, BaseVertex* pSource, BaseVertex* pTarget)
- :m_pSourceVertex(pSource), m_pTargetVertex(pTarget)
- {
- m_pGraph = new Graph(graph);
- _init();
- }
-
- ~YenTopKShortestPathsAlg(void){clear();}
-
- void clear();
- bool has_next();
- BasePath* next();
-
- BasePath* get_shortest_path(BaseVertex* pSource, BaseVertex* pTarget);
- void get_shortest_paths(BaseVertex* pSource, BaseVertex* pTarget, int top_k,
- std::vector<BasePath*>&);
-};
-
-#endif
diff --git a/src/ksp/src/ksp.c b/src/ksp/src/ksp.c
index 0308daf..f3b54e5 100644
--- a/src/ksp/src/ksp.c
+++ b/src/ksp/src/ksp.c
@@ -1,23 +1,27 @@
-/*
- * kShortest path algorithm for PostgreSQL
- *
- * Copyright (c) 2011 Dave Potts
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+
+// #define DEBUG 1
+#include <unistd.h>
#include "postgres.h"
#include "executor/spi.h"
@@ -28,179 +32,41 @@
#include "access/htup_details.h"
#endif
-#include "ksp.h"
-#include "KSPDriver.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/postgres_connection.h"
+#include "./ksp.h"
+#include "./ksp_driver.h"
#ifndef _MSC_VER
Datum kshortest_path(PG_FUNCTION_ARGS);
-#else // _MSC_VER
+#else // _MSC_VER
PGDLLEXPORT Datum kshortest_path(PG_FUNCTION_ARGS);
-#endif // _MSC_VER
-
-#undef DEBUG
+#endif // _MSC_VER
-#ifndef _MSC_VER
-#ifdef DEBUG
-#define DBG(format, arg...) \
- elog(NOTICE, format , ## arg)
-#else
-#define DBG(format, arg...) do { ; } while (0)
-#endif
-#else // _MSC_VER
-extern void DBG(const char *format, ...)
-{
-#if DEBUG
- va_list ap;
- char msg[256];
- va_start(ap, format);
- _vsprintf_p(msg, 256, format, ap);
- va_end(ap);
- elog(NOTICE, msg);
-#endif
-}
-#endif // _MSC_VER
-
-
-#ifdef PG_MODULE_MAGIC
+#ifndef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
-static char *
-text2char(text *in)
-{
- char *out = palloc(VARSIZE(in));
-
- memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
- out[VARSIZE(in) - VARHDRSZ] = '\0';
- return out;
-}
-
-static int ksp_finish(int code, int ret)
-{
- code = SPI_finish();
- if (code != SPI_OK_FINISH )
- {
- elog(ERROR,"couldn't disconnect from SPI");
- return -1 ;
- }
- return ret;
-}
-
-static int
-ksp_fetch_edge_columns(SPITupleTable *tuptable, ksp_edge_columns_t *edge_columns,
- bool has_reverse_cost)
-{
- edge_columns->id = SPI_fnumber(SPI_tuptable->tupdesc, "id");
- edge_columns->source = SPI_fnumber(SPI_tuptable->tupdesc, "source");
- edge_columns->target = SPI_fnumber(SPI_tuptable->tupdesc, "target");
- edge_columns->cost = SPI_fnumber(SPI_tuptable->tupdesc, "cost");
- if (edge_columns->id == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->source == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->target == SPI_ERROR_NOATTRIBUTE ||
- edge_columns->cost == SPI_ERROR_NOATTRIBUTE)
- {
- elog(ERROR, "Error, query must return columns "
- "'id', 'source', 'target' and 'cost'");
- return -1;
- }
-
- if (SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->source) != INT4OID ||
- SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->target) != INT4OID ||
- SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->cost) != FLOAT8OID)
- {
- elog(ERROR, "Error, columns 'source', 'target' must be of type int4, 'cost' must be of type float8");
- return -1;
- }
-
- DBG("columns: id %i source %i target %i cost %f",
- edge_columns->id, edge_columns->source,
- edge_columns->target, edge_columns->cost);
-
- if (has_reverse_cost)
- {
- edge_columns->reverse_cost = SPI_fnumber(SPI_tuptable->tupdesc,
- "reverse_cost");
-
- if (edge_columns->reverse_cost == SPI_ERROR_NOATTRIBUTE)
- {
- elog(ERROR, "Error, reverse_cost is used, but query did't return "
- "'reverse_cost' column");
- return -1;
- }
-
- if (SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->reverse_cost)
- != FLOAT8OID)
- {
- elog(ERROR, "Error, columns 'reverse_cost' must be of type float8");
- return -1;
- }
-
- DBG("columns: reverse_cost cost %f", edge_columns->reverse_cost);
- }
-
- return 0;
-}
-
-void
-ksp_fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc,
- ksp_edge_columns_t *edge_columns, ksp_edge_t *target_edge)
-{
- Datum binval;
- bool isnull;
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->id, &isnull);
- if (isnull)
- elog(ERROR, "id contains a null value");
- target_edge->id = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->source, &isnull);
- if (isnull)
- elog(ERROR, "source contains a null value");
- target_edge->source = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->target, &isnull);
- if (isnull)
- elog(ERROR, "target contains a null value");
- target_edge->target = DatumGetInt32(binval);
-
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->cost, &isnull);
- if (isnull)
- elog(ERROR, "cost contains a null value");
- target_edge->cost = DatumGetFloat8(binval);
-
- if (edge_columns->reverse_cost != -1)
- {
- binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->reverse_cost,
- &isnull);
- if (isnull)
- elog(ERROR, "reverse_cost contains a null value");
- target_edge->reverse_cost = DatumGetFloat8(binval);
- }
-}
-
-
PG_FUNCTION_INFO_V1(kshortest_path);
#ifndef _MSC_VER
Datum
-#else // _MSC_VER
+#else // _MSC_VER
PGDLLEXPORT Datum
-#endif // _MSC_VER
-kshortest_path(PG_FUNCTION_ARGS)
-{
+#endif // _MSC_VER
+kshortest_path(PG_FUNCTION_ARGS) {
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tuple_desc;
- ksp_path_element_t *path;
- void * toDel;
+ pgr_path_element3_t *path;
+// void * toDel;
/* stuff done only on the first call of the function */
- if (SRF_IS_FIRSTCALL())
- {
+ if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int path_count = 0;
- int ret;
+ path = NULL;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
@@ -209,37 +75,33 @@ kshortest_path(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- ret = compute_kshortest_path(text2char(PG_GETARG_TEXT_P(0)), /* SQL string */
- PG_GETARG_INT32(1), /* source id */
- PG_GETARG_INT32(2), /* target_id */
- PG_GETARG_INT32(3), /* number of paths */
- PG_GETARG_BOOL(4), /* has reverse_cost */
- &path,
- &path_count);
- toDel=path;
-#ifdef DEBUG
- if (ret >= 0)
- {
- int i;
-
- for (i = 0; i < path_count; i++)
- {
- DBG("Step %i route_id %d ", i, path[i].route_id);
- DBG(" vertex_id %d ", path[i].vertex_id);
- DBG(" edge_id %d ", path[i].edge_id);
- DBG(" cost %f ", path[i].cost);
- }
- }
-#endif
- DBG("Path-Cnt %i ", path_count);
-
+ compute(
+ pgr_text2char(PG_GETARG_TEXT_P(0)), /* SQL */
+ PG_GETARG_INT64(1), /* source id */
+ PG_GETARG_INT64(2), /* target_id */
+ PG_GETARG_INT32(3), /* number of paths */
+ PG_GETARG_BOOL(4), /* has reverse_cost */
+ PG_GETARG_BOOL(5), /* directed */
+ &path,
+ &path_count);
+// toDel = path;
+
+ PGR_DBG("Total number of tuples to be returned %i ", path_count);
+ PGR_DBG("Return value %i", ret);
+
/* total number of tuples to be returned */
funcctx->max_calls = path_count;
funcctx->user_fctx = path;
- funcctx->tuple_desc =
- BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult3"));
+ /* Build a tuple descriptor for our result type */
+ 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 = BlessTupleDesc(RelationNameGetTupleDesc("__pgr_2i3b2f"));
+ funcctx->tuple_desc = tuple_desc;
MemoryContextSwitchTo(oldcontext);
}
@@ -250,10 +112,9 @@ kshortest_path(PG_FUNCTION_ARGS)
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
tuple_desc = funcctx->tuple_desc;
- path = (ksp_path_element_t*) funcctx->user_fctx;
+ path = (pgr_path_element3_t*) funcctx->user_fctx;
- if (call_cntr < max_calls) /* do when there is more left to send */
- {
+ if (call_cntr < max_calls) { /* do when there is more left to send */
HeapTuple tuple;
Datum result;
/* //Datum values[4];
@@ -262,21 +123,30 @@ kshortest_path(PG_FUNCTION_ARGS)
Datum *values;
bool* nulls;
- values = (Datum *)palloc(5 * sizeof(Datum));
- nulls =(bool *) palloc(5 * sizeof(bool));
-
+ values = (Datum *)palloc(7 * sizeof(Datum));
+ nulls = (bool *) palloc(7 * sizeof(bool));
- values[0] = Int32GetDatum(call_cntr);
+ values[0] = Int32GetDatum(call_cntr + 1);
nulls[0] = false;
- values[1] = Int32GetDatum(path[call_cntr].route_id);
+
+ values[1] = Int32GetDatum(path[call_cntr].from + 1);
nulls[1] = false;
- values[2] = Int32GetDatum(path[call_cntr].vertex_id);
+
+ values[2] = Int32GetDatum(path[call_cntr].seq);
nulls[2] = false;
- values[3] = Int32GetDatum(path[call_cntr].edge_id);
+
+ values[3] = Int64GetDatum(path[call_cntr].vertex);
nulls[3] = false;
- values[4] = Float8GetDatum(path[call_cntr].cost);
+
+ values[4] = Int64GetDatum(path[call_cntr].edge);
nulls[4] = false;
+ values[5] = Float8GetDatum(path[call_cntr].cost);
+ nulls[5] = false;
+
+ values[6] = Float8GetDatum(path[call_cntr].tot_cost);
+ nulls[6] = false;
+
tuple = heap_form_tuple(tuple_desc, values, nulls);
/* make the tuple into a datum */
@@ -287,170 +157,64 @@ kshortest_path(PG_FUNCTION_ARGS)
pfree(nulls);
SRF_RETURN_NEXT(funcctx, result);
- }
- else /* do when there is no more left */
- {
- free(path);
- SRF_RETURN_DONE(funcctx);
- }
+ } else { /* do when there is no more left */
+ if (path == (pgr_path_element3_t *)NULL) free(path);
+ SRF_RETURN_DONE(funcctx);
+ }
}
-int compute_kshortest_path(char* sql, int start_vertex,
- int end_vertex, int no_paths,
- bool has_reverse_cost,
- ksp_path_element_t **ksp_path, int *path_count)
-{
+int compute(char* sql, int64_t start_vertex,
+ int64_t end_vertex, int no_paths,
+ bool has_rcost, bool directed,
+ pgr_path_element3_t **ksp_path, int *path_count) {
+ int SPIcode = 0;
+ pgr_edge_t *edges = NULL;
+ int64_t total_tuples = 0;
+ int readCode = 0;
- int SPIcode;
- void *SPIplan;
- Portal SPIportal;
- bool moredata = TRUE;
- int ntuples;
- ksp_edge_t *edges = NULL;
- int total_tuples = 0;
-#ifndef _MSC_VER
- ksp_edge_columns_t edge_columns = {.id= -1, .source= -1, .target= -1,
- .cost= -1, .reverse_cost= -1};
-#else // _MSC_VER
- ksp_edge_columns_t edge_columns = {-1, -1, -1, -1, -1};
-#endif // _MSC_VER
- int v_max_id=0;
- int v_min_id=INT_MAX;
-
- int s_count = 0;
- int t_count = 0;
-
- char *err_msg=(char *)"";
+ char *err_msg = (char *)"";
int ret = -1;
- register int z;
+ if (start_vertex == end_vertex) {
+ (*path_count) = 0;
+ *ksp_path = NULL;
+ return 0;
+ }
- DBG("start kshortest_path %s\n",sql);
-
- SPIcode = SPI_connect();
- if (SPIcode != SPI_OK_CONNECT)
- {
- elog(ERROR, "kshortest_path: couldn't open a connection to SPI");
- return -1;
- }
-
- SPIplan = SPI_prepare(sql, 0, NULL);
- if (SPIplan == NULL)
- {
- elog(ERROR, "kshortest_path: couldn't create query plan via SPI");
- return -1;
- }
+ PGR_DBG("Load data");
+ readCode = pgr_get_data(sql, &edges, &total_tuples, has_rcost,
+ start_vertex, end_vertex);
+ if (readCode == -1) {
+ (*path_count) = 0;
+ *ksp_path = NULL;
+ pfree(edges);
+ PGR_DBG("Source or vertex not found from Load data\n");
+ return pgr_finish(SPIcode, ret);
+ }
- if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL)
- {
- elog(ERROR, "shortest_path: SPI_cursor_open('%s') returns NULL", sql);
- return -1;
- }
+ PGR_DBG("Total %ld tuples in query:", total_tuples);
+ PGR_DBG("Calling do_pgr_ksp\n");
- while (moredata == TRUE)
- {
- SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
-
- if (edge_columns.id == -1)
- {
- if (ksp_fetch_edge_columns(SPI_tuptable, &edge_columns,
- has_reverse_cost) == -1)
- return ksp_finish(SPIcode, ret);
- }
-
- ntuples = SPI_processed;
- total_tuples += ntuples;
- if (!edges)
- edges = (ksp_edge_t *)palloc(total_tuples * sizeof(ksp_edge_t));
- else
- edges = (ksp_edge_t *)repalloc(edges, total_tuples * sizeof(ksp_edge_t));
-
- if (edges == NULL)
- {
- elog(ERROR, "Out of memory");
- return ksp_finish(SPIcode, ret);
- }
-
- if (ntuples > 0)
- {
- int t;
- SPITupleTable *tuptable = SPI_tuptable;
- TupleDesc tupdesc = SPI_tuptable->tupdesc;
-
- for (t = 0; t < ntuples; t++)
- {
- HeapTuple tuple = tuptable->vals[t];
- ksp_fetch_edge(&tuple, &tupdesc, &edge_columns,
- &edges[total_tuples - ntuples + t]);
- }
- SPI_freetuptable(tuptable);
- }
- else
- {
- moredata = FALSE;
- }
- }
+ ret = do_pgr_ksp(edges, total_tuples,
+ start_vertex, end_vertex,
+ no_paths, has_rcost, directed,
+ ksp_path, path_count, &err_msg);
-
-
- DBG("Total %i tuples", total_tuples);
+ PGR_DBG("total tuples found %i\n", *path_count);
+ PGR_DBG("Exist Status = %i\n", ret);
+ PGR_DBG("Returned message = %s\n", err_msg);
- for(z=0; z<total_tuples; z++)
- {
- //check if edges[] contains source and target
- if(edges[z].source == start_vertex || edges[z].target == start_vertex)
- ++s_count;
- if(edges[z].source == end_vertex || edges[z].target == end_vertex)
- ++t_count;
- DBG("%i - %i", edges[z].source, edges[z].target);
- }
- DBG("Total %i tuples", total_tuples);
-
+ if (ret < 0) {
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
- if(s_count == 0)
- {
- elog(ERROR, "Start vertex was not found.");
- return -1;
- }
-
- if(t_count == 0)
- {
- elog(ERROR, "Target vertex was not found.");
- return -1;
- }
-
- DBG("Calling doKpaths\n");
-
- DBG("SIZE %i\n",total_tuples);
- ret = doKpaths(edges, total_tuples,
- start_vertex, end_vertex,
- no_paths, has_reverse_cost,
- ksp_path, path_count, &err_msg);
- DBG("SIZE %i\n",*path_count);
-
- DBG("ret = %i\n", ret);
-
-
- if (ret < 0)
- {
- //elog(ERROR, "Error computing path: %s", err_msg);
- ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
- errmsg("Error computing path: %s", err_msg)));
- }
-
- return ksp_finish(SPIcode, ret);
+ pfree(edges);
+ return pgr_finish(SPIcode, ret);
}
-ksp_path_element_t * get_ksp_memory(int size,ksp_path_element_t *path){
- if(path ==0 ){
- path=malloc(size * sizeof(ksp_path_element_t));
- } else {
- path=realloc(path,size * sizeof(ksp_path_element_t));
- }
- return path;
-}
diff --git a/src/ksp/src/ksp.h b/src/ksp/src/ksp.h
index bb654ec..539d00e 100644
--- a/src/ksp/src/ksp.h
+++ b/src/ksp/src/ksp.h
@@ -1,77 +1,48 @@
-/*
- * KShortest path algorithm for PostgreSQL
- *
- * Copyright (c) 2012 Dave Potts
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _KSP_H
-#define _KSP_H
+/*PGR
-#define TUPLIMIT 1000
-#define PATH_ALLOC_TOTAL 5
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.com
-#include "postgres.h"
+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.
-#ifdef __cplusplus
-extern "C"
-{
-#endif
+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.
+
+*/
-typedef struct ksp_edge
-{
- int id;
- int source;
- int target;
- float8 cost;
- float8 reverse_cost;
-} ksp_edge_t;
-typedef struct ksp_path_element
-{
- int route_id;
- int vertex_id;
- int edge_id;
- float8 cost;
-} ksp_path_element_t;
+#ifndef SRC_KSP_SRC_KSP_H_
+#define SRC_KSP_SRC_KSP_H_
-typedef struct ksp_edge_columns
-{
- int id;
- int source;
- int target;
- float8 cost;
- float8 reverse_cost;
-} ksp_edge_columns_t;
+// #define TUPLIMIT 1000
+// #define PATH_ALLOC_TOTAL 5
+
+// #include <unistd.h>
+// #include "postgres.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
-int compute_kshortest_path(char* sql, int start_vertex,
- int end_vertex, int no_paths,
- bool has_reverse_cost,
- ksp_path_element_t **path, int *ksp_path_count) ;
+#include "./../../common/src/pgr_types.h"
-ksp_path_element_t * get_ksp_memory(int,ksp_path_element_t *path);
-/*int ksp_finish(int code, int ret);*/
+int compute(char* sql, int64_t start_vertex,
+ int64_t end_vertex, int no_paths,
+ bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **path, int *ksp_path_count);
-#ifdef _MSC_VER
- void DBG(const char* format, ...);
-#endif // _MSC_VER
#ifdef __cplusplus
}
#endif
-#endif // _KSP_H
+#endif // SRC_KSP_SRC_KSP_H_
diff --git a/src/ksp/src/ksp_driver.cpp b/src/ksp/src/ksp_driver.cpp
new file mode 100644
index 0000000..cc8a4d7
--- /dev/null
+++ b/src/ksp/src/ksp_driver.cpp
@@ -0,0 +1,138 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
+
+
+#include <deque>
+#include <sstream>
+
+#include <boost/config.hpp>
+#include <boost/graph/adjacency_list.hpp>
+
+#include "./ksp_driver.h"
+extern "C" {
+#if 0
+#include "postgres.h"
+#include "./ksp.h"
+#include "./../../common/src/pgr_types.h"
+#endif
+#include "./../../common/src/postgres_connection.h"
+}
+
+
+
+#include "./pgr_ksp.hpp"
+
+
+
+int do_pgr_ksp(pgr_edge_t *data_edges, int64_t total_tuples,
+ int64_t start_vertex, int64_t end_vertex,
+ int no_paths, bool has_reverse_cost, bool directedFlag,
+ pgr_path_element3_t **ksp_path, int *path_count,
+ char ** err_msg) {
+ try {
+ // in c code this should have been checked:
+ // 1) start_vertex is in the data_edges DONE
+ // 2) end_vertex is in the data_edges DONE
+ // 3) start and end_vertex are different DONE
+ std::ostringstream log;
+
+ graphType gType = directedFlag? DIRECTED: UNDIRECTED;
+ const int initial_size = 1;
+
+ std::deque< Path > paths;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS,
+ boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ Pgr_ksp < DirectedGraph > digraph(gType, initial_size);
+ Pgr_ksp < UndirectedGraph > undigraph(gType, initial_size);
+
+ if (directedFlag) {
+ digraph.initialize_graph(data_edges, total_tuples);
+ paths = digraph.Yen(start_vertex, end_vertex, no_paths);
+ digraph.clear();
+ } else {
+ undigraph.initialize_graph(data_edges, total_tuples);
+ paths = undigraph.Yen(start_vertex, end_vertex, no_paths);
+ }
+
+
+ int count(count_tuples(paths));
+
+ if (count == 0) {
+ *err_msg = strdup(
+ "NOTICE: No path found between Starting and Ending vertices");
+ *ksp_path = noPathFound3(-1, path_count, (*ksp_path));
+ return 0;
+ }
+
+ // get the space required to store all the paths
+ *ksp_path = NULL;
+ *ksp_path = pgr_get_memory3(count, (*ksp_path));
+
+ int sequence = 0;
+ int route_id = 0;
+ for (const auto &path : paths) {
+ if (path.path.size() > 0)
+ path.dpPrint(ksp_path, sequence, route_id);
+ ++route_id;
+ }
+
+ log << "NOTICE Sequence: " << sequence << "\n";
+ if (count != sequence) {
+ log << "ERROR: Internal count and real count are different. \n"
+ << "ERROR: This should not happen: Please report in GitHub:"
+ << " pgrouting issues.";
+ *err_msg = strdup(log.str().c_str());
+ return -1;
+ }
+ #if 1
+ *err_msg = strdup("OK");
+ #else
+ *err_msg = strdup(log.str().c_str());
+ #endif
+ *path_count = count;
+ return EXIT_SUCCESS;
+ } catch ( ... ) {
+ *err_msg = strdup("Caught unknown expection!");
+ return -1;
+ }
+}
+
+
+#if 0
+// move around this lines to force a return with an empty path and the log msg
+// cool for debugging
+*err_msg = strdup(log.str().c_str());
+(*path_count) = 1;
+*path = noPathFound(start_vertex);
+return -1;
+#endif
diff --git a/src/ksp/src/ksp_driver.h b/src/ksp/src/ksp_driver.h
new file mode 100644
index 0000000..6cba968
--- /dev/null
+++ b/src/ksp/src/ksp_driver.h
@@ -0,0 +1,44 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_KSP_SRC_KSP_DRIVER_H_
+#define SRC_KSP_SRC_KSP_DRIVER_H_
+
+// #include <stdarg.h>
+// #include <stdio.h>
+
+#include "./../../common/src/pgr_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int do_pgr_ksp(pgr_edge_t * edges, int64_t total_tuples,
+ int64_t start_vertex, int64_t end_vertex,
+ int no_paths, bool has_reverse_cost, bool directed,
+ pgr_path_element3_t **ksp_path, int *path_count,
+ char ** err_msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SRC_KSP_SRC_KSP_DRIVER_H_
diff --git a/src/ksp/src/pgr_ksp.cpp b/src/ksp/src/pgr_ksp.cpp
new file mode 100644
index 0000000..d0ce540
--- /dev/null
+++ b/src/ksp/src/pgr_ksp.cpp
@@ -0,0 +1,129 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+*/
+
+#include <deque>
+#include "./../../common/src/basePath_SSEC.hpp"
+
+template < class G >
+void Pgr_ksp< G >::clear() {
+ m_Heap.clear();
+}
+
+template < class G >
+void Pgr_ksp< G >::getFirstSolution() {
+ Path path;
+
+ this->dijkstra(path, m_start, m_end);
+
+ if (path.path.size() <= 1 ) return;
+ curr_result_path = path;
+ m_ResultSet.insert(curr_result_path);
+}
+
+template < class G>
+std::deque<Path> Pgr_ksp< G >::Yen(
+ int64_t start_vertex, int64_t end_vertex, int K) {
+ std::deque<Path> l_ResultList;
+ if ((start_vertex != end_vertex) && (K > 0)) {
+ if (!this->get_gVertex(start_vertex, v_source)
+ || !this->get_gVertex(end_vertex, v_target)) {
+ return l_ResultList;
+ }
+ m_start = start_vertex;
+ m_end = end_vertex;
+ executeYen(K);
+ }
+
+ while (m_Heap.size()) {
+ curr_result_path = *m_Heap.begin();
+ m_ResultSet.insert(curr_result_path);
+ m_Heap.erase(m_Heap.begin());
+ }
+
+ while (m_ResultSet.size()) {
+ l_ResultList.push_back((*m_ResultSet.begin()));
+ m_ResultSet.erase(m_ResultSet.begin());
+ }
+ return l_ResultList;
+}
+
+
+template < class G >
+void Pgr_ksp< G >::removeVertices(const Path &subpath) {
+ for (unsigned int i = 0; i < subpath.path.size(); i++)
+ this->disconnect_vertex(subpath.path[i].vertex);
+}
+
+template < class G >
+void Pgr_ksp< G >::doNextCycle() {
+ // REG_SIGINT
+
+
+ int64_t spurNodeId;
+ Path rootPath;
+ Path spurPath;
+
+ for (unsigned int i = 0; i < curr_result_path.path.size() ; ++i) {
+ // int64_t spurEdge = curr_result_path.path[i].edge;
+ spurNodeId = curr_result_path.path[i].vertex;
+
+ rootPath = curr_result_path.getSubpath(i);
+
+ for (pIt = m_ResultSet.begin(); pIt != m_ResultSet.end(); ++pIt) {
+ if ((*pIt).isEqual(rootPath)) {
+ // edge to be removed = (*pIt).path[i].edge;
+ this->disconnect_edge((*pIt).path[i].vertex, // from
+ (*pIt).path[i+1].vertex); // to
+ }
+ }
+ removeVertices(rootPath);
+
+ // int spurPathSize;
+
+ // THROW_ON_SIGINT
+ this->dijkstra(spurPath, spurNodeId , m_end);
+ // THROW_ON_SIGINT
+
+ if (spurPath.path.size() > 0) {
+ rootPath.appendPath(spurPath);
+ m_Heap.insert(rootPath);
+ }
+
+ this->restore_graph();
+ rootPath.clear();
+ spurPath.clear();
+ }
+}
+
+template < class G >
+void Pgr_ksp< G >::executeYen(int K) {
+ clear();
+ getFirstSolution();
+
+ if (m_ResultSet.size() == 0) return; // no path found
+
+ while ( m_ResultSet.size() < (unsigned int) K ) {
+ doNextCycle();
+ if ( m_Heap.size() == 0 ) break;
+ curr_result_path = *m_Heap.begin();
+ m_ResultSet.insert(curr_result_path);
+ m_Heap.erase(m_Heap.begin());
+ }
+}
diff --git a/src/ksp/src/pgr_ksp.hpp b/src/ksp/src/pgr_ksp.hpp
new file mode 100644
index 0000000..83a106b
--- /dev/null
+++ b/src/ksp/src/pgr_ksp.hpp
@@ -0,0 +1,96 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+#ifndef SRC_KSP_SRC_PGR_KSP_HPP_
+#define SRC_KSP_SRC_PGR_KSP_HPP_
+
+#include <deque>
+#include <set>
+#include "./../../common/src/basePath_SSEC.hpp"
+#include "./../../dijkstra/src/pgr_dijkstra.hpp"
+
+template < class G >
+class Pgr_ksp: public Pgr_dijkstra< G > {
+ public:
+ explicit Pgr_ksp(graphType gtype, const int initial_size)
+ : Pgr_dijkstra <G>(gtype, initial_size)
+ {}
+
+ ~Pgr_ksp(void) {}
+ std::deque<Path> Yen(int64_t source, int64_t target, int K);
+ void clear();
+
+ private:
+ class compPaths {
+ public:
+ bool operator()(const Path &p1, const Path &p2) const {
+ if (p1.cost < p2.cost) return true;
+ if (p1.cost > p2.cost) return false;
+
+ // paths costs are equal now we check by length
+ if (p1.path.size() < p2.path.size()) return true;
+ if (p1.path.size() > p2.path.size()) return false;
+
+ // paths weights & lengths are equal now we check by ID
+ unsigned int i;
+ for ( i = 0; i < p1.path.size() ; i++)
+ if ( p1.path[i].vertex < p2.path[i].vertex) return true;
+
+ // we got here and everything is equal
+ return false;
+ }
+ };
+
+ //! the actual algorithm
+ void executeYen(int top_k);
+
+ /** @name Auxiliary function for yen's algorithm */
+ ///@{
+
+ //! Performs the first Dijkstra of the algorithm
+ void getFirstSolution();
+ //! Performs the next cycle of the algorithm
+ void doNextCycle();
+ //! stores in subPath the first i elements of path
+ void removeVertices(const Path &path);
+ ///@}
+
+ private:
+ /** @name members */
+ ///@{
+ typedef typename boost::graph_traits < G >::vertex_descriptor V;
+ V v_source; //!< source descriptor
+ V v_target; //!< target descriptor
+ int64_t m_start; //!< source id
+ int64_t m_end; //!< target id
+
+ Path curr_result_path; //!< storage for the current result
+
+ typedef typename std::set<Path, compPaths> pSet;
+ typedef typename std::set<Path, compPaths>::iterator pSet_i;
+ pSet m_ResultSet; //!< ordered set of shortest paths
+ pSet m_Heap; //!< the heap
+ pSet_i pIt; //!< iterator for heap and result set
+};
+
+#include "./pgr_ksp.cpp"
+
+#endif // SRC_KSP_SRC_PGR_KSP_HPP_
diff --git a/src/ksp/test/ksp-any-00.data b/src/ksp/test/ksp-any-00.data
index ae01f90..6794c89 100644
--- a/src/ksp/test/ksp-any-00.data
+++ b/src/ksp/test/ksp-any-00.data
@@ -16,8 +16,8 @@ create table network (
id serial NOT NULL,
source integer NOT NULL,
target integer NOT NULL,
- cost float,
- reverse_cost float
+ cost double precision,
+ reverse_cost double precision
);
-- Add a geom column
select addgeometrycolumn('','network','the_geom',3857,'MULTILINESTRING',2);
@@ -83,3 +83,78 @@ update network set the_geom = st_setsrid(st_geomfromtext('MULTILINESTRING(('||
update network set cost = st_length(the_geom);
update network set reverse_cost = st_length(the_geom)*5;
+
+
+
+
+-- DATA FROM SAMPLE DATA
+
+
+DROP TABLE IF EXISTS edge_table;
+CREATE TABLE edge_table (
+ id serial,
+ dir character varying,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ the_geom geometry
+);
+
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,0, 2,1);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES (-1, 1, 2,1, 3,1);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES (-1, 1, 3,1, 4,1);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,1, 2,2);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,1, 3,2);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 0,2, 1,2);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 1,2, 2,2);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,2, 3,2);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 3,2, 4,2);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,2, 2,3);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,2, 3,3);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 2,3, 3,3);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,3, 4,3);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,3, 2,4);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 4,2, 4,3);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 4,1, 4,2);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 0.5,3.5, 1.999999999999,3.5);
+INSERT INTO edge_table (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 3.5,2.3, 3.5,4);
+
+
+UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
+ dir = CASE WHEN (cost>0 and reverse_cost>0) THEN 'B' -- both ways
+ WHEN (cost>0 and reverse_cost<0) THEN 'FT' -- direction of the LINESSTRING
+ WHEN (cost<0 and reverse_cost>0) THEN 'TF' -- reverse direction of the LINESTRING
+ ELSE '' END; -- unknown
+
+SELECT pgr_createTopology('edge_table',0.001);
+
+
+-- SAMPLE DATA FROM THE ISSUE 285
+
+drop table if exists parallel;
+CREATE TABLE parallel (
+ id serial,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ the_geom geometry
+);
+
+INSERT INTO parallel (x1,y1,x2,y2)
+ VALUES (1,0,1,1),(1,1,1,3),(1,1,1,3),(1,1,1,3),(1,3,1,4);
+
+UPDATE parallel SET the_geom = ST_makeline(ST_point(x1,y1),ST_point(x2,y2));
+UPDATE parallel SET the_geom = ST_makeline(ARRAY[ST_point(1,1),ST_point(0,2),ST_point(1,3)]) WHERE id = 3;
+UPDATE parallel SET the_geom = ST_makeline(ARRAY[ST_point(1,1),ST_point(2,1),ST_point(2,3),ST_point(1,3)]) WHERE id = 4;
+UPDATE parallel SET cost = ST_length(the_geom), reverse_cost = ST_length(the_geom);
+SELECT pgr_createTopology('parallel',0.001);
diff --git a/src/ksp/test/ksp-any-01.rest b/src/ksp/test/ksp-any-01.rest
deleted file mode 100644
index d3a35b4..0000000
--- a/src/ksp/test/ksp-any-01.rest
+++ /dev/null
@@ -1,91 +0,0 @@
-0|15|4|5|2.00
-1|2|0|2|2.83
-1|9|2|5|4.47
-1|10|3|0|4.24
-1|13|4|3|1.41
-2|1|0|1|1.41
-2|5|1|2|1.41
-2|9|2|5|4.47
-2|10|3|0|4.24
-2|13|4|3|1.41
-3|5|1|2|1.41
-3|9|2|5|4.47
-3|14|4|6|2.24
-3|21|6|7|3.16
-3|24|7|1|6.08
-4|2|0|2|2.83
-4|4|1|0|1.41
-4|9|2|5|4.47
-4|14|4|6|2.24
-4|21|6|7|3.16
-4|24|7|1|6.08
-5|14|4|6|2.24
-5|21|6|7|3.16
-5|23|7|8|6.71
-5|26|8|11|3.61
-5|34|11|13|2.24
-5|39|13|5|6.32
-6|14|4|6|2.24
-6|21|6|7|3.16
-6|23|7|8|6.71
-6|27|8|12|4.00
-6|37|12|13|2.00
-6|39|13|5|6.32
-7|12|3|10|9.90
-7|13|4|3|1.41
-7|31|10|12|6.32
-7|37|12|13|2.00
-7|39|13|5|6.32
-8|12|3|10|9.90
-8|13|4|3|1.41
-8|30|10|11|9.00
-8|34|11|13|2.24
-8|39|13|5|6.32
-9|1|0|1|1.41
-9|6|1|7|6.08
-9|10|3|0|4.24
-9|13|4|3|1.41
-9|23|7|8|6.71
-9|26|8|11|3.61
-9|34|11|13|2.24
-9|39|13|5|6.32
-10|1|0|1|1.41
-10|6|1|7|6.08
-10|10|3|0|4.24
-10|13|4|3|1.41
-10|23|7|8|6.71
-10|27|8|12|4.00
-10|37|12|13|2.00
-10|39|13|5|6.32
-11|12|3|10|9.90
-11|13|4|3|1.41
-11|26|8|11|3.61
-11|31|10|12|6.32
-11|34|11|13|2.24
-11|36|12|8|4.00
-11|39|13|5|6.32
-12|2|0|2|2.83
-12|6|1|7|6.08
-12|8|2|1|1.41
-12|10|3|0|4.24
-12|13|4|3|1.41
-12|23|7|8|6.71
-12|26|8|11|3.61
-12|34|11|13|2.24
-12|39|13|5|6.32
-13|2|0|2|2.83
-13|6|1|7|6.08
-13|8|2|1|1.41
-13|10|3|0|4.24
-13|13|4|3|1.41
-13|23|7|8|6.71
-13|27|8|12|4.00
-13|37|12|13|2.00
-13|39|13|5|6.32
-14|12|3|10|9.90
-14|13|4|3|1.41
-14|27|8|12|4.00
-14|30|10|11|9.00
-14|32|11|8|3.61
-14|37|12|13|2.00
-14|39|13|5|6.32
diff --git a/src/ksp/test/ksp-any-01.result b/src/ksp/test/ksp-any-01.result
new file mode 100644
index 0000000..8b9ba4e
--- /dev/null
+++ b/src/ksp/test/ksp-any-01.result
@@ -0,0 +1,214 @@
+0|0|4|15|2.0000
+1|0|5|-1|0.0000
+2|1|4|13|1.4142
+3|1|3|10|4.2426
+4|1|0|1|1.4142
+5|1|1|5|1.4142
+6|1|2|9|4.4721
+7|1|5|-1|0.0000
+8|2|4|13|1.4142
+9|2|3|10|4.2426
+10|2|0|2|2.8284
+11|2|2|9|4.4721
+12|2|5|-1|0.0000
+13|3|4|14|2.2361
+14|3|6|21|3.1623
+15|3|7|24|6.0828
+16|3|1|5|1.4142
+17|3|2|9|4.4721
+18|3|5|-1|0.0000
+19|4|4|14|2.2361
+20|4|6|21|3.1623
+21|4|7|24|6.0828
+22|4|1|4|1.4142
+23|4|0|2|2.8284
+24|4|2|9|4.4721
+25|4|5|-1|0.0000
+26|5|4|14|2.2361
+27|5|6|21|3.1623
+28|5|7|23|6.7082
+29|5|8|26|3.6056
+30|5|11|34|2.2361
+31|5|13|39|6.3246
+32|5|5|-1|0.0000
+33|6|4|14|2.2361
+34|6|6|21|3.1623
+35|6|7|23|6.7082
+36|6|8|27|4.0000
+37|6|12|37|2.0000
+38|6|13|39|6.3246
+39|6|5|-1|0.0000
+40|7|4|13|1.4142
+41|7|3|12|9.8995
+42|7|10|31|6.3246
+43|7|12|37|2.0000
+44|7|13|39|6.3246
+45|7|5|-1|0.0000
+46|8|4|13|1.4142
+47|8|3|12|9.8995
+48|8|10|30|9.0000
+49|8|11|34|2.2361
+50|8|13|39|6.3246
+51|8|5|-1|0.0000
+52|9|4|13|1.4142
+53|9|3|10|4.2426
+54|9|0|1|1.4142
+55|9|1|6|6.0828
+56|9|7|23|6.7082
+57|9|8|26|3.6056
+58|9|11|34|2.2361
+59|9|13|39|6.3246
+60|9|5|-1|0.0000
+61|10|4|13|1.4142
+62|10|3|10|4.2426
+63|10|0|1|1.4142
+64|10|1|6|6.0828
+65|10|7|23|6.7082
+66|10|8|27|4.0000
+67|10|12|37|2.0000
+68|10|13|39|6.3246
+69|10|5|-1|0.0000
+70|11|4|13|1.4142
+71|11|3|12|9.8995
+72|11|10|31|6.3246
+73|11|12|36|4.0000
+74|11|8|26|3.6056
+75|11|11|34|2.2361
+76|11|13|39|6.3246
+77|11|5|-1|0.0000
+78|12|4|13|1.4142
+79|12|3|10|4.2426
+80|12|0|2|2.8284
+81|12|2|8|1.4142
+82|12|1|6|6.0828
+83|12|7|23|6.7082
+84|12|8|26|3.6056
+85|12|11|34|2.2361
+86|12|13|39|6.3246
+87|12|5|-1|0.0000
+88|13|4|13|1.4142
+89|13|3|10|4.2426
+90|13|0|2|2.8284
+91|13|2|8|1.4142
+92|13|1|6|6.0828
+93|13|7|23|6.7082
+94|13|8|27|4.0000
+95|13|12|37|2.0000
+96|13|13|39|6.3246
+97|13|5|-1|0.0000
+98|14|4|14|2.2361
+99|14|6|21|3.1623
+100|14|7|23|6.7082
+101|14|8|26|3.6056
+102|14|11|33|9.0000
+103|14|10|31|6.3246
+104|14|12|37|2.0000
+105|14|13|39|6.3246
+106|14|5|-1|0.0000
+0|2.0000
+1|12.9574
+2|12.9574
+3|17.3675
+4|20.1959
+5|24.2727
+6|24.4311
+7|25.9628
+8|28.8743
+9|32.0282
+10|32.1866
+11|33.8044
+12|34.8566
+13|35.0150
+14|39.3612
+0|0|t|t|t
+2|1|t|t|t
+3|1|t|t|t
+4|1|t|t|t
+5|1|t|t|t
+6|1|t|t|t
+8|2|t|t|t
+9|2|t|t|t
+10|2|t|t|t
+11|2|t|t|t
+13|3|t|t|t
+14|3|t|t|t
+15|3|t|t|t
+16|3|t|t|t
+17|3|t|t|t
+19|4|t|t|t
+20|4|t|t|t
+21|4|t|t|t
+22|4|t|t|t
+23|4|t|t|t
+24|4|t|t|t
+26|5|t|t|t
+27|5|t|t|t
+28|5|t|t|t
+29|5|t|t|t
+30|5|t|t|t
+31|5|t|t|t
+33|6|t|t|t
+34|6|t|t|t
+35|6|t|t|t
+36|6|t|t|t
+37|6|t|t|t
+38|6|t|t|t
+40|7|t|t|t
+41|7|t|t|t
+42|7|t|t|t
+43|7|t|t|t
+44|7|t|t|t
+46|8|t|t|t
+47|8|t|t|t
+48|8|t|t|t
+49|8|t|t|t
+50|8|t|t|t
+52|9|t|t|t
+53|9|t|t|t
+54|9|t|t|t
+55|9|t|t|t
+56|9|t|t|t
+57|9|t|t|t
+58|9|t|t|t
+59|9|t|t|t
+61|10|t|t|t
+62|10|t|t|t
+63|10|t|t|t
+64|10|t|t|t
+65|10|t|t|t
+66|10|t|t|t
+67|10|t|t|t
+68|10|t|t|t
+70|11|t|t|t
+71|11|t|t|t
+72|11|t|t|t
+73|11|t|t|t
+74|11|t|t|t
+75|11|t|t|t
+76|11|t|t|t
+78|12|t|t|t
+79|12|t|t|t
+80|12|t|t|t
+81|12|t|t|t
+82|12|t|t|t
+83|12|t|t|t
+84|12|t|t|t
+85|12|t|t|t
+86|12|t|t|t
+88|13|t|t|t
+89|13|t|t|t
+90|13|t|t|t
+91|13|t|t|t
+92|13|t|t|t
+93|13|t|t|t
+94|13|t|t|t
+95|13|t|t|t
+96|13|t|t|t
+98|14|t|t|t
+99|14|t|t|t
+100|14|t|t|t
+101|14|t|t|t
+102|14|t|t|t
+103|14|t|t|t
+104|14|t|t|t
+105|14|t|t|t
diff --git a/src/ksp/test/ksp-any-01.test b/src/ksp/test/ksp-any-01.test
deleted file mode 100644
index d19d083..0000000
--- a/src/ksp/test/ksp-any-01.test
+++ /dev/null
@@ -1,15 +0,0 @@
---
--- Generate 15 shortest paths between nodes 4 and 5
---
--- List by links
---
-select ksp.id1, ksp.id3, n.source, n.target, round(st_length(n.the_geom)::numeric, 2) as len
- from pgr_ksp(
- 'select source, target, cost,reverse_cost, id from network order by id',
- 4,
- 5,
- 15,
- 'f') ksp,
- network n
- where ksp.id3=n.id
- order by ksp.id1, ksp.id3;
diff --git a/src/ksp/test/ksp-any-01.test.sql b/src/ksp/test/ksp-any-01.test.sql
new file mode 100644
index 0000000..9232109
--- /dev/null
+++ b/src/ksp/test/ksp-any-01.test.sql
@@ -0,0 +1,20 @@
+--
+-- Generate 15 shortest paths between nodes 4 and 5
+--
+--
+select seq, id1, id2, id3, round(cost::numeric, 4) from pgr_ksp(
+ 'select id, source, target, cost from network order by id',
+ 4, 5,
+ 15, 'f');
+
+select id1, round(sum(cost)::numeric,4) from pgr_ksp(
+ 'select id, source, target, cost from network order by id',
+ 4, 5,
+ 15, 'f') group by id1 order by id1;
+
+
+-- the equality conditions
+select seq, id1, id2 = network.source, id3 = network.id, round(network.cost::numeric,4) = round(result.cost::numeric, 4) from pgr_ksp(
+ 'select id, source, target, cost from network order by id',
+ 4, 5,
+ 15, 'f') result, network where id = id3 order by seq;
diff --git a/src/ksp/test/ksp-any-02.rest b/src/ksp/test/ksp-any-02.rest
deleted file mode 100644
index 54e7120..0000000
--- a/src/ksp/test/ksp-any-02.rest
+++ /dev/null
@@ -1,15 +0,0 @@
-0|2.00
-1|12.96
-2|12.96
-3|17.37
-4|20.20
-5|24.27
-6|24.43
-7|25.96
-8|28.87
-9|32.03
-10|32.19
-11|33.80
-12|34.86
-13|35.02
-14|36.24
diff --git a/src/ksp/test/ksp-any-02.result b/src/ksp/test/ksp-any-02.result
new file mode 100644
index 0000000..bb927a1
--- /dev/null
+++ b/src/ksp/test/ksp-any-02.result
@@ -0,0 +1,214 @@
+1|1|4|15|2.0000
+2|1|5|-1|0.0000
+3|2|4|13|1.4142
+4|2|3|10|4.2426
+5|2|0|1|1.4142
+6|2|1|5|1.4142
+7|2|2|9|4.4721
+8|2|5|-1|0.0000
+9|3|4|13|1.4142
+10|3|3|10|4.2426
+11|3|0|2|2.8284
+12|3|2|9|4.4721
+13|3|5|-1|0.0000
+14|4|4|14|2.2361
+15|4|6|21|3.1623
+16|4|7|24|6.0828
+17|4|1|5|1.4142
+18|4|2|9|4.4721
+19|4|5|-1|0.0000
+20|5|4|14|2.2361
+21|5|6|21|3.1623
+22|5|7|24|6.0828
+23|5|1|4|1.4142
+24|5|0|2|2.8284
+25|5|2|9|4.4721
+26|5|5|-1|0.0000
+27|6|4|14|2.2361
+28|6|6|21|3.1623
+29|6|7|23|6.7082
+30|6|8|26|3.6056
+31|6|11|34|2.2361
+32|6|13|39|6.3246
+33|6|5|-1|0.0000
+34|7|4|14|2.2361
+35|7|6|21|3.1623
+36|7|7|23|6.7082
+37|7|8|27|4.0000
+38|7|12|37|2.0000
+39|7|13|39|6.3246
+40|7|5|-1|0.0000
+41|8|4|13|1.4142
+42|8|3|12|9.8995
+43|8|10|31|6.3246
+44|8|12|37|2.0000
+45|8|13|39|6.3246
+46|8|5|-1|0.0000
+47|9|4|13|1.4142
+48|9|3|12|9.8995
+49|9|10|30|9.0000
+50|9|11|34|2.2361
+51|9|13|39|6.3246
+52|9|5|-1|0.0000
+53|10|4|13|1.4142
+54|10|3|10|4.2426
+55|10|0|1|1.4142
+56|10|1|6|6.0828
+57|10|7|23|6.7082
+58|10|8|26|3.6056
+59|10|11|34|2.2361
+60|10|13|39|6.3246
+61|10|5|-1|0.0000
+62|11|4|13|1.4142
+63|11|3|10|4.2426
+64|11|0|1|1.4142
+65|11|1|6|6.0828
+66|11|7|23|6.7082
+67|11|8|27|4.0000
+68|11|12|37|2.0000
+69|11|13|39|6.3246
+70|11|5|-1|0.0000
+71|12|4|13|1.4142
+72|12|3|12|9.8995
+73|12|10|31|6.3246
+74|12|12|36|4.0000
+75|12|8|26|3.6056
+76|12|11|34|2.2361
+77|12|13|39|6.3246
+78|12|5|-1|0.0000
+79|13|4|13|1.4142
+80|13|3|10|4.2426
+81|13|0|2|2.8284
+82|13|2|8|1.4142
+83|13|1|6|6.0828
+84|13|7|23|6.7082
+85|13|8|26|3.6056
+86|13|11|34|2.2361
+87|13|13|39|6.3246
+88|13|5|-1|0.0000
+89|14|4|13|1.4142
+90|14|3|10|4.2426
+91|14|0|2|2.8284
+92|14|2|8|1.4142
+93|14|1|6|6.0828
+94|14|7|23|6.7082
+95|14|8|27|4.0000
+96|14|12|37|2.0000
+97|14|13|39|6.3246
+98|14|5|-1|0.0000
+99|15|4|14|2.2361
+100|15|6|21|3.1623
+101|15|7|23|6.7082
+102|15|8|26|3.6056
+103|15|11|33|9.0000
+104|15|10|31|6.3246
+105|15|12|37|2.0000
+106|15|13|39|6.3246
+107|15|5|-1|0.0000
+1|2.0000
+2|12.9574
+3|12.9574
+4|17.3675
+5|20.1959
+6|24.2727
+7|24.4311
+8|25.9628
+9|28.8743
+10|32.0282
+11|32.1866
+12|33.8044
+13|34.8566
+14|35.0150
+15|39.3612
+1|1|t|t|t
+3|2|t|t|t
+4|2|t|t|t
+5|2|t|t|t
+6|2|t|t|t
+7|2|t|t|t
+9|3|t|t|t
+10|3|t|t|t
+11|3|t|t|t
+12|3|t|t|t
+14|4|t|t|t
+15|4|t|t|t
+16|4|t|t|t
+17|4|t|t|t
+18|4|t|t|t
+20|5|t|t|t
+21|5|t|t|t
+22|5|t|t|t
+23|5|t|t|t
+24|5|t|t|t
+25|5|t|t|t
+27|6|t|t|t
+28|6|t|t|t
+29|6|t|t|t
+30|6|t|t|t
+31|6|t|t|t
+32|6|t|t|t
+34|7|t|t|t
+35|7|t|t|t
+36|7|t|t|t
+37|7|t|t|t
+38|7|t|t|t
+39|7|t|t|t
+41|8|t|t|t
+42|8|t|t|t
+43|8|t|t|t
+44|8|t|t|t
+45|8|t|t|t
+47|9|t|t|t
+48|9|t|t|t
+49|9|t|t|t
+50|9|t|t|t
+51|9|t|t|t
+53|10|t|t|t
+54|10|t|t|t
+55|10|t|t|t
+56|10|t|t|t
+57|10|t|t|t
+58|10|t|t|t
+59|10|t|t|t
+60|10|t|t|t
+62|11|t|t|t
+63|11|t|t|t
+64|11|t|t|t
+65|11|t|t|t
+66|11|t|t|t
+67|11|t|t|t
+68|11|t|t|t
+69|11|t|t|t
+71|12|t|t|t
+72|12|t|t|t
+73|12|t|t|t
+74|12|t|t|t
+75|12|t|t|t
+76|12|t|t|t
+77|12|t|t|t
+79|13|t|t|t
+80|13|t|t|t
+81|13|t|t|t
+82|13|t|t|t
+83|13|t|t|t
+84|13|t|t|t
+85|13|t|t|t
+86|13|t|t|t
+87|13|t|t|t
+89|14|t|t|t
+90|14|t|t|t
+91|14|t|t|t
+92|14|t|t|t
+93|14|t|t|t
+94|14|t|t|t
+95|14|t|t|t
+96|14|t|t|t
+97|14|t|t|t
+99|15|t|t|t
+100|15|t|t|t
+101|15|t|t|t
+102|15|t|t|t
+103|15|t|t|t
+104|15|t|t|t
+105|15|t|t|t
+106|15|t|t|t
diff --git a/src/ksp/test/ksp-any-02.test b/src/ksp/test/ksp-any-02.test
deleted file mode 100644
index 86566e4..0000000
--- a/src/ksp/test/ksp-any-02.test
+++ /dev/null
@@ -1,14 +0,0 @@
---
--- Dump a 15 fastest routes between nodes 4 and 5 by total route length
---
-select ksp.id1, round(sum(st_length(n.the_geom))::numeric, 2) as len
- from pgr_ksp(
- 'select source, target, cost, reverse_cost, id from network',
- 4,
- 5,
- 15,
- 'f') ksp,
- network n
- where ksp.id3=n.id
- group by id1
- order by id1;
diff --git a/src/ksp/test/ksp-any-02.test.sql b/src/ksp/test/ksp-any-02.test.sql
new file mode 100644
index 0000000..2c05b94
--- /dev/null
+++ b/src/ksp/test/ksp-any-02.test.sql
@@ -0,0 +1,22 @@
+--
+-- Generate 15 shortest paths between nodes 4 and 5
+-- with auto detection
+-- V3
+--
+
+select seq, path_id, node, edge, round(cost::numeric, 4) from pgr_ksp(
+ 'select id, source, target, cost from network order by id',
+ 4, 5::bigint,
+ 15);
+
+select path_id, round(sum(cost)::numeric,4) from pgr_ksp(
+ 'select id, source, target, cost from network order by id',
+ 4, 5::bigint,
+ 15) group by path_id order by path_id;
+
+
+-- the equality conditions
+select seq, path_id, node = network.source, edge = network.id, round(network.cost::numeric,4) = round(result.cost::numeric, 4) from pgr_ksp(
+ 'select id, source, target, cost from network order by id',
+ 4, 5::bigint,
+ 15) result, network where id = edge order by seq;
diff --git a/src/ksp/test/ksp-parallel-any-03.result b/src/ksp/test/ksp-parallel-any-03.result
new file mode 100644
index 0000000..0a48d12
--- /dev/null
+++ b/src/ksp/test/ksp-parallel-any-03.result
@@ -0,0 +1,26 @@
+0|0|2|2|2
+1|0|3|-1|0
+0|0|2|2|2
+1|0|3|-1|0
+0|0|2|2|2
+1|0|3|-1|0
+0|0|2|2|2
+1|0|3|-1|0
+0|0|2|2|2
+1|0|3|-1|0
+0|0|1|1|1
+1|0|2|2|2
+2|0|3|5|1
+3|0|4|-1|0
+0|0|1|1|1
+1|0|2|2|2
+2|0|3|5|1
+3|0|4|-1|0
+0|0|1|1|1
+1|0|2|2|2
+2|0|3|5|1
+3|0|4|-1|0
+0|0|1|1|1
+1|0|2|2|2
+2|0|3|5|1
+3|0|4|-1|0
diff --git a/src/ksp/test/ksp-parallel-any-03.test.sql b/src/ksp/test/ksp-parallel-any-03.test.sql
new file mode 100644
index 0000000..fa5b048
--- /dev/null
+++ b/src/ksp/test/ksp-parallel-any-03.test.sql
@@ -0,0 +1,59 @@
+---
+-- TESTS FROM ISSUE 285
+---
+
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 2, 3, 1, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 2, 3, 2, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 2, 3, 3, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 2, 3, 4, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 2, 3, 100, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 1, 4, 1, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 1, 4, 2, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 1, 4, 3, true
+);
+
+SELECT seq, id1 AS route, id2 AS node, id3 AS edge, cost
+ FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM parallel',
+ 1, 4, 100, true
+);
+
diff --git a/doc/test/ksp-any.rest b/src/ksp/test/ksp-v2.result
similarity index 78%
rename from doc/test/ksp-any.rest
rename to src/ksp/test/ksp-v2.result
index 0c1816f..897e502 100644
--- a/doc/test/ksp-any.rest
+++ b/src/ksp/test/ksp-v2.result
@@ -12,13 +12,13 @@
11|1|12|-1|0
0|0|7|6|1
1|0|8|7|1
-2|0|5|10|1
-3|0|10|12|1
-4|0|11|13|1
+2|0|5|8|1
+3|0|6|9|1
+4|0|9|15|1
5|0|12|-1|0
6|1|7|6|1
7|1|8|7|1
8|1|5|8|1
-9|1|6|9|1
-10|1|9|15|1
+9|1|6|11|1
+10|1|11|13|1
11|1|12|-1|0
diff --git a/doc/test/ksp-any.test b/src/ksp/test/ksp-v2.test.sql
similarity index 100%
rename from doc/test/ksp-any.test
rename to src/ksp/test/ksp-v2.test.sql
diff --git a/src/ksp/test/ksp-v3-1route.result b/src/ksp/test/ksp-v3-1route.result
new file mode 100644
index 0000000..d701ff7
--- /dev/null
+++ b/src/ksp/test/ksp-v3-1route.result
@@ -0,0 +1,93 @@
+1|1|2|1|1
+2|2|3|-1|1
+3|3|4|-1|1
+4|2|5|1|1
+5|3|6|1|-1
+6|7|8|1|1
+7|8|5|1|1
+8|5|6|1|1
+9|6|9|1|1
+10|5|10|1|1
+11|6|11|1|-1
+12|10|11|1|-1
+13|11|12|1|-1
+14|10|13|1|1
+15|9|12|1|1
+16|4|9|1|1
+17|14|15|1|1
+18|16|17|1|1
+1|0|0|2|4|1
+1|1|0|5|8|1
+1|2|0|6|9|1
+1|3|0|9|15|1
+1|4|0|12|-1|0
+2|1|1|1|2|4|1|0
+2|2|1|2|5|8|1|1
+2|3|1|3|6|9|1|2
+2|4|1|4|9|15|1|3
+2|5|1|5|12|-1|0|4
+3|1|1|1|2|4|1|0
+3|2|1|2|5|8|1|1
+3|3|1|3|6|9|1|2
+3|4|1|4|9|15|1|3
+3|5|1|5|12|-1|0|4
+4|1|1|1|2|4|1|0
+4|2|1|2|5|8|1|1
+4|3|1|3|6|9|1|2
+4|4|1|4|9|15|1|3
+4|5|1|5|12|-1|0|4
+5|1|1|1|2|4|1|0
+5|2|1|2|5|8|1|1
+5|3|1|3|6|9|1|2
+5|4|1|4|9|15|1|3
+5|5|1|5|12|-1|0|4
+6|1|1|1|2|4|1|0
+6|2|1|2|5|8|1|1
+6|3|1|3|6|9|1|2
+6|4|1|4|9|15|1|3
+6|5|1|5|12|-1|0|4
+7|1|1|1|2|4|1|0
+7|2|1|2|5|10|1|1
+7|3|1|3|10|12|1|2
+7|4|1|4|11|13|1|3
+7|5|1|5|12|-1|0|4
+8|1|1|1|2|4|1|0
+8|2|1|2|5|10|1|1
+8|3|1|3|10|12|1|2
+8|4|1|4|11|13|1|3
+8|5|1|5|12|-1|0|4
+9|1|1|1|2|4|1|0
+9|2|1|2|5|10|1|1
+9|3|1|3|10|12|1|2
+9|4|1|4|11|13|1|3
+9|5|1|5|12|-1|0|4
+11|1|1|1|0
+11|2|1|1|1
+11|3|1|1|2
+11|4|1|1|3
+11|5|1|0|4
+12|1|1|1|0
+12|2|1|1|1
+12|3|1|1|2
+12|4|1|1|3
+12|5|1|0|4
+13|1|1|1|0
+13|2|1|1|1
+13|3|1|1|2
+13|4|1|1|3
+13|5|1|0|4
+14|1|1|1|2|4|1|0
+14|2|1|2|5|8|1|1
+14|3|1|3|6|9|1|2
+14|4|1|4|9|15|1|3
+14|5|1|5|12|-1|0|4
+15|1|1|1|2|4|1|0
+15|2|1|2|5|8|1|1
+15|3|1|3|6|9|1|2
+15|4|1|4|9|15|1|3
+15|5|1|5|12|-1|0|4
+16|1|1|1|2|4|1|0
+16|2|1|2|5|8|1|1
+16|3|1|3|6|9|1|2
+16|4|1|4|9|15|1|3
+16|5|1|5|12|-1|0|4
diff --git a/src/ksp/test/ksp-v3-1route.test.sql b/src/ksp/test/ksp-v3-1route.test.sql
new file mode 100644
index 0000000..6048979
--- /dev/null
+++ b/src/ksp/test/ksp-v3-1route.test.sql
@@ -0,0 +1,116 @@
+--------------------------------------------------------------------------------
+-- PGR_ksp V3 only
+--------------------------------------------------------------------------------
+
+-- data
+SELECT id, source, target, cost, reverse_cost FROM edge_table order by id;
+
+
+-- Examples to handle the one flag to choose signatures using :ref:`fig1-direct-Cost-Reverse`
+------------------------------------------------------------------------------------------
+
+
+ SELECT 1, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1,
+ true
+ );
+
+ SELECT 2, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1,
+ directed:=true -- takes the new signature
+ );
+
+ SELECT 3, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1
+ );
+
+
+
+--Examples using :ref:`fig1-direct-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ SELECT 4, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1
+ );
+
+
+ SELECT 5, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1, heap_paths:=true
+ );
+
+ SELECT 6, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1, true, true
+ );
+
+--Example for :ref:`fig2-undirect-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ SELECT 7, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1, directed:=false
+ );
+
+ SELECT 8, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1, directed:=false, heap_paths:=true
+ );
+
+ SELECT 9, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 1, false, true
+ );
+
+
+
+-- Examples for :ref:`fig3-direct-Cost`
+-------------------------------------------------------------------------------
+
+
+ SELECT 10, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, 2
+ );
+
+
+ SELECT 11, seq, path_id, cost, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 1
+ );
+
+
+ SELECT 12, seq, path_id, cost, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 1, heap_paths:=true
+ );
+
+ SELECT 13, seq, path_id, cost, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 1, true, true
+ );
+
+--Examples for :ref:`fig4-undirect-Cost`
+-------------------------------------------------------------------------------
+
+
+ SELECT 14, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 1, directed:=false
+ );
+
+ SELECT 15, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 1, directed:=false, heap_paths:=true
+ );
+
+ SELECT 16, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 1, false, true
+ );
diff --git a/src/ksp/test/ksp-v3.result b/src/ksp/test/ksp-v3.result
new file mode 100644
index 0000000..1ca2113
--- /dev/null
+++ b/src/ksp/test/ksp-v3.result
@@ -0,0 +1,154 @@
+1|0|0|2|4|1
+1|1|0|5|8|1
+1|2|0|6|9|1
+1|3|0|9|15|1
+1|4|0|12|-1|0
+1|5|1|2|4|1
+1|6|1|5|8|1
+1|7|1|6|11|1
+1|8|1|11|13|1
+1|9|1|12|-1|0
+2|1|1|1|2|4|1|0
+2|2|1|2|5|8|1|1
+2|3|1|3|6|9|1|2
+2|4|1|4|9|15|1|3
+2|5|1|5|12|-1|0|4
+2|6|2|1|2|4|1|0
+2|7|2|2|5|8|1|1
+2|8|2|3|6|11|1|2
+2|9|2|4|11|13|1|3
+2|10|2|5|12|-1|0|4
+3|1|1|1|2|4|1|0
+3|2|1|2|5|8|1|1
+3|3|1|3|6|9|1|2
+3|4|1|4|9|15|1|3
+3|5|1|5|12|-1|0|4
+3|6|2|1|2|4|1|0
+3|7|2|2|5|8|1|1
+3|8|2|3|6|11|1|2
+3|9|2|4|11|13|1|3
+3|10|2|5|12|-1|0|4
+4|1|1|1|2|4|1|0
+4|2|1|2|5|8|1|1
+4|3|1|3|6|9|1|2
+4|4|1|4|9|15|1|3
+4|5|1|5|12|-1|0|4
+4|6|2|1|2|4|1|0
+4|7|2|2|5|8|1|1
+4|8|2|3|6|11|1|2
+4|9|2|4|11|13|1|3
+4|10|2|5|12|-1|0|4
+5|1|1|1|2|4|1|0
+5|2|1|2|5|8|1|1
+5|3|1|3|6|9|1|2
+5|4|1|4|9|15|1|3
+5|5|1|5|12|-1|0|4
+5|6|2|1|2|4|1|0
+5|7|2|2|5|8|1|1
+5|8|2|3|6|11|1|2
+5|9|2|4|11|13|1|3
+5|10|2|5|12|-1|0|4
+5|11|3|1|2|4|1|0
+5|12|3|2|5|10|1|1
+5|13|3|3|10|12|1|2
+5|14|3|4|11|13|1|3
+5|15|3|5|12|-1|0|4
+6|1|1|1|2|4|1|0
+6|2|1|2|5|8|1|1
+6|3|1|3|6|9|1|2
+6|4|1|4|9|15|1|3
+6|5|1|5|12|-1|0|4
+6|6|2|1|2|4|1|0
+6|7|2|2|5|8|1|1
+6|8|2|3|6|11|1|2
+6|9|2|4|11|13|1|3
+6|10|2|5|12|-1|0|4
+6|11|3|1|2|4|1|0
+6|12|3|2|5|10|1|1
+6|13|3|3|10|12|1|2
+6|14|3|4|11|13|1|3
+6|15|3|5|12|-1|0|4
+7|1|1|1|0
+7|2|1|1|1
+7|3|1|1|2
+7|4|1|1|3
+7|5|1|0|4
+7|6|2|1|0
+7|7|2|1|1
+7|8|2|1|2
+7|9|2|1|3
+7|10|2|0|4
+8|1|1|1|0
+8|2|1|1|1
+8|3|1|1|2
+8|4|1|1|3
+8|5|1|0|4
+8|6|2|1|0
+8|7|2|1|1
+8|8|2|1|2
+8|9|2|1|3
+8|10|2|0|4
+8|11|3|1|0
+8|12|3|1|1
+8|13|3|1|2
+8|14|3|1|3
+8|15|3|0|4
+8|16|4|1|0
+8|17|4|1|1
+8|18|4|1|2
+8|19|4|1|3
+8|20|4|1|4
+8|21|4|1|5
+8|22|4|0|6
+9|5|1|5|12|-1|0|4
+9|10|2|5|12|-1|0|4
+9|15|3|5|12|-1|0|4
+9|22|4|7|12|-1|0|6
+11|4
+11|4
+12|4
+12|4
+12|4
+13|4
+13|4
+13|4
+14|1|1|1|2|4|1|0
+14|2|1|2|5|8|1|1
+14|3|1|3|6|9|1|2
+14|4|1|4|9|15|1|3
+14|5|1|5|12|-1|0|4
+14|6|2|1|2|4|1|0
+14|7|2|2|5|8|1|1
+14|8|2|3|6|11|1|2
+14|9|2|4|11|13|1|3
+14|10|2|5|12|-1|0|4
+15|1|1|1|2|4|1|0
+15|2|1|2|5|8|1|1
+15|3|1|3|6|9|1|2
+15|4|1|4|9|15|1|3
+15|5|1|5|12|-1|0|4
+15|6|2|1|2|4|1|0
+15|7|2|2|5|8|1|1
+15|8|2|3|6|11|1|2
+15|9|2|4|11|13|1|3
+15|10|2|5|12|-1|0|4
+15|11|3|1|2|4|1|0
+15|12|3|2|5|10|1|1
+15|13|3|3|10|12|1|2
+15|14|3|4|11|13|1|3
+15|15|3|5|12|-1|0|4
+16|1|1|1|2|4|1|0
+16|2|1|2|5|8|1|1
+16|3|1|3|6|9|1|2
+16|4|1|4|9|15|1|3
+16|5|1|5|12|-1|0|4
+16|6|2|1|2|4|1|0
+16|7|2|2|5|8|1|1
+16|8|2|3|6|11|1|2
+16|9|2|4|11|13|1|3
+16|10|2|5|12|-1|0|4
+16|11|3|1|2|4|1|0
+16|12|3|2|5|10|1|1
+16|13|3|3|10|12|1|2
+16|14|3|4|11|13|1|3
+16|15|3|5|12|-1|0|4
diff --git a/src/ksp/test/ksp-v3.test.sql b/src/ksp/test/ksp-v3.test.sql
new file mode 100644
index 0000000..49b7d74
--- /dev/null
+++ b/src/ksp/test/ksp-v3.test.sql
@@ -0,0 +1,117 @@
+--------------------------------------------------------------------------------
+-- PGR_ksp V3
+--------------------------------------------------------------------------------
+
+
+
+
+-- Examples to handle the one flag to choose signatures using :ref:`fig1-direct-Cost-Reverse`
+------------------------------------------------------------------------------------------
+
+
+ SELECT 1, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2,
+ true -- takes the (V2.0) signature (has_rcost = true and works on directed graph)
+ );
+
+
+ SELECT 2, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2,
+ directed:=true -- takes the new signature
+ );
+
+ SELECT 3, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2
+ );
+
+
+
+--Examples using :ref:`fig1-direct-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ SELECT 4, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2
+ );
+
+
+ SELECT 5, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, heap_paths:=true
+ );
+
+ SELECT 6, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, true, true
+ );
+
+--Example for :ref:`fig2-undirect-Cost-Reverse`
+-------------------------------------------------------------------------------
+
+
+ SELECT 7, seq, path_id, cost, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, directed:=false
+ );
+
+ SELECT 8, seq, path_id, cost, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, directed:=false, heap_paths:=true
+ );
+
+ SELECT 9, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost, reverse_cost FROM edge_table',
+ 2, 12, 2, false, true
+ ) where edge = -1;
+
+
+
+-- Examples for :ref:`fig3-direct-Cost`
+-------------------------------------------------------------------------------
+
+
+ SELECT 10, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 3, 2
+ );
+
+
+ SELECT 11, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2
+ ) where edge = -1 order by agg_cost;
+
+
+ SELECT 12, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, heap_paths:=true
+ ) where edge = -1 order by agg_cost;
+
+ SELECT 13, agg_cost FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, true, true
+ ) where edge = -1 order by agg_cost;
+
+--Examples for :ref:`fig4-undirect-Cost`
+-------------------------------------------------------------------------------
+
+
+ SELECT 14, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, directed:=false
+ );
+
+ SELECT 15, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, directed:=false, heap_paths:=true
+ );
+
+ SELECT 16, * FROM pgr_ksp(
+ 'SELECT id, source, target, cost FROM edge_table',
+ 2, 12, 2, false, true
+ );
+
diff --git a/src/ksp/test/makeTests.sh b/src/ksp/test/makeTests.sh
new file mode 100644
index 0000000..4837bc9
--- /dev/null
+++ b/src/ksp/test/makeTests.sh
@@ -0,0 +1,12 @@
+psql -U postgres -h localhost -A -t -q -f ksp-any-00.data ksp_test
+
+psql -U postgres -h localhost -A -t -q -f ksp-any-01.test ksp_test &> ksp-any-01.aaa
+sed s/psql:ksp-any-01.test:[0-9]*:// <ksp-any-01.aaa > ksp-any-01.rest
+
+psql -U postgres -h localhost -A -t -q -f ksp-any-02.test ksp_test &> ksp-any-02.aaa
+sed s/psql:ksp-any-02.test:[0-9]*:// <ksp-any-02.aaa >ksp-any-02.rest
+
+psql -U postgres -h localhost -A -t -q -f ksp-parallel-any-03.test ksp_test &> ksp-parallel-any-03.aaa
+sed s/psql:ksp-parallel-any-03.test:[0-9]*:// <ksp-parallel-any-03.aaa >ksp-parallel-any-03.rest
+
+rm *.aaa
diff --git a/src/ksp/test/show_data.result b/src/ksp/test/show_data.result
new file mode 100644
index 0000000..858e671
--- /dev/null
+++ b/src/ksp/test/show_data.result
@@ -0,0 +1,104 @@
+network
+1|0|1|1.4142135623731|7.07106781186548|0105000020110F00000100000001020000000200000000000000000000000000000000000000000000000000F03F000000000000F03F
+2|0|2|2.82842712474619|14.142135623731|0105000020110F0000010000000102000000020000000000000000000000000000000000000000000000000000400000000000000040
+3|0|3|4.24264068711928|21.2132034355964|0105000020110F0000010000000102000000020000000000000000000000000000000000000000000000000008400000000000000840
+4|1|0|1.4142135623731|7.07106781186548|0105000020110F000001000000010200000002000000000000000000F03F000000000000F03F00000000000000000000000000000000
+5|1|2|1.4142135623731|7.07106781186548|0105000020110F000001000000010200000002000000000000000000F03F000000000000F03F00000000000000400000000000000040
+6|1|7|6.08276253029822|30.4138126514911|0105000020110F000001000000010200000002000000000000000000F03F000000000000F03F0000000000001C400000000000000040
+7|2|0|2.82842712474619|14.142135623731|0105000020110F0000010000000102000000020000000000000000000040000000000000004000000000000000000000000000000000
+8|2|1|1.4142135623731|7.07106781186548|0105000020110F00000100000001020000000200000000000000000000400000000000000040000000000000F03F000000000000F03F
+9|2|5|4.47213595499958|22.3606797749979|0105000020110F0000010000000102000000020000000000000000000040000000000000004000000000000010400000000000001840
+10|3|0|4.24264068711928|21.2132034355964|0105000020110F0000010000000102000000020000000000000000000840000000000000084000000000000000000000000000000000
+11|3|4|1.4142135623731|7.07106781186548|0105000020110F0000010000000102000000020000000000000000000840000000000000084000000000000010400000000000001040
+12|3|10|9.89949493661167|49.4974746830583|0105000020110F0000010000000102000000020000000000000000000840000000000000084000000000000024400000000000002440
+13|4|3|1.4142135623731|7.07106781186548|0105000020110F0000010000000102000000020000000000000000001040000000000000104000000000000008400000000000000840
+14|4|6|2.23606797749979|11.1803398874989|0105000020110F0000010000000102000000020000000000000000001040000000000000104000000000000018400000000000001440
+15|4|5|2|10|0105000020110F0000010000000102000000020000000000000000001040000000000000104000000000000010400000000000001840
+16|5|2|4.47213595499958|22.3606797749979|0105000020110F0000010000000102000000020000000000000000001040000000000000184000000000000000400000000000000040
+17|5|4|2|10|0105000020110F0000010000000102000000020000000000000000001040000000000000184000000000000010400000000000001040
+18|5|9|2.82842712474619|14.142135623731|0105000020110F0000010000000102000000020000000000000000001040000000000000184000000000000000400000000000002040
+19|5|13|6.32455532033676|31.6227766016838|0105000020110F0000010000000102000000020000000000000000001040000000000000184000000000000000400000000000002840
+20|6|4|2.23606797749979|11.1803398874989|0105000020110F0000010000000102000000020000000000000000001840000000000000144000000000000010400000000000001040
+21|6|7|3.16227766016838|15.8113883008419|0105000020110F000001000000010200000002000000000000000000184000000000000014400000000000001C400000000000000040
+22|7|6|3.16227766016838|15.8113883008419|0105000020110F0000010000000102000000020000000000000000001C40000000000000004000000000000018400000000000001440
+23|7|8|6.70820393249937|33.5410196624969|0105000020110F0000010000000102000000020000000000000000001C40000000000000004000000000000010400000000000002040
+24|7|1|6.08276253029822|30.4138126514911|0105000020110F0000010000000102000000020000000000000000001C400000000000000040000000000000F03F000000000000F03F
+25|8|7|6.70820393249937|33.5410196624969|0105000020110F000001000000010200000002000000000000000000104000000000000020400000000000001C400000000000000040
+26|8|11|3.60555127546399|18.0277563773199|0105000020110F00000100000001020000000200000000000000000010400000000000002040000000000000F03F0000000000002440
+27|8|12|4|20|0105000020110F0000010000000102000000020000000000000000001040000000000000204000000000000010400000000000002840
+28|9|5|2.82842712474619|14.142135623731|0105000020110F0000010000000102000000020000000000000000000040000000000000204000000000000010400000000000001840
+29|10|3|9.89949493661167|49.4974746830583|0105000020110F0000010000000102000000020000000000000000002440000000000000244000000000000008400000000000000840
+30|10|11|9|45|0105000020110F00000100000001020000000200000000000000000024400000000000002440000000000000F03F0000000000002440
+31|10|12|6.32455532033676|31.6227766016838|0105000020110F0000010000000102000000020000000000000000002440000000000000244000000000000010400000000000002840
+32|11|8|3.60555127546399|18.0277563773199|0105000020110F000001000000010200000002000000000000000000F03F000000000000244000000000000010400000000000002040
+33|11|10|9|45|0105000020110F000001000000010200000002000000000000000000F03F000000000000244000000000000024400000000000002440
+34|11|13|2.23606797749979|11.1803398874989|0105000020110F000001000000010200000002000000000000000000F03F000000000000244000000000000000400000000000002840
+35|12|10|6.32455532033676|31.6227766016838|0105000020110F0000010000000102000000020000000000000000001040000000000000284000000000000024400000000000002440
+36|12|8|4|20|0105000020110F0000010000000102000000020000000000000000001040000000000000284000000000000010400000000000002040
+37|12|13|2|10|0105000020110F0000010000000102000000020000000000000000001040000000000000284000000000000000400000000000002840
+38|13|12|2|10|0105000020110F0000010000000102000000020000000000000000000040000000000000284000000000000010400000000000002840
+39|13|5|6.32455532033676|31.6227766016838|0105000020110F0000010000000102000000020000000000000000000040000000000000284000000000000010400000000000001840
+40|13|11|2.23606797749979|11.1803398874989|0105000020110F00000100000001020000000200000000000000000000400000000000002840000000000000F03F0000000000002440
+nodes
+1|0|Zero|0101000020110F000000000000000000000000000000000000
+2|1|One|0101000020110F0000000000000000F03F000000000000F03F
+3|2|Two|0101000020110F000000000000000000400000000000000040
+4|3|Three|0101000020110F000000000000000008400000000000000840
+5|4|Four|0101000020110F000000000000000010400000000000001040
+6|5|Five|0101000020110F000000000000000010400000000000001840
+7|6|Six|0101000020110F000000000000000018400000000000001440
+8|7|Seven|0101000020110F00000000000000001C400000000000000040
+9|8|Eight|0101000020110F000000000000000010400000000000002040
+10|9|Nine|0101000020110F000000000000000000400000000000002040
+11|10|Ten|0101000020110F000000000000000024400000000000002440
+12|11|Eleven|0101000020110F0000000000000000F03F0000000000002440
+13|12|Twelve|0101000020110F000000000000000010400000000000002840
+14|13|Thirteen|0101000020110F000000000000000000400000000000002840
+edge_table
+1|B|1|2|1|1|2|0|2|1|010200000002000000000000000000004000000000000000000000000000000040000000000000F03F
+2|TF|2|3|-1|1|2|1|3|1|0102000000020000000000000000000040000000000000F03F0000000000000840000000000000F03F
+3|TF|3|4|-1|1|3|1|4|1|0102000000020000000000000000000840000000000000F03F0000000000001040000000000000F03F
+4|B|2|5|1|1|2|1|2|2|0102000000020000000000000000000040000000000000F03F00000000000000400000000000000040
+5|FT|3|6|1|-1|3|1|3|2|0102000000020000000000000000000840000000000000F03F00000000000008400000000000000040
+6|B|7|8|1|1|0|2|1|2|01020000000200000000000000000000000000000000000040000000000000F03F0000000000000040
+7|B|8|5|1|1|1|2|2|2|010200000002000000000000000000F03F000000000000004000000000000000400000000000000040
+8|B|5|6|1|1|2|2|3|2|0102000000020000000000000000000040000000000000004000000000000008400000000000000040
+9|B|6|9|1|1|3|2|4|2|0102000000020000000000000000000840000000000000004000000000000010400000000000000040
+10|B|5|10|1|1|2|2|2|3|0102000000020000000000000000000040000000000000004000000000000000400000000000000840
+11|FT|6|11|1|-1|3|2|3|3|0102000000020000000000000000000840000000000000004000000000000008400000000000000840
+12|FT|10|11|1|-1|2|3|3|3|0102000000020000000000000000000040000000000000084000000000000008400000000000000840
+13|FT|11|12|1|-1|3|3|4|3|0102000000020000000000000000000840000000000000084000000000000010400000000000000840
+14|B|10|13|1|1|2|3|2|4|0102000000020000000000000000000040000000000000084000000000000000400000000000001040
+15|B|9|12|1|1|4|2|4|3|0102000000020000000000000000001040000000000000004000000000000010400000000000000840
+16|B|4|9|1|1|4|1|4|2|0102000000020000000000000000001040000000000000F03F00000000000010400000000000000040
+17|B|14|15|1|1|0.5|3.5|1.999999999999|3.5|010200000002000000000000000000E03F0000000000000C4068EEFFFFFFFFFF3F0000000000000C40
+18|B|16|17|1|1|3.5|2.3|3.5|4|0102000000020000000000000000000C4066666666666602400000000000000C400000000000001040
+edge_table_vertices
+1|||||010100000000000000000000400000000000000000
+2|||||01010000000000000000000040000000000000F03F
+3|||||01010000000000000000000840000000000000F03F
+4|||||01010000000000000000001040000000000000F03F
+5|||||010100000000000000000000400000000000000040
+6|||||010100000000000000000008400000000000000040
+7|||||010100000000000000000000000000000000000040
+8|||||0101000000000000000000F03F0000000000000040
+9|||||010100000000000000000010400000000000000040
+10|||||010100000000000000000000400000000000000840
+11|||||010100000000000000000008400000000000000840
+12|||||010100000000000000000010400000000000000840
+13|||||010100000000000000000000400000000000001040
+14|||||0101000000000000000000E03F0000000000000C40
+15|||||010100000068EEFFFFFFFFFF3F0000000000000C40
+16|||||01010000000000000000000C406666666666660240
+17|||||01010000000000000000000C400000000000001040
+paralell
+1|1|2|1|1|1|0|1|1|010200000002000000000000000000F03F0000000000000000000000000000F03F000000000000F03F
+2|2|3|2|2|1|1|1|3|010200000002000000000000000000F03F000000000000F03F000000000000F03F0000000000000840
+3|2|3|2.82842712474619|2.82842712474619|1|1|1|3|010200000003000000000000000000F03F000000000000F03F00000000000000000000000000000040000000000000F03F0000000000000840
+4|2|3|4|4|1|1|1|3|010200000004000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000840000000000000F03F0000000000000840
+5|3|4|1|1|1|3|1|4|010200000002000000000000000000F03F0000000000000840000000000000F03F0000000000001040
+paralell_vertices
+1|||||0101000000000000000000F03F0000000000000000
+2|||||0101000000000000000000F03F000000000000F03F
+3|||||0101000000000000000000F03F0000000000000840
+4|||||0101000000000000000000F03F0000000000001040
diff --git a/src/ksp/test/show_data.test.sql b/src/ksp/test/show_data.test.sql
new file mode 100644
index 0000000..14a0416
--- /dev/null
+++ b/src/ksp/test/show_data.test.sql
@@ -0,0 +1,18 @@
+--------------------------------------------------
+-- Test to see that we are working with the same data
+--------------------------------------------------
+\echo network
+select * from network order by id;
+\echo nodes
+select * from nodes order by id;
+--------------------------------------------------
+\echo edge_table
+select * from edge_table order by id;
+\echo edge_table_vertices
+select * from edge_table_vertices_pgr order by id;
+--------------------------------------------------
+\echo paralell
+select * from parallel order by id;
+\echo paralell_vertices
+select * from parallel_vertices_pgr order by id;
+
diff --git a/src/ksp/test/test.conf b/src/ksp/test/test.conf
index cadeada..addfc85 100644
--- a/src/ksp/test/test.conf
+++ b/src/ksp/test/test.conf
@@ -4,7 +4,17 @@
'any' => {
'comment' => 'KSP test for any versions.',
'data' => ['ksp-any-00.data'],
- 'tests' => [qw(ksp-any-01 ksp-any-02)]
+ 'tests' => [qw(
+show_data
+ksp-v3-1route
+ksp-parallel-any-03
+ksp-any-01
+ksp-any-02
+ksp-v2
+ksp-v3
+)],
+ 'not done tests' => [qw(
+)]
},
# 'vpg-vpgis' => {}, # for version specific tests
# '8-1' => {}, # for pg 8.x and postgis 1.x
diff --git a/src/driving_distance/CMakeLists.txt b/src/label_graph/CMakeLists.txt
similarity index 69%
copy from src/driving_distance/CMakeLists.txt
copy to src/label_graph/CMakeLists.txt
index c4a8382..c51535e 100644
--- a/src/driving_distance/CMakeLists.txt
+++ b/src/label_graph/CMakeLists.txt
@@ -1,5 +1,4 @@
SET(PACKAGE_SQL_FILES "")
ADD_SUBDIRECTORY(sql)
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
-#MESSAGE("core/driving_distance: ${PACKAGE_SQL_FILES}")
SUBDIRS(doc src test)
diff --git a/src/common/src/CMakeLists.txt b/src/label_graph/doc/CMakeLists.txt
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/label_graph/doc/CMakeLists.txt
diff --git a/src/label_graph/doc/analyze_brokengraph.rst b/src/label_graph/doc/analyze_brokengraph.rst
new file mode 100644
index 0000000..501d898
--- /dev/null
+++ b/src/label_graph/doc/analyze_brokengraph.rst
@@ -0,0 +1,176 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_labelGraph:
+
+
+pgr_labelGraph
+===============================================================================
+
+.. index::
+ single: pgr_labelGraph(text, text, text, text, text, text)
+ module: common
+
+
+
+Name
+-------------------------------------------------------------------------------
+
+``pgr_labelGraph`` — Locates and labels sub-networks within a network which are not topologically connected. Must be run after ``pgr_createTopology()``. No use of ``geometry`` column. Only ``id``, ``source`` and ``target`` columns are required.
+
+
+
+Synopsis
+-------------------------------------------------------------------------------
+
+The function returns:
+
+ - ``OK`` when a column with provided name has been generated and populated successfully. All connected edges will have unique similar integer values. In case of ``rows_where`` condition, non participating rows will have -1 integer values.
+ - ``FAIL`` when the processing cannot be finished due to some error. Notice will be thrown accordingly.
+ - ``rows_where condition generated 0 rows`` when passed SQL condition has not been fulfilled by any row.
+
+.. code-block:: sql
+
+ varchar pgr_labelGraph(text, text, text, text, text, text)
+
+
+
+Description
+-------------------------------------------------------------------------------
+
+A network behind any routing query may consist of sub-networks completely isolated from each other. Possible reasons could be:
+
+- An island with no bridge connecting to the mainland.
+- An edge or mesh of edges failed to connect to other networks because of human negligence during data generation.
+- The data is not properly noded.
+- Topology creation failed to succeed.
+
+pgr_labelGraph() will create an integer column (with the name provided by the user) and will assign same integer values to all those edges in the network which are connected topologically. Thus better analysis regarding network structure is possible. In case of ``rows_where`` condition, non participating rows will have -1 integer values.
+
+Prerequisites:
+Must run ``pgr_createTopology()`` in order to generate ``source`` and ``target`` columns. Primary key column ``id`` should also be there in the network table.
+
+Function accepts the following parameters:
+
+:edge_table: ``text`` Network table name, with optional schema name.
+:id: ``text`` Primary key column name of the network table. Default is ``id``.
+:source: ``text`` Source column name generated after ``pgr_createTopology()``. Default is ``source``.
+:target: ``text`` Target column name generated after ``pgr_createTopology()``. Default is ``target``.
+:subgraph: ``text`` Column name which will hold the integer labels for each sub-graph. Default is ``subgraph``.
+:rows_where: ``text`` The SQL where condition. Default is ``true``, means the processing will be done on the whole table.
+
+
+
+
+Possible Usage
+-------------------------------------------------------------------------------
+-- The following should be OK
+
+.. code-block:: sql
+
+ select pgr_labelGraph('ways');
+ select pgr_labelGraph('Ways');
+ select pgr_labelGraph('ways', 'id');
+ select pgr_labelGraph('ways', 'id', 'source');
+ select pgr_labelGraph('ways', 'id', 'source', 'target');
+ select pgr_labelGraph('ways', 'id', 'source', 'target', 'subgraph');
+ select pgr_labelGraph('ways', 'id', 'source', 'target', 'subgraph', 'id<100');
+
+-- When table located in another schema e03
+
+.. code-block:: sql
+
+ select pgr_labelGraph('e03.ways');
+ select pgr_labelGraph('e03.Ways');
+ select pgr_labelGraph('e03.ways', 'id');
+ select pgr_labelGraph('e03.ways', 'id', 'source');
+ select pgr_labelGraph('e03.ways', 'id', 'source', 'target');
+ select pgr_labelGraph('e03.ways', 'id', 'source', 'target', 'subgraph');
+ select pgr_labelGraph('e03.ways', 'id', 'source', 'target', 'subgraph', 'id<100');
+
+-- When using the named notation
+
+.. code-block:: sql
+
+ select pgr_labelGraph('e03.calles', target:='destino', subgraph:='subgraph', id:='gido', source:='salida');
+ select pgr_labelGraph('e03.calles', rows_where:='gido<100', id:='gido', source:='salida', target:='destino', subgraph:='subgraph');
+
+-- The following should FAIL
+
+.. code-block:: sql
+
+ select pgr_labelGraph('id', 'ways');
+ select pgr_labelGraph('ways', 'id', 'sourc', 'target');
+ select pgr_labelGraph('ways', 'id', 'source', 'Target');
+ select pgr_labelGraph('ways', 'id', 'source', 'target', 'subgraph', 'id<');
+
+-- When table located in another schema e03
+
+.. code-block:: sql
+
+ select pgr_labelGraph('e03.calles');
+ select pgr_labelGraph('e03.Calles');
+ select pgr_labelGraph('id', 'e03.calles');
+ select pgr_labelGraph('e03.calles', 'id', 'sourc', 'target');
+ select pgr_labelGraph('e03.calles', 'gido', 'source', 'target', 'subgraph', 'id<');
+ select pgr_labelGraph('e03.calles', 'gid', 'salida', 'target', 'subgraph', 'id<10');
+ select pgr_labelGraph('e03.calles', 'gid', 'salida', 'destino', 'subgraph', 'id<10 AND id>100');
+
+-- When using the named notation
+
+.. code-block:: sql
+
+ select pgr_labelGraph('e03.calles', target:='destino', subgraph:='subgraph', id:='gido');
+ select pgr_labelGraph('e03.calles', target:='destino', subgraph:='subgraph', id:='gido', source:='salido');
+ select pgr_labelGraph(rows_where:='gido<100', id:='gido', source:='salida', 'e03.calles', target:='destino', subgraph:='subgraph');
+
+-- The following should return "rows_where condition generated 0 rows"
+
+.. code-block:: sql
+
+ select pgr_labelGraph('ways', 'id', 'source', 'target', 'subgraph', 'id<10 AND id>100');
+ select pgr_labelGraph('e03.calles', id:='gido', rows_where:='gido<100 AND gido>200', source:='salida', target:='destino', subgraph:='subgraph');
+
+
+
+
+Examples Output pane Messages
+-------------------------------------------------------------------------------
+
+.. code-block:: sql
+
+ NOTICE: Processing:
+ NOTICE: pgr_labelGraph('ways','id','source','target','subgraph','true')
+ NOTICE: Performing initial checks, please hold on ...
+ NOTICE: Starting - Checking table ...
+ NOTICE: Ending - Checking table
+ NOTICE: Starting - Checking columns
+ NOTICE: Ending - Checking columns
+ NOTICE: Starting - Checking rows_where condition
+ NOTICE: Ending - Checking rows_where condition
+ NOTICE: Starting - Calculating subgraphs
+ NOTICE: Successfully complicated calculating subgraphs
+ NOTICE: Ending - Calculating subgraphs
+
+ Total query runtime: 5426 ms.
+ 1 row retrieved.
+
+ pgr_labelgraph
+ character varying
+ --------------------
+ OK
+ (1 row)
+
+
+
+
+See Also
+-------------------------------------------------------------------------------
+
+* `pgr_createTopology <https://github.com/Zia-/pgrouting/blob/develop/src/common/sql/pgrouting_topology.sql>`_ to create the topology of a table based on its geometry and tolerance value.
diff --git a/src/ksp/sql/CMakeLists.txt b/src/label_graph/sql/CMakeLists.txt
similarity index 70%
copy from src/ksp/sql/CMakeLists.txt
copy to src/label_graph/sql/CMakeLists.txt
index dd5c7d9..7cc8c31 100644
--- a/src/ksp/sql/CMakeLists.txt
+++ b/src/label_graph/sql/CMakeLists.txt
@@ -1,7 +1,7 @@
# Append in local scope
LIST(APPEND PACKAGE_SQL_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/routing_ksp.sql)
-
+ ${CMAKE_CURRENT_SOURCE_DIR}/label_graph.sql
+)
+
# set in parent scope
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
-
diff --git a/src/label_graph/sql/label_graph.sql b/src/label_graph/sql/label_graph.sql
new file mode 100644
index 0000000..bd079fa
--- /dev/null
+++ b/src/label_graph/sql/label_graph.sql
@@ -0,0 +1,172 @@
+CREATE OR REPLACE FUNCTION pgr_labelGraph(
+ edge_table text,
+ id text default 'id',
+ source text default 'source',
+ target text default 'target',
+ subgraph text default 'subgraph',
+ rows_where text default 'true'
+ )
+ RETURNS character varying AS
+$BODY$
+
+DECLARE
+ naming record;
+ schema_name text;
+ table_name text;
+ garbage text;
+ incre integer;
+ table_schema_name text;
+ query text;
+ ecnt integer;
+ sql1 text;
+ rec1 record;
+ sql2 text;
+ rec2 record;
+ rec_count record;
+ rec_single record;
+ graph_id integer;
+ gids int [];
+
+BEGIN
+ raise notice 'Processing:';
+ raise notice 'pgr_brokenGraph(''%'',''%'',''%'',''%'',''%'',''%'')', edge_table,id,source,target,subgraph,rows_where;
+ raise notice 'Performing initial checks, please hold on ...';
+
+ Raise Notice 'Starting - Checking table ...';
+ BEGIN
+ raise debug 'Checking % table existance', edge_table;
+ execute 'select * from pgr_getTableName('|| quote_literal(edge_table) ||')' into naming;
+ schema_name = naming.sname;
+ table_name = naming.tname;
+ table_schema_name = schema_name||'.'||table_name;
+ IF schema_name is null then
+ raise notice 'no schema';
+ return 'FAIL';
+ else
+ if table_name is null then
+ raise notice 'no table';
+ return 'FAIL';
+ end if;
+ end if;
+ END;
+ Raise Notice 'Ending - Checking table';
+
+ Raise Notice 'Starting - Checking columns';
+ BEGIN
+ raise debug 'Checking exitance of necessary columns inside % table', edge_table;
+ execute 'select * from pgr_isColumnInTable('|| quote_literal(table_schema_name) ||', '|| quote_literal(id) ||')' into naming;
+ if naming.pgr_iscolumnintable = 'f' then
+ raise notice 'no id column';
+ return 'FAIL';
+ end if;
+ execute 'select * from pgr_isColumnInTable('|| quote_literal(table_schema_name) ||', '|| quote_literal(source) ||')' into naming;
+ if naming.pgr_iscolumnintable = 'f' then
+ raise notice 'no source column';
+ return 'FAIL';
+ end if;
+ execute 'select * from pgr_isColumnInTable('|| quote_literal(table_schema_name) ||', '|| quote_literal(target) ||')' into naming;
+ if naming.pgr_iscolumnintable = 'f' then
+ raise notice 'no target column';
+ return 'FAIL';
+ end if;
+ execute 'select * from pgr_isColumnInTable('|| quote_literal(table_schema_name) ||', '|| quote_literal(subgraph) ||')' into naming;
+ if naming.pgr_iscolumnintable = 't' then
+ raise notice 'subgraph column already in the table';
+ return 'FAIL';
+ end if;
+ END;
+ Raise Notice 'Ending - Checking columns';
+
+ Raise Notice 'Starting - Checking rows_where condition';
+ BEGIN
+ raise debug 'Checking rows_where condition';
+ query='select count(*) from '|| pgr_quote_ident(table_schema_name) ||' where '|| rows_where;
+ execute query into ecnt;
+ raise debug '-->Rows where condition: OK';
+ raise debug ' --> OK';
+ EXCEPTION WHEN OTHERS THEN
+ raise notice 'Got %', SQLERRM;
+ Raise notice 'ERROR: Condition is not correct. Please execute the following query to test your condition';
+ Raise notice '%', query;
+ return 'FAIL';
+ END;
+ Raise Notice 'Ending - Checking rows_where condition';
+
+ garbage := 'garbage001';
+ incre := 1;
+ Raise Notice 'Starting - Checking temporary column';
+ Begin
+ raise debug 'Checking Checking temporary columns existance';
+
+ While True
+ Loop
+ execute 'select * from pgr_isColumnInTable('|| quote_literal(table_schema_name) ||', '|| quote_literal(garbage) ||')' into naming;
+ If naming.pgr_iscolumnintable = 't' THEN
+ incre := incre + 1;
+ garbage := 'garbage00'||incre||'';
+ ELSE
+ EXIT;
+ END IF;
+ End Loop;
+ End;
+ Raise Notice 'Ending - Checking temporary column';
+
+ Raise Notice 'Starting - Calculating subgraphs';
+ BEGIN
+ --------- Add necessary columns ----------
+ EXECUTE 'ALTER TABLE '|| pgr_quote_ident(table_schema_name) ||' ADD COLUMN ' || pgr_quote_ident(subgraph) || ' INTEGER DEFAULT -1';
+ EXECUTE 'ALTER TABLE '|| pgr_quote_ident(table_schema_name) ||' ADD COLUMN ' || pgr_quote_ident(garbage) || ' INTEGER DEFAULT 0';
+ graph_id := 1;
+
+ EXECUTE 'select count(*) as count from '|| pgr_quote_ident(table_schema_name) ||' where '|| rows_where ||'' into rec_count;
+ if rec_count.count = 0 then
+ RETURN 'rows_where condition generated 0 rows';
+ end if;
+
+ WHILE TRUE
+ LOOP
+ ---------- Assign the very first -1 row graph_id ----------
+ EXECUTE 'SELECT ' || pgr_quote_ident(id) || ' AS gid FROM '|| pgr_quote_ident(table_schema_name) ||' WHERE '|| rows_where ||' AND ' || pgr_quote_ident(subgraph) || ' = -1 LIMIT 1' INTO rec_single;
+ EXECUTE 'UPDATE '|| pgr_quote_ident(table_schema_name) ||' SET ' || pgr_quote_ident(subgraph) || ' = ' || graph_id || ' WHERE ' || pgr_quote_ident(id) || ' = ' || rec_single.gid || '';
+
+ --------- Search other rows with that particular graph_id -----------
+ WHILE TRUE
+ LOOP
+ EXECUTE 'SELECT COUNT(*) FROM '|| pgr_quote_ident(table_schema_name) ||' WHERE ' || pgr_quote_ident(subgraph) || ' = ' || graph_id || ' AND ' || pgr_quote_ident(garbage) || ' = 0' into rec_count;
+ ----------- The following if else will check those rows which already have entertained ------------
+ IF (rec_count.count > 0) THEN
+ sql1 := 'SELECT ' || pgr_quote_ident(id) || ' AS gid, ' || pgr_quote_ident(source) || ' AS source, ' || pgr_quote_ident(target) || ' AS target FROM '|| pgr_quote_ident(table_schema_name) ||' WHERE ' || pgr_quote_ident(subgraph) || ' = ' || graph_id || ' AND ' || pgr_quote_ident(garbage) || ' = 0';
+ FOR rec1 IN EXECUTE sql1
+ LOOP
+ sql2 := 'SELECT ' || pgr_quote_ident(id) || ' AS gid, ' || pgr_quote_ident(source) || ' AS source, ' || pgr_quote_ident(target) || ' AS target FROM '|| pgr_quote_ident(table_schema_name) ||' WHERE '|| pgr_quote_ident(source) ||' = '|| rec1.source ||' OR '|| pgr_quote_ident(target) ||' = '|| rec1.source ||' OR '|| pgr_quote_ident(source) ||' = '|| rec1.target ||' OR '|| pgr_quote_ident(target) ||' = '|| rec1.target ||'';
+ FOR rec2 IN EXECUTE sql2
+ LOOP
+ EXECUTE 'UPDATE '|| pgr_quote_ident(table_schema_name) ||' SET ' || pgr_quote_ident(subgraph) || ' = ' || graph_id || ' WHERE ' || pgr_quote_ident(id) || ' = ' || rec2.gid || '';
+ END LOOP;
+ EXECUTE 'UPDATE '|| pgr_quote_ident(table_schema_name) ||' SET ' || pgr_quote_ident(garbage) || ' = 1 WHERE ' || pgr_quote_ident(id) || ' = ' || rec1.gid || '';
+ END LOOP;
+ ELSE
+ EXIT;
+ END IF;
+ END LOOP;
+
+ ------ Following is to exit the while loop. 0 means no more -1 id.
+ EXECUTE 'SELECT COUNT(*) AS count FROM '|| pgr_quote_ident(table_schema_name) ||' WHERE '|| rows_where ||' AND ' || pgr_quote_ident(subgraph) || ' = -1' INTO rec_count;
+ If (rec_count.count = 0) THEN
+ EXIT;
+ ELSE
+ graph_id := graph_id + 1;
+ END IF;
+ END LOOP;
+
+ ----------- Drop garbage column ------------
+ EXECUTE 'ALTER TABLE '|| pgr_quote_ident(table_schema_name) ||' DROP COLUMN ' || pgr_quote_ident(garbage) ||'';
+ Raise Notice 'Successfully complicated calculating subgraphs';
+ END;
+ Raise Notice 'Ending - Calculating subgraphs';
+
+ RETURN 'OK';
+
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE STRICT;
diff --git a/src/common/src/CMakeLists.txt b/src/label_graph/src/CMakeLists.txt
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/label_graph/src/CMakeLists.txt
diff --git a/src/common/src/CMakeLists.txt b/src/label_graph/test/CMakeLists.txt
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/label_graph/test/CMakeLists.txt
diff --git a/src/label_graph/test/pgrouting_brokengraph.data b/src/label_graph/test/pgrouting_brokengraph.data
new file mode 100644
index 0000000..9ec2ffd
--- /dev/null
+++ b/src/label_graph/test/pgrouting_brokengraph.data
@@ -0,0 +1,4214 @@
+create schema e03;
+
+create table ways(
+ id integer,
+ source integer,
+ target integer
+);
+
+insert into ways values
+ (1, 1, 2),
+ (2, 2, 3),
+ (3, 3, 4),
+ (4, 4, 5),
+ (5, 5, 6),
+ (7, 7, 8),
+ (8, 9, 10),
+ (9, 11, 12),
+ (10, 12, 13),
+ (11, 13, 14),
+ (12, 14, 15),
+ (13, 15, 16),
+ (15, 17, 18),
+ (16, 18, 19),
+ (17, 19, 20),
+ (18, 20, 21),
+ (19, 21, 22),
+ (20, 22, 23),
+ (21, 23, 24),
+ (22, 24, 25),
+ (23, 25, 26),
+ (24, 26, 27),
+ (25, 27, 28),
+ (26, 28, 29),
+ (27, 29, 30),
+ (28, 30, 31),
+ (29, 31, 32),
+ (31, 33, 34),
+ (32, 34, 35),
+ (33, 35, 36),
+ (34, 36, 37),
+ (35, 37, 38),
+ (36, 38, 39),
+ (37, 39, 40),
+ (38, 40, 41),
+ (39, 41, 42),
+ (40, 42, 43),
+ (41, 43, 44),
+ (42, 44, 45),
+ (43, 45, 46),
+ (44, 46, 47),
+ (45, 47, 48),
+ (46, 48, 49),
+ (47, 49, 50),
+ (48, 50, 51),
+ (49, 51, 52),
+ (50, 52, 53),
+ (51, 53, 54),
+ (52, 54, 55),
+ (53, 55, 56),
+ (54, 56, 57),
+ (55, 57, 58),
+ (56, 58, 59),
+ (57, 59, 60),
+ (58, 60, 61),
+ (59, 61, 62),
+ (60, 62, 63),
+ (61, 63, 64),
+ (62, 64, 65),
+ (63, 65, 66),
+ (64, 66, 67),
+ (65, 67, 68),
+ (66, 68, 69),
+ (67, 69, 70),
+ (69, 41, 71),
+ (70, 71, 72),
+ (71, 72, 73),
+ (72, 73, 74),
+ (73, 74, 75),
+ (74, 75, 76),
+ (75, 76, 77),
+ (76, 77, 78),
+ (77, 78, 79),
+ (78, 79, 80),
+ (79, 80, 81),
+ (80, 81, 82),
+ (81, 82, 83),
+ (82, 83, 84),
+ (83, 84, 85),
+ (84, 85, 86),
+ (85, 86, 87),
+ (86, 87, 88),
+ (87, 88, 89),
+ (88, 89, 90),
+ (89, 90, 91),
+ (90, 91, 92),
+ (91, 92, 93),
+ (92, 93, 94),
+ (93, 94, 95),
+ (94, 95, 96),
+ (95, 96, 97),
+ (96, 97, 98),
+ (97, 98, 99),
+ (98, 99, 100),
+ (99, 100, 101),
+ (100, 101, 102),
+ (101, 102, 103),
+ (102, 103, 62),
+ (103, 62, 104),
+ (105, 105, 106),
+ (106, 106, 48),
+ (107, 48, 107),
+ (108, 107, 108),
+ (109, 108, 109),
+ (110, 109, 110),
+ (111, 110, 111),
+ (112, 111, 112),
+ (113, 112, 113),
+ (114, 113, 114),
+ (115, 114, 115),
+ (116, 115, 116),
+ (117, 116, 117),
+ (118, 117, 118),
+ (119, 118, 119),
+ (120, 119, 120),
+ (121, 120, 121),
+ (122, 121, 122),
+ (124, 122, 123),
+ (125, 123, 124),
+ (126, 124, 125),
+ (127, 125, 126),
+ (128, 126, 127),
+ (129, 127, 128),
+ (130, 128, 129),
+ (132, 6, 130),
+ (133, 130, 131),
+ (134, 131, 132),
+ (135, 132, 133),
+ (136, 133, 134),
+ (137, 134, 135),
+ (138, 135, 136),
+ (139, 137, 138),
+ (140, 138, 139),
+ (141, 139, 140),
+ (142, 140, 141),
+ (143, 141, 142),
+ (144, 142, 143),
+ (146, 144, 145),
+ (148, 146, 147),
+ (149, 147, 148),
+ (150, 148, 149),
+ (151, 149, 150),
+ (152, 150, 151),
+ (153, 151, 152),
+ (154, 152, 153),
+ (155, 153, 154),
+ (156, 154, 155),
+ (157, 155, 156),
+ (159, 157, 158),
+ (160, 158, 159),
+ (162, 160, 161),
+ (163, 161, 162),
+ (164, 162, 163),
+ (165, 163, 164),
+ (166, 164, 165),
+ (167, 165, 166),
+ (168, 166, 167),
+ (169, 167, 168),
+ (170, 168, 169),
+ (171, 169, 170),
+ (172, 170, 171),
+ (173, 171, 172),
+ (174, 172, 159),
+ (176, 173, 174),
+ (178, 175, 176),
+ (179, 176, 177),
+ (180, 177, 178),
+ (181, 178, 179),
+ (182, 179, 180),
+ (183, 181, 178),
+ (184, 178, 182),
+ (185, 179, 183),
+ (186, 183, 184),
+ (188, 151, 185),
+ (190, 186, 187),
+ (191, 188, 189),
+ (192, 189, 190),
+ (193, 190, 191),
+ (194, 191, 192),
+ (195, 192, 193),
+ (196, 193, 194),
+ (197, 194, 195),
+ (198, 196, 197),
+ (199, 197, 198),
+ (200, 198, 199),
+ (202, 200, 201),
+ (203, 201, 197),
+ (204, 197, 202),
+ (205, 202, 203),
+ (206, 203, 204),
+ (207, 204, 205),
+ (209, 204, 199),
+ (211, 206, 207),
+ (212, 207, 208),
+ (213, 207, 209),
+ (214, 210, 211),
+ (216, 212, 213),
+ (217, 213, 214),
+ (218, 214, 215),
+ (220, 216, 217),
+ (221, 217, 218),
+ (223, 219, 220),
+ (224, 220, 221),
+ (225, 221, 222),
+ (226, 222, 223),
+ (227, 223, 224),
+ (228, 224, 225),
+ (229, 225, 226),
+ (230, 226, 219),
+ (232, 213, 227),
+ (234, 228, 229),
+ (235, 229, 227),
+ (236, 227, 230),
+ (237, 230, 231),
+ (239, 232, 233),
+ (240, 233, 234),
+ (241, 234, 235),
+ (243, 236, 237),
+ (244, 237, 238),
+ (245, 238, 239),
+ (246, 239, 240),
+ (247, 240, 241),
+ (248, 241, 242),
+ (249, 242, 243),
+ (250, 243, 244),
+ (251, 244, 245),
+ (252, 245, 246),
+ (253, 246, 247),
+ (254, 247, 248),
+ (255, 248, 249),
+ (256, 249, 250),
+ (257, 250, 251),
+ (258, 251, 252),
+ (259, 252, 253),
+ (260, 253, 254),
+ (261, 254, 255),
+ (262, 255, 256),
+ (263, 256, 257),
+ (265, 237, 235),
+ (266, 235, 258),
+ (268, 259, 260),
+ (269, 260, 261),
+ (270, 262, 263),
+ (272, 259, 263),
+ (274, 263, 264),
+ (275, 264, 265),
+ (276, 265, 266),
+ (277, 266, 267),
+ (278, 267, 268),
+ (280, 265, 269),
+ (281, 269, 270),
+ (282, 270, 271),
+ (283, 269, 266),
+ (285, 272, 218),
+ (286, 218, 231),
+ (287, 231, 272),
+ (289, 273, 274),
+ (291, 275, 274),
+ (292, 274, 246),
+ (294, 276, 277),
+ (295, 278, 279),
+ (296, 279, 280),
+ (297, 280, 281),
+ (298, 281, 282),
+ (299, 282, 283),
+ (300, 283, 284),
+ (301, 284, 285),
+ (302, 285, 286),
+ (303, 286, 276),
+ (304, 276, 287),
+ (305, 288, 289),
+ (306, 289, 290),
+ (307, 290, 257),
+ (309, 291, 292),
+ (310, 292, 293),
+ (312, 294, 295),
+ (314, 296, 288),
+ (315, 288, 289),
+ (316, 289, 286),
+ (317, 286, 285),
+ (319, 297, 298),
+ (320, 299, 300),
+ (321, 300, 301),
+ (322, 302, 303),
+ (324, 304, 305),
+ (325, 77, 306),
+ (373, 347, 348),
+ (327, 3, 307),
+ (328, 307, 308),
+ (330, 309, 310),
+ (331, 310, 4),
+ (333, 311, 312),
+ (334, 312, 313),
+ (335, 313, 314),
+ (336, 314, 315),
+ (337, 316, 317),
+ (338, 317, 318),
+ (339, 318, 319),
+ (341, 320, 321),
+ (342, 321, 322),
+ (343, 322, 323),
+ (345, 322, 324),
+ (347, 38, 325),
+ (348, 325, 326),
+ (349, 326, 327),
+ (350, 327, 328),
+ (351, 328, 329),
+ (352, 329, 330),
+ (353, 330, 43),
+ (355, 115, 331),
+ (356, 332, 333),
+ (357, 333, 334),
+ (358, 334, 335),
+ (359, 335, 336),
+ (361, 335, 337),
+ (362, 337, 338),
+ (363, 338, 59),
+ (365, 339, 340),
+ (366, 340, 341),
+ (367, 341, 342),
+ (368, 342, 343),
+ (369, 343, 344),
+ (370, 344, 345),
+ (371, 345, 346),
+ (372, 346, 347),
+ (374, 348, 349),
+ (376, 346, 350),
+ (377, 350, 351),
+ (378, 351, 352),
+ (380, 353, 354),
+ (381, 354, 355),
+ (382, 355, 356),
+ (383, 356, 357),
+ (384, 357, 358),
+ (385, 358, 359),
+ (386, 359, 360),
+ (387, 360, 361),
+ (388, 361, 362),
+ (389, 362, 363),
+ (390, 363, 364),
+ (391, 364, 365),
+ (392, 365, 366),
+ (393, 366, 367),
+ (394, 367, 368),
+ (395, 368, 369),
+ (396, 369, 370),
+ (397, 370, 86),
+ (398, 86, 371),
+ (400, 354, 372),
+ (401, 372, 373),
+ (402, 373, 374),
+ (403, 374, 375),
+ (404, 375, 376),
+ (405, 376, 377),
+ (406, 377, 378),
+ (407, 378, 379),
+ (408, 379, 380),
+ (409, 380, 381),
+ (410, 381, 382),
+ (411, 382, 383),
+ (413, 55, 384),
+ (414, 384, 385),
+ (415, 385, 336),
+ (416, 336, 386),
+ (417, 386, 387),
+ (418, 385, 388),
+ (419, 388, 58),
+ (421, 389, 50),
+ (422, 50, 390),
+ (423, 390, 391),
+ (424, 391, 392),
+ (425, 392, 88),
+ (427, 36, 393),
+ (428, 393, 394),
+ (429, 394, 395),
+ (430, 395, 396),
+ (431, 396, 352),
+ (432, 352, 397),
+ (433, 397, 339),
+ (434, 339, 398),
+ (435, 398, 399),
+ (436, 399, 400),
+ (437, 400, 401),
+ (438, 401, 402),
+ (439, 402, 403),
+ (440, 403, 404),
+ (441, 404, 405),
+ (443, 406, 407),
+ (444, 407, 316),
+ (445, 316, 321),
+ (446, 321, 323),
+ (447, 323, 408),
+ (448, 408, 409),
+ (449, 409, 410),
+ (450, 410, 411),
+ (451, 411, 411),
+ (452, 411, 412),
+ (453, 412, 394),
+ (455, 413, 414),
+ (457, 415, 414),
+ (459, 416, 417),
+ (460, 417, 418),
+ (462, 419, 420),
+ (463, 420, 421),
+ (464, 421, 116),
+ (465, 116, 422),
+ (466, 422, 423),
+ (467, 423, 424),
+ (469, 417, 422),
+ (471, 425, 426),
+ (473, 124, 427),
+ (474, 427, 428),
+ (476, 425, 428),
+ (477, 428, 416),
+ (478, 416, 121),
+ (479, 121, 429),
+ (481, 430, 401),
+ (483, 431, 432),
+ (484, 432, 433),
+ (485, 433, 434),
+ (486, 434, 291),
+ (487, 291, 435),
+ (488, 435, 436),
+ (489, 436, 437),
+ (490, 437, 431),
+ (492, 129, 332),
+ (493, 332, 438),
+ (494, 438, 70),
+ (495, 70, 437),
+ (497, 429, 427),
+ (499, 418, 120),
+ (500, 120, 439),
+ (501, 439, 420),
+ (502, 420, 440),
+ (503, 440, 441),
+ (504, 441, 442),
+ (505, 442, 328),
+ (507, 327, 443),
+ (509, 444, 419),
+ (510, 419, 440),
+ (512, 445, 446),
+ (513, 446, 441),
+ (514, 441, 447),
+ (515, 447, 114),
+ (517, 442, 448),
+ (518, 448, 46),
+ (520, 443, 449),
+ (522, 449, 450),
+ (524, 450, 451),
+ (526, 451, 452),
+ (528, 452, 444),
+ (529, 444, 399),
+ (531, 76, 453),
+ (532, 441, 452),
+ (534, 454, 455),
+ (535, 455, 456),
+ (536, 456, 457),
+ (537, 457, 458),
+ (538, 458, 459),
+ (539, 459, 460),
+ (540, 460, 461),
+ (541, 461, 462),
+ (543, 463, 464),
+ (545, 465, 464),
+ (547, 463, 465),
+ (548, 465, 464),
+ (549, 464, 466),
+ (551, 467, 468),
+ (552, 468, 469),
+ (554, 470, 471),
+ (555, 471, 472),
+ (556, 472, 473),
+ (557, 473, 474),
+ (558, 474, 475),
+ (592, 90, 502),
+ (559, 475, 476),
+ (560, 477, 236),
+ (561, 236, 478),
+ (563, 479, 480),
+ (564, 480, 481),
+ (566, 482, 483),
+ (567, 483, 297),
+ (613, 484, 485),
+ (614, 485, 105),
+ (615, 105, 391),
+ (682, 486, 487),
+ (568, 297, 488),
+ (569, 145, 489),
+ (571, 270, 268),
+ (573, 490, 138),
+ (575, 140, 491),
+ (576, 491, 263),
+ (578, 492, 493),
+ (579, 493, 494),
+ (580, 494, 495),
+ (581, 349, 496),
+ (583, 497, 498),
+ (584, 498, 92),
+ (586, 494, 499),
+ (587, 499, 466),
+ (589, 500, 501),
+ (590, 501, 94),
+ (593, 502, 503),
+ (594, 503, 504),
+ (596, 366, 505),
+ (597, 505, 506),
+ (598, 506, 507),
+ (599, 507, 504),
+ (600, 504, 91),
+ (602, 508, 509),
+ (603, 509, 510),
+ (604, 510, 333),
+ (606, 511, 512),
+ (607, 512, 511),
+ (609, 511, 513),
+ (610, 513, 101),
+ (612, 75, 484),
+ (617, 466, 514),
+ (619, 463, 515),
+ (620, 515, 516),
+ (621, 516, 517),
+ (623, 518, 93),
+ (625, 519, 520),
+ (626, 520, 521),
+ (627, 521, 74),
+ (629, 522, 521),
+ (631, 523, 520),
+ (633, 524, 52),
+ (637, 57, 525),
+ (638, 525, 526),
+ (640, 56, 525),
+ (642, 527, 528),
+ (644, 527, 529),
+ (645, 529, 530),
+ (647, 524, 529),
+ (649, 59, 531),
+ (651, 532, 533),
+ (652, 533, 531),
+ (653, 531, 60),
+ (655, 533, 512),
+ (657, 511, 534),
+ (658, 534, 99),
+ (660, 535, 95),
+ (662, 536, 537),
+ (663, 537, 538),
+ (664, 538, 539),
+ (665, 539, 540),
+ (667, 53, 530),
+ (669, 45, 540),
+ (671, 541, 43),
+ (673, 329, 326),
+ (675, 96, 542),
+ (676, 542, 543),
+ (677, 543, 544),
+ (678, 544, 545),
+ (679, 545, 546),
+ (680, 546, 547),
+ (681, 547, 486),
+ (683, 487, 548),
+ (684, 548, 549),
+ (685, 549, 550),
+ (686, 550, 551),
+ (687, 551, 552),
+ (688, 552, 553),
+ (689, 553, 554),
+ (691, 555, 543),
+ (693, 556, 544),
+ (695, 557, 545),
+ (697, 558, 546),
+ (699, 559, 560),
+ (701, 561, 562),
+ (702, 562, 560),
+ (704, 563, 564),
+ (705, 564, 37),
+ (707, 565, 564),
+ (709, 566, 386),
+ (711, 423, 566),
+ (713, 567, 79),
+ (715, 568, 569),
+ (716, 569, 65),
+ (718, 67, 570),
+ (719, 570, 571),
+ (721, 459, 572),
+ (722, 572, 573),
+ (723, 573, 462),
+ (725, 574, 573),
+ (727, 575, 434),
+ (729, 576, 577),
+ (730, 577, 578),
+ (731, 578, 579),
+ (732, 579, 580),
+ (733, 580, 581),
+ (734, 581, 582),
+ (735, 582, 312),
+ (736, 312, 583),
+ (737, 583, 584),
+ (738, 584, 585),
+ (739, 585, 407),
+ (740, 407, 586),
+ (741, 586, 587),
+ (742, 587, 588),
+ (743, 588, 589),
+ (744, 589, 590),
+ (745, 590, 591),
+ (746, 591, 592),
+ (747, 592, 593),
+ (748, 593, 594),
+ (749, 594, 308),
+ (750, 308, 309),
+ (751, 309, 595),
+ (752, 595, 596),
+ (753, 596, 597),
+ (754, 597, 304),
+ (755, 304, 496),
+ (756, 496, 598),
+ (855, 599, 293),
+ (757, 598, 600),
+ (758, 600, 404),
+ (759, 404, 601),
+ (760, 601, 125),
+ (762, 602, 503),
+ (764, 603, 520),
+ (766, 604, 605),
+ (767, 605, 606),
+ (768, 606, 607),
+ (769, 607, 454),
+ (770, 454, 571),
+ (771, 571, 604),
+ (773, 606, 433),
+ (775, 608, 609),
+ (776, 609, 458),
+ (777, 458, 610),
+ (779, 611, 144),
+ (781, 612, 145),
+ (782, 145, 477),
+ (783, 477, 469),
+ (784, 469, 481),
+ (785, 481, 611),
+ (786, 611, 612),
+ (788, 613, 489),
+ (789, 489, 470),
+ (790, 470, 482),
+ (791, 482, 478),
+ (792, 478, 613),
+ (794, 614, 615),
+ (796, 616, 617),
+ (797, 617, 618),
+ (798, 618, 11),
+ (799, 11, 619),
+ (800, 619, 620),
+ (801, 620, 621),
+ (802, 621, 622),
+ (803, 622, 413),
+ (805, 623, 624),
+ (807, 623, 625),
+ (809, 626, 627),
+ (810, 627, 624),
+ (811, 624, 628),
+ (813, 629, 630),
+ (814, 630, 173),
+ (816, 623, 631),
+ (817, 631, 632),
+ (818, 632, 633),
+ (819, 633, 634),
+ (820, 635, 636),
+ (822, 626, 635),
+ (824, 637, 3),
+ (825, 3, 638),
+ (826, 638, 639),
+ (828, 627, 640),
+ (830, 639, 633),
+ (832, 641, 642),
+ (833, 642, 643),
+ (835, 2, 637),
+ (837, 644, 645),
+ (838, 645, 639),
+ (839, 639, 641),
+ (841, 646, 647),
+ (842, 647, 132),
+ (844, 131, 648),
+ (846, 649, 650),
+ (847, 650, 651),
+ (848, 651, 652),
+ (849, 652, 616),
+ (851, 649, 653),
+ (852, 653, 6),
+ (854, 653, 599),
+ (856, 293, 654),
+ (857, 654, 655),
+ (858, 655, 656),
+ (859, 656, 657),
+ (860, 657, 156),
+ (862, 155, 658),
+ (863, 658, 659),
+ (864, 659, 660),
+ (866, 656, 661),
+ (867, 661, 662),
+ (868, 662, 617),
+ (870, 663, 658),
+ (871, 658, 664),
+ (872, 664, 652),
+ (874, 153, 663),
+ (876, 158, 154),
+ (878, 31, 13),
+ (880, 14, 665),
+ (882, 666, 621),
+ (884, 667, 666),
+ (886, 29, 667),
+ (888, 668, 5),
+ (890, 152, 659),
+ (892, 669, 670),
+ (893, 670, 671),
+ (894, 672, 233),
+ (896, 670, 245),
+ (898, 673, 674),
+ (899, 674, 675),
+ (901, 676, 273),
+ (982, 734, 735),
+ (902, 273, 238),
+ (904, 240, 673),
+ (905, 673, 675),
+ (906, 675, 677),
+ (907, 217, 678),
+ (952, 633, 679),
+ (908, 678, 680),
+ (909, 680, 681),
+ (910, 681, 682),
+ (911, 682, 683),
+ (912, 683, 684),
+ (913, 685, 686),
+ (914, 686, 687),
+ (915, 687, 688),
+ (916, 688, 689),
+ (917, 689, 690),
+ (918, 690, 691),
+ (919, 691, 692),
+ (920, 692, 693),
+ (921, 693, 694),
+ (923, 230, 695),
+ (924, 645, 696),
+ (925, 214, 697),
+ (926, 698, 699),
+ (927, 700, 701),
+ (929, 300, 702),
+ (931, 703, 704),
+ (933, 705, 565),
+ (934, 565, 706),
+ (935, 706, 306),
+ (937, 707, 678),
+ (939, 708, 709),
+ (940, 709, 710),
+ (941, 710, 711),
+ (942, 711, 712),
+ (1025, 773, 774),
+ (943, 712, 713),
+ (944, 713, 714),
+ (945, 714, 715),
+ (947, 716, 698),
+ (948, 698, 717),
+ (949, 313, 718),
+ (950, 718, 706),
+ (953, 679, 719),
+ (954, 719, 720),
+ (955, 720, 721),
+ (956, 721, 722),
+ (958, 723, 724),
+ (959, 724, 725),
+ (960, 725, 726),
+ (962, 727, 703),
+ (963, 703, 679),
+ (964, 679, 722),
+ (966, 483, 728),
+ (967, 621, 729),
+ (968, 729, 15),
+ (970, 730, 731),
+ (971, 731, 732),
+ (972, 622, 733),
+ (973, 734, 735),
+ (974, 735, 736),
+ (975, 736, 737),
+ (976, 737, 731),
+ (978, 730, 738),
+ (979, 738, 739),
+ (980, 739, 740),
+ (981, 740, 734),
+ (984, 741, 738),
+ (986, 742, 743),
+ (987, 743, 744),
+ (988, 744, 745),
+ (989, 745, 143),
+ (991, 746, 747),
+ (992, 747, 748),
+ (993, 748, 749),
+ (994, 749, 260),
+ (996, 750, 751),
+ (997, 751, 752),
+ (999, 725, 743),
+ (1000, 743, 753),
+ (1001, 754, 755),
+ (1002, 755, 756),
+ (1003, 756, 757),
+ (1004, 757, 758),
+ (1006, 759, 760),
+ (1007, 760, 761),
+ (1008, 761, 762),
+ (1010, 763, 758),
+ (1011, 758, 762),
+ (1012, 762, 764),
+ (1013, 764, 141),
+ (1015, 765, 766),
+ (1017, 767, 768),
+ (1018, 768, 769),
+ (1019, 769, 770),
+ (1020, 770, 142),
+ (1022, 771, 757),
+ (1024, 772, 773),
+ (1027, 744, 767),
+ (1028, 767, 763),
+ (1029, 763, 771),
+ (1030, 771, 765),
+ (1032, 775, 750),
+ (1033, 750, 776),
+ (1035, 724, 777),
+ (1036, 778, 779),
+ (1037, 779, 780),
+ (1039, 769, 781),
+ (1040, 779, 775),
+ (1041, 775, 782),
+ (1042, 783, 751),
+ (1044, 756, 784),
+ (1045, 755, 785),
+ (1046, 749, 786),
+ (1047, 786, 787),
+ (1049, 768, 745),
+ (1051, 770, 760),
+ (1052, 760, 788),
+ (1053, 788, 789),
+ (1055, 762, 790),
+ (1056, 790, 746),
+ (1057, 746, 263),
+ (1059, 748, 787),
+ (1060, 787, 776),
+ (1061, 776, 780),
+ (1062, 780, 754),
+ (1063, 754, 747),
+ (1065, 290, 791),
+ (1066, 674, 792),
+ (1067, 139, 793),
+ (1069, 794, 795),
+ (1111, 817, 830),
+ (1070, 795, 796),
+ (1071, 796, 737),
+ (1073, 789, 761),
+ (1075, 797, 798),
+ (1076, 264, 799),
+ (1077, 773, 800),
+ (1078, 801, 802),
+ (1079, 795, 803),
+ (1080, 804, 805),
+ (1081, 719, 806),
+ (1082, 720, 807),
+ (1083, 721, 808),
+ (1084, 808, 704),
+ (1086, 809, 808),
+ (1088, 810, 150),
+ (1090, 165, 811),
+ (1091, 811, 812),
+ (1092, 812, 813),
+ (1093, 814, 815),
+ (1094, 816, 817),
+ (1096, 818, 819),
+ (1097, 819, 820),
+ (1099, 821, 822),
+ (1101, 823, 824),
+ (1103, 825, 819),
+ (1105, 826, 827),
+ (1106, 811, 168),
+ (1108, 828, 30),
+ (1110, 829, 817),
+ (1112, 831, 828),
+ (1114, 177, 176),
+ (1116, 793, 797),
+ (1117, 797, 793),
+ (1121, 832, 528),
+ (1122, 528, 526),
+ (1123, 526, 54),
+ (1125, 833, 821),
+ (1126, 821, 822),
+ (1127, 822, 833),
+ (1129, 834, 823),
+ (1130, 823, 835),
+ (1131, 835, 834),
+ (1133, 383, 836),
+ (1134, 836, 837),
+ (1135, 837, 561),
+ (1136, 561, 554),
+ (1137, 554, 383),
+ (1139, 295, 838),
+ (1141, 299, 716),
+ (1142, 716, 623),
+ (1144, 295, 839),
+ (1456, 840, 841),
+ (1146, 625, 636),
+ (1147, 636, 668),
+ (1149, 842, 825),
+ (1150, 825, 820),
+ (1151, 820, 843),
+ (1152, 843, 844),
+ (1153, 844, 816),
+ (1237, 878, 646),
+ (1154, 816, 845),
+ (1155, 845, 846),
+ (1156, 846, 629),
+ (1157, 629, 847),
+ (1158, 847, 848),
+ (1159, 848, 849),
+ (1160, 849, 850),
+ (1161, 850, 628),
+ (1162, 628, 851),
+ (1163, 839, 847),
+ (1165, 838, 173),
+ (1167, 852, 853),
+ (1168, 853, 854),
+ (1169, 855, 415),
+ (1171, 796, 856),
+ (1172, 856, 857),
+ (1173, 857, 737),
+ (1175, 736, 857),
+ (1176, 857, 856),
+ (1178, 620, 858),
+ (1179, 858, 665),
+ (1180, 665, 12),
+ (1181, 12, 32),
+ (1182, 32, 859),
+ (1183, 859, 660),
+ (1184, 660, 664),
+ (1185, 664, 657),
+ (1186, 657, 157),
+ (1187, 157, 860),
+ (1188, 860, 861),
+ (1189, 861, 646),
+ (1190, 646, 648),
+ (1191, 648, 862),
+ (1192, 862, 294),
+ (1194, 863, 855),
+ (1195, 855, 413),
+ (1197, 413, 415),
+ (1198, 415, 863),
+ (1200, 144, 801),
+ (1201, 801, 766),
+ (1202, 766, 864),
+ (1203, 864, 752),
+ (1204, 752, 865),
+ (1205, 865, 866),
+ (1206, 866, 867),
+ (1260, 493, 868),
+ (1262, 869, 185),
+ (1263, 185, 826),
+ (1207, 867, 870),
+ (1208, 788, 871),
+ (1209, 764, 872),
+ (1210, 873, 874),
+ (1212, 790, 491),
+ (1213, 491, 267),
+ (1215, 875, 750),
+ (1217, 786, 874),
+ (1218, 874, 875),
+ (1219, 875, 876),
+ (1220, 876, 866),
+ (1222, 865, 876),
+ (1223, 876, 873),
+ (1224, 873, 867),
+ (1226, 618, 859),
+ (1228, 868, 730),
+ (1230, 730, 619),
+ (1231, 619, 858),
+ (1233, 835, 877),
+ (1234, 29, 828),
+ (1236, 647, 878),
+ (1239, 599, 435),
+ (1241, 860, 651),
+ (1242, 651, 879),
+ (1243, 879, 599),
+ (1245, 880, 881),
+ (1246, 514, 517),
+ (1247, 517, 462),
+ (1249, 861, 650),
+ (1250, 650, 879),
+ (1251, 879, 293),
+ (1253, 730, 742),
+ (1254, 742, 726),
+ (1256, 868, 492),
+ (1257, 492, 514),
+ (1259, 514, 493),
+ (1264, 826, 882),
+ (1265, 882, 883),
+ (1266, 878, 880),
+ (1268, 499, 884),
+ (1269, 884, 885),
+ (1270, 885, 460),
+ (1272, 516, 460),
+ (1274, 743, 886),
+ (1275, 729, 887),
+ (1276, 739, 740),
+ (1278, 515, 888),
+ (1279, 432, 605),
+ (1281, 577, 774),
+ (1283, 889, 890),
+ (1284, 890, 891),
+ (1285, 891, 892),
+ (1286, 892, 562),
+ (1287, 562, 893),
+ (1288, 378, 894),
+ (1289, 837, 892),
+ (1291, 836, 891),
+ (1293, 890, 895),
+ (1295, 489, 576),
+ (1297, 896, 470),
+ (1299, 502, 505),
+ (1301, 470, 472),
+ (1303, 506, 889),
+ (1304, 889, 895),
+ (1305, 895, 382),
+ (1307, 480, 804),
+ (1308, 804, 897),
+ (1309, 258, 478),
+ (1311, 482, 258),
+ (1313, 864, 778),
+ (1314, 778, 765),
+ (1539, 898, 899),
+ (1316, 900, 901),
+ (1317, 902, 903),
+ (1318, 248, 904),
+ (1319, 234, 905),
+ (1320, 174, 303),
+ (1321, 303, 814),
+ (1322, 814, 175),
+ (1323, 175, 906),
+ (1325, 846, 907),
+ (1326, 845, 133),
+ (1328, 906, 908),
+ (1329, 843, 183),
+ (1330, 183, 829),
+ (1332, 130, 909),
+ (1334, 829, 184),
+ (1335, 184, 844),
+ (1337, 850, 849),
+ (1339, 910, 911),
+ (1341, 912, 906),
+ (1343, 911, 913),
+ (1345, 174, 914),
+ (1347, 911, 848),
+ (1349, 630, 302),
+ (1351, 862, 909),
+ (1352, 909, 131),
+ (1354, 299, 910),
+ (1355, 910, 913),
+ (1356, 913, 914),
+ (1357, 914, 173),
+ (1359, 615, 632),
+ (1361, 812, 133),
+ (1363, 643, 615),
+ (1365, 638, 631),
+ (1366, 631, 915),
+ (1368, 643, 916),
+ (1370, 702, 916),
+ (1372, 916, 702),
+ (1374, 915, 642),
+ (1376, 917, 583),
+ (1377, 583, 853),
+ (1378, 853, 314),
+ (1379, 314, 918),
+ (1380, 918, 919),
+ (1381, 919, 33),
+ (1383, 397, 920),
+ (1384, 920, 341),
+ (1386, 921, 922),
+ (1387, 922, 923),
+ (1388, 923, 350),
+ (1390, 922, 924),
+ (1391, 924, 396),
+ (1393, 925, 921),
+ (1394, 921, 926),
+ (1395, 926, 927),
+ (1397, 928, 929),
+ (1455, 947, 840),
+ (1398, 929, 930),
+ (1399, 930, 923),
+ (1401, 930, 931),
+ (1402, 929, 347),
+ (1404, 932, 933),
+ (1405, 933, 926),
+ (1407, 409, 934),
+ (1408, 934, 935),
+ (1410, 936, 928),
+ (1411, 928, 932),
+ (1413, 932, 927),
+ (1414, 927, 937),
+ (1416, 937, 938),
+ (1418, 939, 935),
+ (1419, 935, 940),
+ (1420, 940, 938),
+ (1422, 348, 936),
+ (1424, 933, 921),
+ (1426, 510, 941),
+ (1427, 941, 942),
+ (1429, 941, 509),
+ (1431, 943, 852),
+ (1432, 852, 944),
+ (1433, 944, 584),
+ (1434, 584, 945),
+ (1435, 945, 946),
+ (1439, 947, 948),
+ (1440, 948, 39),
+ (1442, 949, 948),
+ (1443, 948, 40),
+ (1445, 841, 72),
+ (1447, 840, 72),
+ (1449, 950, 71),
+ (1451, 951, 952),
+ (1453, 953, 950),
+ (1454, 950, 947),
+ (1457, 841, 954),
+ (1458, 955, 956),
+ (1459, 956, 402),
+ (1461, 957, 958),
+ (1463, 958, 400),
+ (1465, 957, 959),
+ (1466, 959, 121),
+ (1468, 960, 952),
+ (1470, 335, 961),
+ (1471, 962, 87),
+ (1473, 963, 368),
+ (1475, 559, 553),
+ (1476, 553, 964),
+ (1477, 381, 552),
+ (1479, 552, 965),
+ (1481, 551, 966),
+ (1482, 966, 967),
+ (1483, 967, 968),
+ (1484, 968, 380),
+ (1486, 551, 969),
+ (1541, 898, 970),
+ (1487, 969, 486),
+ (1489, 969, 487),
+ (1491, 559, 971),
+ (1492, 966, 965),
+ (1494, 972, 967),
+ (1495, 967, 973),
+ (1496, 973, 974),
+ (1497, 974, 550),
+ (1499, 974, 973),
+ (1500, 973, 968),
+ (1502, 549, 975),
+ (1503, 975, 378),
+ (1505, 548, 976),
+ (1506, 975, 977),
+ (1507, 978, 379),
+ (1509, 507, 979),
+ (1510, 542, 980),
+ (1511, 981, 982),
+ (1513, 112, 983),
+ (1514, 984, 985),
+ (1515, 985, 398),
+ (1517, 940, 411),
+ (1518, 411, 411),
+ (1520, 986, 587),
+ (1521, 587, 987),
+ (1523, 885, 988),
+ (1524, 989, 990),
+ (1525, 990, 991),
+ (1526, 990, 992),
+ (1527, 990, 993),
+ (1528, 994, 990),
+ (1530, 990, 995),
+ (1531, 996, 709),
+ (1532, 709, 997),
+ (1533, 998, 898),
+ (1534, 898, 899),
+ (1535, 899, 970),
+ (1536, 970, 999),
+ (1537, 999, 898),
+ (1543, 898, 999),
+ (1545, 334, 1000),
+ (1546, 69, 1001),
+ (1547, 1001, 1002),
+ (1548, 1003, 1004),
+ (1550, 1005, 1006),
+ (1552, 337, 1007),
+ (1553, 69, 1008),
+ (1554, 570, 1009),
+ (1555, 1009, 1010),
+ (1556, 1011, 1012),
+ (1557, 884, 772),
+ (1559, 1013, 1014),
+ (1613, 508, 129),
+ (1560, 1014, 1015),
+ (1562, 1016, 1014),
+ (1564, 1017, 1018),
+ (1565, 581, 1019),
+ (1566, 582, 1020),
+ (1567, 78, 1021),
+ (1568, 536, 1022),
+ (1569, 1022, 73),
+ (1571, 44, 539),
+ (1573, 537, 1023),
+ (1574, 538, 1024),
+ (1575, 317, 1025),
+ (1576, 317, 1026),
+ (1577, 319, 1027),
+ (1578, 318, 944),
+ (1580, 718, 1028),
+ (1581, 126, 1029),
+ (1582, 1029, 1030),
+ (1583, 1030, 405),
+ (1584, 405, 1031),
+ (1585, 1031, 1032),
+ (1586, 1032, 1033),
+ (1588, 403, 430),
+ (1589, 430, 1034),
+ (1590, 1034, 123),
+ (1592, 1032, 1035),
+ (1593, 1035, 1036),
+ (1595, 1035, 1037),
+ (1597, 1038, 405),
+ (1599, 1039, 1030),
+ (1601, 598, 1040),
+ (1602, 1036, 1041),
+ (1604, 1042, 1043),
+ (1606, 1042, 1044),
+ (1607, 1043, 1045),
+ (1608, 1046, 1047),
+ (1610, 1046, 1048),
+ (1611, 1047, 1049),
+ (1612, 128, 508),
+ (1615, 127, 426),
+ (1617, 215, 222),
+ (1619, 223, 707),
+ (1621, 707, 224),
+ (1623, 224, 216),
+ (1625, 216, 225),
+ (1627, 226, 211),
+ (1629, 211, 220),
+ (1631, 215, 221),
+ (1633, 640, 644),
+ (1635, 49, 390),
+ (1636, 390, 1050),
+ (1637, 1050, 1051),
+ (1638, 438, 1001),
+ (1639, 1001, 569),
+ (1640, 569, 104),
+ (1641, 104, 1052),
+ (1642, 1052, 338),
+ (1643, 338, 388),
+ (1644, 388, 384),
+ (1645, 384, 982),
+ (1646, 982, 1053),
+ (1647, 1053, 389),
+ (1648, 389, 107),
+ (1649, 107, 1054),
+ (1650, 1054, 448),
+ (1651, 448, 330),
+ (1652, 330, 325),
+ (1653, 325, 393),
+ (1654, 393, 1055),
+ (1655, 1055, 943),
+ (1657, 436, 1056),
+ (1658, 1056, 1029),
+ (1659, 1029, 601),
+ (1660, 601, 1057),
+ (1661, 1057, 1034),
+ (1662, 1034, 959),
+ (1663, 959, 439),
+ (1664, 439, 421),
+ (1665, 421, 447),
+ (1666, 447, 446),
+ (1667, 446, 1054),
+ (1668, 1054, 47),
+ (1669, 47, 485),
+ (1671, 604, 1009),
+ (1672, 1009, 68),
+ (1674, 1031, 600),
+ (1675, 600, 956),
+ (1676, 956, 985),
+ (1677, 985, 340),
+ (1678, 340, 920),
+ (1679, 920, 351),
+ (1680, 351, 924),
+ (1681, 924, 1058),
+ (1682, 1058, 412),
+ (1683, 412, 1055),
+ (1684, 1055, 35),
+ (1686, 1059, 579),
+ (1687, 579, 1060),
+ (1688, 1060, 81),
+ (1690, 82, 1061),
+ (1691, 1061, 1062),
+ (1692, 1062, 484),
+ (1693, 484, 1022),
+ (1694, 1022, 42),
+ (1696, 392, 371),
+ (1697, 371, 1063),
+ (1698, 1063, 1061),
+ (1699, 1061, 80),
+ (1700, 80, 580),
+ (1701, 580, 1064),
+ (1703, 89, 1065),
+ (1704, 1065, 51),
+ (1705, 51, 1053),
+ (1707, 1052, 61),
+ (1708, 61, 513),
+ (1709, 513, 534),
+ (1710, 534, 501),
+ (1711, 501, 498),
+ (1712, 498, 1065),
+ (1713, 1065, 392),
+ (1715, 461, 572),
+ (1716, 572, 610),
+ (1717, 610, 1066),
+ (1718, 1066, 1067),
+ (1719, 1067, 1068),
+ (1720, 1068, 607),
+ (1722, 711, 1069),
+ (1723, 1069, 1070),
+ (1724, 1070, 701),
+ (1725, 701, 1071),
+ (1726, 1071, 694),
+ (1727, 694, 609),
+ (1728, 609, 1072),
+ (1729, 1072, 456),
+ (1730, 456, 1067),
+ (1772, 1073, 946),
+ (1732, 715, 1074),
+ (1733, 1074, 1075),
+ (1734, 1075, 1076),
+ (1735, 1076, 710),
+ (1737, 1068, 455),
+ (1738, 455, 1077),
+ (1739, 1077, 608),
+ (1740, 608, 693),
+ (1741, 693, 1078),
+ (1742, 1078, 712),
+ (1743, 712, 1076),
+ (1744, 1076, 1079),
+ (1745, 1079, 1080),
+ (1746, 1080, 1081),
+ (1747, 1081, 1082),
+ (1748, 1066, 457),
+ (1749, 457, 1072),
+ (1750, 1072, 1077),
+ (1752, 1083, 1075),
+ (1753, 1075, 713),
+ (1755, 714, 1074),
+ (1756, 1074, 1084),
+ (1757, 1071, 1078),
+ (1759, 1078, 1070),
+ (1760, 1070, 700),
+ (1762, 1033, 1085),
+ (1763, 1085, 310),
+ (1764, 310, 307),
+ (1765, 307, 1086),
+ (1766, 1086, 1087),
+ (1767, 1087, 986),
+ (1768, 986, 1088),
+ (1769, 1088, 1089),
+ (1770, 1089, 406),
+ (1771, 406, 1073),
+ (1773, 946, 917),
+ (1774, 917, 1090),
+ (1775, 1090, 1091),
+ (1776, 1091, 1092),
+ (1777, 1092, 1093),
+ (1778, 1093, 1094),
+ (1779, 1094, 1064),
+ (1780, 1064, 1059),
+ (1781, 1059, 1095),
+ (1782, 1095, 1096),
+ (1783, 1096, 896),
+ (1785, 395, 1058),
+ (1786, 1058, 1097),
+ (1787, 1097, 934),
+ (1788, 934, 1098),
+ (1789, 1098, 1099),
+ (1790, 1099, 320),
+ (1791, 320, 586),
+ (1792, 586, 1089),
+ (1794, 987, 588),
+ (1795, 588, 1087),
+ (1797, 1063, 85),
+ (1798, 85, 1100),
+ (1799, 1100, 353),
+ (1801, 1050, 106),
+ (1803, 1062, 1101),
+ (1804, 370, 1100),
+ (1805, 1100, 1102),
+ (1807, 1102, 1103);
+
+create table e03.calles(
+ gido integer,
+ salida integer,
+ destino integer
+);
+
+insert into e03.calles values
+ (1, 1, 2),
+ (2, 2, 3),
+ (3, 3, 4),
+ (4, 4, 5),
+ (5, 5, 6),
+ (7, 7, 8),
+ (8, 9, 10),
+ (9, 11, 12),
+ (10, 12, 13),
+ (11, 13, 14),
+ (12, 14, 15),
+ (13, 15, 16),
+ (15, 17, 18),
+ (16, 18, 19),
+ (17, 19, 20),
+ (18, 20, 21),
+ (19, 21, 22),
+ (20, 22, 23),
+ (21, 23, 24),
+ (22, 24, 25),
+ (23, 25, 26),
+ (24, 26, 27),
+ (25, 27, 28),
+ (26, 28, 29),
+ (27, 29, 30),
+ (28, 30, 31),
+ (29, 31, 32),
+ (31, 33, 34),
+ (32, 34, 35),
+ (33, 35, 36),
+ (34, 36, 37),
+ (35, 37, 38),
+ (36, 38, 39),
+ (37, 39, 40),
+ (38, 40, 41),
+ (39, 41, 42),
+ (40, 42, 43),
+ (41, 43, 44),
+ (42, 44, 45),
+ (43, 45, 46),
+ (44, 46, 47),
+ (45, 47, 48),
+ (46, 48, 49),
+ (47, 49, 50),
+ (48, 50, 51),
+ (49, 51, 52),
+ (50, 52, 53),
+ (51, 53, 54),
+ (52, 54, 55),
+ (53, 55, 56),
+ (54, 56, 57),
+ (55, 57, 58),
+ (56, 58, 59),
+ (57, 59, 60),
+ (58, 60, 61),
+ (59, 61, 62),
+ (60, 62, 63),
+ (61, 63, 64),
+ (62, 64, 65),
+ (63, 65, 66),
+ (64, 66, 67),
+ (65, 67, 68),
+ (66, 68, 69),
+ (67, 69, 70),
+ (69, 41, 71),
+ (70, 71, 72),
+ (71, 72, 73),
+ (72, 73, 74),
+ (73, 74, 75),
+ (74, 75, 76),
+ (75, 76, 77),
+ (76, 77, 78),
+ (77, 78, 79),
+ (78, 79, 80),
+ (79, 80, 81),
+ (80, 81, 82),
+ (81, 82, 83),
+ (82, 83, 84),
+ (83, 84, 85),
+ (84, 85, 86),
+ (85, 86, 87),
+ (86, 87, 88),
+ (87, 88, 89),
+ (88, 89, 90),
+ (89, 90, 91),
+ (90, 91, 92),
+ (91, 92, 93),
+ (92, 93, 94),
+ (93, 94, 95),
+ (94, 95, 96),
+ (95, 96, 97),
+ (96, 97, 98),
+ (97, 98, 99),
+ (98, 99, 100),
+ (99, 100, 101),
+ (100, 101, 102),
+ (101, 102, 103),
+ (102, 103, 62),
+ (103, 62, 104),
+ (105, 105, 106),
+ (106, 106, 48),
+ (107, 48, 107),
+ (108, 107, 108),
+ (109, 108, 109),
+ (110, 109, 110),
+ (111, 110, 111),
+ (112, 111, 112),
+ (113, 112, 113),
+ (114, 113, 114),
+ (115, 114, 115),
+ (116, 115, 116),
+ (117, 116, 117),
+ (118, 117, 118),
+ (119, 118, 119),
+ (120, 119, 120),
+ (121, 120, 121),
+ (122, 121, 122),
+ (124, 122, 123),
+ (125, 123, 124),
+ (126, 124, 125),
+ (127, 125, 126),
+ (128, 126, 127),
+ (129, 127, 128),
+ (130, 128, 129),
+ (132, 6, 130),
+ (133, 130, 131),
+ (134, 131, 132),
+ (135, 132, 133),
+ (136, 133, 134),
+ (137, 134, 135),
+ (138, 135, 136),
+ (139, 137, 138),
+ (140, 138, 139),
+ (141, 139, 140),
+ (142, 140, 141),
+ (143, 141, 142),
+ (144, 142, 143),
+ (146, 144, 145),
+ (148, 146, 147),
+ (149, 147, 148),
+ (150, 148, 149),
+ (151, 149, 150),
+ (152, 150, 151),
+ (153, 151, 152),
+ (154, 152, 153),
+ (155, 153, 154),
+ (156, 154, 155),
+ (157, 155, 156),
+ (159, 157, 158),
+ (160, 158, 159),
+ (162, 160, 161),
+ (163, 161, 162),
+ (164, 162, 163),
+ (165, 163, 164),
+ (166, 164, 165),
+ (167, 165, 166),
+ (168, 166, 167),
+ (169, 167, 168),
+ (170, 168, 169),
+ (171, 169, 170),
+ (172, 170, 171),
+ (173, 171, 172),
+ (174, 172, 159),
+ (176, 173, 174),
+ (178, 175, 176),
+ (179, 176, 177),
+ (180, 177, 178),
+ (181, 178, 179),
+ (182, 179, 180),
+ (183, 181, 178),
+ (184, 178, 182),
+ (185, 179, 183),
+ (186, 183, 184),
+ (188, 151, 185),
+ (190, 186, 187),
+ (191, 188, 189),
+ (192, 189, 190),
+ (193, 190, 191),
+ (194, 191, 192),
+ (195, 192, 193),
+ (196, 193, 194),
+ (197, 194, 195),
+ (198, 196, 197),
+ (199, 197, 198),
+ (200, 198, 199),
+ (202, 200, 201),
+ (203, 201, 197),
+ (204, 197, 202),
+ (205, 202, 203),
+ (206, 203, 204),
+ (207, 204, 205),
+ (209, 204, 199),
+ (211, 206, 207),
+ (212, 207, 208),
+ (213, 207, 209),
+ (214, 210, 211),
+ (216, 212, 213),
+ (217, 213, 214),
+ (218, 214, 215),
+ (220, 216, 217),
+ (221, 217, 218),
+ (223, 219, 220),
+ (224, 220, 221),
+ (225, 221, 222),
+ (226, 222, 223),
+ (227, 223, 224),
+ (228, 224, 225),
+ (229, 225, 226),
+ (230, 226, 219),
+ (232, 213, 227),
+ (234, 228, 229),
+ (235, 229, 227),
+ (236, 227, 230),
+ (237, 230, 231),
+ (239, 232, 233),
+ (240, 233, 234),
+ (241, 234, 235),
+ (243, 236, 237),
+ (244, 237, 238),
+ (245, 238, 239),
+ (246, 239, 240),
+ (247, 240, 241),
+ (248, 241, 242),
+ (249, 242, 243),
+ (250, 243, 244),
+ (251, 244, 245),
+ (252, 245, 246),
+ (253, 246, 247),
+ (254, 247, 248),
+ (255, 248, 249),
+ (256, 249, 250),
+ (257, 250, 251),
+ (258, 251, 252),
+ (259, 252, 253),
+ (260, 253, 254),
+ (261, 254, 255),
+ (262, 255, 256),
+ (263, 256, 257),
+ (265, 237, 235),
+ (266, 235, 258),
+ (268, 259, 260),
+ (269, 260, 261),
+ (270, 262, 263),
+ (272, 259, 263),
+ (274, 263, 264),
+ (275, 264, 265),
+ (276, 265, 266),
+ (277, 266, 267),
+ (278, 267, 268),
+ (280, 265, 269),
+ (281, 269, 270),
+ (282, 270, 271),
+ (283, 269, 266),
+ (285, 272, 218),
+ (286, 218, 231),
+ (287, 231, 272),
+ (289, 273, 274),
+ (291, 275, 274),
+ (292, 274, 246),
+ (294, 276, 277),
+ (295, 278, 279),
+ (296, 279, 280),
+ (297, 280, 281),
+ (298, 281, 282),
+ (299, 282, 283),
+ (300, 283, 284),
+ (301, 284, 285),
+ (302, 285, 286),
+ (303, 286, 276),
+ (304, 276, 287),
+ (305, 288, 289),
+ (306, 289, 290),
+ (307, 290, 257),
+ (309, 291, 292),
+ (310, 292, 293),
+ (312, 294, 295),
+ (314, 296, 288),
+ (315, 288, 289),
+ (316, 289, 286),
+ (317, 286, 285),
+ (319, 297, 298),
+ (320, 299, 300),
+ (321, 300, 301),
+ (322, 302, 303),
+ (324, 304, 305),
+ (325, 77, 306),
+ (373, 347, 348),
+ (327, 3, 307),
+ (328, 307, 308),
+ (330, 309, 310),
+ (331, 310, 4),
+ (333, 311, 312),
+ (334, 312, 313),
+ (335, 313, 314),
+ (336, 314, 315),
+ (337, 316, 317),
+ (338, 317, 318),
+ (339, 318, 319),
+ (341, 320, 321),
+ (342, 321, 322),
+ (343, 322, 323),
+ (345, 322, 324),
+ (347, 38, 325),
+ (348, 325, 326),
+ (349, 326, 327),
+ (350, 327, 328),
+ (351, 328, 329),
+ (352, 329, 330),
+ (353, 330, 43),
+ (355, 115, 331),
+ (356, 332, 333),
+ (357, 333, 334),
+ (358, 334, 335),
+ (359, 335, 336),
+ (361, 335, 337),
+ (362, 337, 338),
+ (363, 338, 59),
+ (365, 339, 340),
+ (366, 340, 341),
+ (367, 341, 342),
+ (368, 342, 343),
+ (369, 343, 344),
+ (370, 344, 345),
+ (371, 345, 346),
+ (372, 346, 347),
+ (374, 348, 349),
+ (376, 346, 350),
+ (377, 350, 351),
+ (378, 351, 352),
+ (380, 353, 354),
+ (381, 354, 355),
+ (382, 355, 356),
+ (383, 356, 357),
+ (384, 357, 358),
+ (385, 358, 359),
+ (386, 359, 360),
+ (387, 360, 361),
+ (388, 361, 362),
+ (389, 362, 363),
+ (390, 363, 364),
+ (391, 364, 365),
+ (392, 365, 366),
+ (393, 366, 367),
+ (394, 367, 368),
+ (395, 368, 369),
+ (396, 369, 370),
+ (397, 370, 86),
+ (398, 86, 371),
+ (400, 354, 372),
+ (401, 372, 373),
+ (402, 373, 374),
+ (403, 374, 375),
+ (404, 375, 376),
+ (405, 376, 377),
+ (406, 377, 378),
+ (407, 378, 379),
+ (408, 379, 380),
+ (409, 380, 381),
+ (410, 381, 382),
+ (411, 382, 383),
+ (413, 55, 384),
+ (414, 384, 385),
+ (415, 385, 336),
+ (416, 336, 386),
+ (417, 386, 387),
+ (418, 385, 388),
+ (419, 388, 58),
+ (421, 389, 50),
+ (422, 50, 390),
+ (423, 390, 391),
+ (424, 391, 392),
+ (425, 392, 88),
+ (427, 36, 393),
+ (428, 393, 394),
+ (429, 394, 395),
+ (430, 395, 396),
+ (431, 396, 352),
+ (432, 352, 397),
+ (433, 397, 339),
+ (434, 339, 398),
+ (435, 398, 399),
+ (436, 399, 400),
+ (437, 400, 401),
+ (438, 401, 402),
+ (439, 402, 403),
+ (440, 403, 404),
+ (441, 404, 405),
+ (443, 406, 407),
+ (444, 407, 316),
+ (445, 316, 321),
+ (446, 321, 323),
+ (447, 323, 408),
+ (448, 408, 409),
+ (449, 409, 410),
+ (450, 410, 411),
+ (451, 411, 411),
+ (452, 411, 412),
+ (453, 412, 394),
+ (455, 413, 414),
+ (457, 415, 414),
+ (459, 416, 417),
+ (460, 417, 418),
+ (462, 419, 420),
+ (463, 420, 421),
+ (464, 421, 116),
+ (465, 116, 422),
+ (466, 422, 423),
+ (467, 423, 424),
+ (469, 417, 422),
+ (471, 425, 426),
+ (473, 124, 427),
+ (474, 427, 428),
+ (476, 425, 428),
+ (477, 428, 416),
+ (478, 416, 121),
+ (479, 121, 429),
+ (481, 430, 401),
+ (483, 431, 432),
+ (484, 432, 433),
+ (485, 433, 434),
+ (486, 434, 291),
+ (487, 291, 435),
+ (488, 435, 436),
+ (489, 436, 437),
+ (490, 437, 431),
+ (492, 129, 332),
+ (493, 332, 438),
+ (494, 438, 70),
+ (495, 70, 437),
+ (497, 429, 427),
+ (499, 418, 120),
+ (500, 120, 439),
+ (501, 439, 420),
+ (502, 420, 440),
+ (503, 440, 441),
+ (504, 441, 442),
+ (505, 442, 328),
+ (507, 327, 443),
+ (509, 444, 419),
+ (510, 419, 440),
+ (512, 445, 446),
+ (513, 446, 441),
+ (514, 441, 447),
+ (515, 447, 114),
+ (517, 442, 448),
+ (518, 448, 46),
+ (520, 443, 449),
+ (522, 449, 450),
+ (524, 450, 451),
+ (526, 451, 452),
+ (528, 452, 444),
+ (529, 444, 399),
+ (531, 76, 453),
+ (532, 441, 452),
+ (534, 454, 455),
+ (535, 455, 456),
+ (536, 456, 457),
+ (537, 457, 458),
+ (538, 458, 459),
+ (539, 459, 460),
+ (540, 460, 461),
+ (541, 461, 462),
+ (543, 463, 464),
+ (545, 465, 464),
+ (547, 463, 465),
+ (548, 465, 464),
+ (549, 464, 466),
+ (551, 467, 468),
+ (552, 468, 469),
+ (554, 470, 471),
+ (555, 471, 472),
+ (556, 472, 473),
+ (557, 473, 474),
+ (558, 474, 475),
+ (592, 90, 502),
+ (559, 475, 476),
+ (560, 477, 236),
+ (561, 236, 478),
+ (563, 479, 480),
+ (564, 480, 481),
+ (566, 482, 483),
+ (567, 483, 297),
+ (613, 484, 485),
+ (614, 485, 105),
+ (615, 105, 391),
+ (682, 486, 487),
+ (568, 297, 488),
+ (569, 145, 489),
+ (571, 270, 268),
+ (573, 490, 138),
+ (575, 140, 491),
+ (576, 491, 263),
+ (578, 492, 493),
+ (579, 493, 494),
+ (580, 494, 495),
+ (581, 349, 496),
+ (583, 497, 498),
+ (584, 498, 92),
+ (586, 494, 499),
+ (587, 499, 466),
+ (589, 500, 501),
+ (590, 501, 94),
+ (593, 502, 503),
+ (594, 503, 504),
+ (596, 366, 505),
+ (597, 505, 506),
+ (598, 506, 507),
+ (599, 507, 504),
+ (600, 504, 91),
+ (602, 508, 509),
+ (603, 509, 510),
+ (604, 510, 333),
+ (606, 511, 512),
+ (607, 512, 511),
+ (609, 511, 513),
+ (610, 513, 101),
+ (612, 75, 484),
+ (617, 466, 514),
+ (619, 463, 515),
+ (620, 515, 516),
+ (621, 516, 517),
+ (623, 518, 93),
+ (625, 519, 520),
+ (626, 520, 521),
+ (627, 521, 74),
+ (629, 522, 521),
+ (631, 523, 520),
+ (633, 524, 52),
+ (637, 57, 525),
+ (638, 525, 526),
+ (640, 56, 525),
+ (642, 527, 528),
+ (644, 527, 529),
+ (645, 529, 530),
+ (647, 524, 529),
+ (649, 59, 531),
+ (651, 532, 533),
+ (652, 533, 531),
+ (653, 531, 60),
+ (655, 533, 512),
+ (657, 511, 534),
+ (658, 534, 99),
+ (660, 535, 95),
+ (662, 536, 537),
+ (663, 537, 538),
+ (664, 538, 539),
+ (665, 539, 540),
+ (667, 53, 530),
+ (669, 45, 540),
+ (671, 541, 43),
+ (673, 329, 326),
+ (675, 96, 542),
+ (676, 542, 543),
+ (677, 543, 544),
+ (678, 544, 545),
+ (679, 545, 546),
+ (680, 546, 547),
+ (681, 547, 486),
+ (683, 487, 548),
+ (684, 548, 549),
+ (685, 549, 550),
+ (686, 550, 551),
+ (687, 551, 552),
+ (688, 552, 553),
+ (689, 553, 554),
+ (691, 555, 543),
+ (693, 556, 544),
+ (695, 557, 545),
+ (697, 558, 546),
+ (699, 559, 560),
+ (701, 561, 562),
+ (702, 562, 560),
+ (704, 563, 564),
+ (705, 564, 37),
+ (707, 565, 564),
+ (709, 566, 386),
+ (711, 423, 566),
+ (713, 567, 79),
+ (715, 568, 569),
+ (716, 569, 65),
+ (718, 67, 570),
+ (719, 570, 571),
+ (721, 459, 572),
+ (722, 572, 573),
+ (723, 573, 462),
+ (725, 574, 573),
+ (727, 575, 434),
+ (729, 576, 577),
+ (730, 577, 578),
+ (731, 578, 579),
+ (732, 579, 580),
+ (733, 580, 581),
+ (734, 581, 582),
+ (735, 582, 312),
+ (736, 312, 583),
+ (737, 583, 584),
+ (738, 584, 585),
+ (739, 585, 407),
+ (740, 407, 586),
+ (741, 586, 587),
+ (742, 587, 588),
+ (743, 588, 589),
+ (744, 589, 590),
+ (745, 590, 591),
+ (746, 591, 592),
+ (747, 592, 593),
+ (748, 593, 594),
+ (749, 594, 308),
+ (750, 308, 309),
+ (751, 309, 595),
+ (752, 595, 596),
+ (753, 596, 597),
+ (754, 597, 304),
+ (755, 304, 496),
+ (756, 496, 598),
+ (855, 599, 293),
+ (757, 598, 600),
+ (758, 600, 404),
+ (759, 404, 601),
+ (760, 601, 125),
+ (762, 602, 503),
+ (764, 603, 520),
+ (766, 604, 605),
+ (767, 605, 606),
+ (768, 606, 607),
+ (769, 607, 454),
+ (770, 454, 571),
+ (771, 571, 604),
+ (773, 606, 433),
+ (775, 608, 609),
+ (776, 609, 458),
+ (777, 458, 610),
+ (779, 611, 144),
+ (781, 612, 145),
+ (782, 145, 477),
+ (783, 477, 469),
+ (784, 469, 481),
+ (785, 481, 611),
+ (786, 611, 612),
+ (788, 613, 489),
+ (789, 489, 470),
+ (790, 470, 482),
+ (791, 482, 478),
+ (792, 478, 613),
+ (794, 614, 615),
+ (796, 616, 617),
+ (797, 617, 618),
+ (798, 618, 11),
+ (799, 11, 619),
+ (800, 619, 620),
+ (801, 620, 621),
+ (802, 621, 622),
+ (803, 622, 413),
+ (805, 623, 624),
+ (807, 623, 625),
+ (809, 626, 627),
+ (810, 627, 624),
+ (811, 624, 628),
+ (813, 629, 630),
+ (814, 630, 173),
+ (816, 623, 631),
+ (817, 631, 632),
+ (818, 632, 633),
+ (819, 633, 634),
+ (820, 635, 636),
+ (822, 626, 635),
+ (824, 637, 3),
+ (825, 3, 638),
+ (826, 638, 639),
+ (828, 627, 640),
+ (830, 639, 633),
+ (832, 641, 642),
+ (833, 642, 643),
+ (835, 2, 637),
+ (837, 644, 645),
+ (838, 645, 639),
+ (839, 639, 641),
+ (841, 646, 647),
+ (842, 647, 132),
+ (844, 131, 648),
+ (846, 649, 650),
+ (847, 650, 651),
+ (848, 651, 652),
+ (849, 652, 616),
+ (851, 649, 653),
+ (852, 653, 6),
+ (854, 653, 599),
+ (856, 293, 654),
+ (857, 654, 655),
+ (858, 655, 656),
+ (859, 656, 657),
+ (860, 657, 156),
+ (862, 155, 658),
+ (863, 658, 659),
+ (864, 659, 660),
+ (866, 656, 661),
+ (867, 661, 662),
+ (868, 662, 617),
+ (870, 663, 658),
+ (871, 658, 664),
+ (872, 664, 652),
+ (874, 153, 663),
+ (876, 158, 154),
+ (878, 31, 13),
+ (880, 14, 665),
+ (882, 666, 621),
+ (884, 667, 666),
+ (886, 29, 667),
+ (888, 668, 5),
+ (890, 152, 659),
+ (892, 669, 670),
+ (893, 670, 671),
+ (894, 672, 233),
+ (896, 670, 245),
+ (898, 673, 674),
+ (899, 674, 675),
+ (901, 676, 273),
+ (982, 734, 735),
+ (902, 273, 238),
+ (904, 240, 673),
+ (905, 673, 675),
+ (906, 675, 677),
+ (907, 217, 678),
+ (952, 633, 679),
+ (908, 678, 680),
+ (909, 680, 681),
+ (910, 681, 682),
+ (911, 682, 683),
+ (912, 683, 684),
+ (913, 685, 686),
+ (914, 686, 687),
+ (915, 687, 688),
+ (916, 688, 689),
+ (917, 689, 690),
+ (918, 690, 691),
+ (919, 691, 692),
+ (920, 692, 693),
+ (921, 693, 694),
+ (923, 230, 695),
+ (924, 645, 696),
+ (925, 214, 697),
+ (926, 698, 699),
+ (927, 700, 701),
+ (929, 300, 702),
+ (931, 703, 704),
+ (933, 705, 565),
+ (934, 565, 706),
+ (935, 706, 306),
+ (937, 707, 678),
+ (939, 708, 709),
+ (940, 709, 710),
+ (941, 710, 711),
+ (942, 711, 712),
+ (1025, 773, 774),
+ (943, 712, 713),
+ (944, 713, 714),
+ (945, 714, 715),
+ (947, 716, 698),
+ (948, 698, 717),
+ (949, 313, 718),
+ (950, 718, 706),
+ (953, 679, 719),
+ (954, 719, 720),
+ (955, 720, 721),
+ (956, 721, 722),
+ (958, 723, 724),
+ (959, 724, 725),
+ (960, 725, 726),
+ (962, 727, 703),
+ (963, 703, 679),
+ (964, 679, 722),
+ (966, 483, 728),
+ (967, 621, 729),
+ (968, 729, 15),
+ (970, 730, 731),
+ (971, 731, 732),
+ (972, 622, 733),
+ (973, 734, 735),
+ (974, 735, 736),
+ (975, 736, 737),
+ (976, 737, 731),
+ (978, 730, 738),
+ (979, 738, 739),
+ (980, 739, 740),
+ (981, 740, 734),
+ (984, 741, 738),
+ (986, 742, 743),
+ (987, 743, 744),
+ (988, 744, 745),
+ (989, 745, 143),
+ (991, 746, 747),
+ (992, 747, 748),
+ (993, 748, 749),
+ (994, 749, 260),
+ (996, 750, 751),
+ (997, 751, 752),
+ (999, 725, 743),
+ (1000, 743, 753),
+ (1001, 754, 755),
+ (1002, 755, 756),
+ (1003, 756, 757),
+ (1004, 757, 758),
+ (1006, 759, 760),
+ (1007, 760, 761),
+ (1008, 761, 762),
+ (1010, 763, 758),
+ (1011, 758, 762),
+ (1012, 762, 764),
+ (1013, 764, 141),
+ (1015, 765, 766),
+ (1017, 767, 768),
+ (1018, 768, 769),
+ (1019, 769, 770),
+ (1020, 770, 142),
+ (1022, 771, 757),
+ (1024, 772, 773),
+ (1027, 744, 767),
+ (1028, 767, 763),
+ (1029, 763, 771),
+ (1030, 771, 765),
+ (1032, 775, 750),
+ (1033, 750, 776),
+ (1035, 724, 777),
+ (1036, 778, 779),
+ (1037, 779, 780),
+ (1039, 769, 781),
+ (1040, 779, 775),
+ (1041, 775, 782),
+ (1042, 783, 751),
+ (1044, 756, 784),
+ (1045, 755, 785),
+ (1046, 749, 786),
+ (1047, 786, 787),
+ (1049, 768, 745),
+ (1051, 770, 760),
+ (1052, 760, 788),
+ (1053, 788, 789),
+ (1055, 762, 790),
+ (1056, 790, 746),
+ (1057, 746, 263),
+ (1059, 748, 787),
+ (1060, 787, 776),
+ (1061, 776, 780),
+ (1062, 780, 754),
+ (1063, 754, 747),
+ (1065, 290, 791),
+ (1066, 674, 792),
+ (1067, 139, 793),
+ (1069, 794, 795),
+ (1111, 817, 830),
+ (1070, 795, 796),
+ (1071, 796, 737),
+ (1073, 789, 761),
+ (1075, 797, 798),
+ (1076, 264, 799),
+ (1077, 773, 800),
+ (1078, 801, 802),
+ (1079, 795, 803),
+ (1080, 804, 805),
+ (1081, 719, 806),
+ (1082, 720, 807),
+ (1083, 721, 808),
+ (1084, 808, 704),
+ (1086, 809, 808),
+ (1088, 810, 150),
+ (1090, 165, 811),
+ (1091, 811, 812),
+ (1092, 812, 813),
+ (1093, 814, 815),
+ (1094, 816, 817),
+ (1096, 818, 819),
+ (1097, 819, 820),
+ (1099, 821, 822),
+ (1101, 823, 824),
+ (1103, 825, 819),
+ (1105, 826, 827),
+ (1106, 811, 168),
+ (1108, 828, 30),
+ (1110, 829, 817),
+ (1112, 831, 828),
+ (1114, 177, 176),
+ (1116, 793, 797),
+ (1117, 797, 793),
+ (1121, 832, 528),
+ (1122, 528, 526),
+ (1123, 526, 54),
+ (1125, 833, 821),
+ (1126, 821, 822),
+ (1127, 822, 833),
+ (1129, 834, 823),
+ (1130, 823, 835),
+ (1131, 835, 834),
+ (1133, 383, 836),
+ (1134, 836, 837),
+ (1135, 837, 561),
+ (1136, 561, 554),
+ (1137, 554, 383),
+ (1139, 295, 838),
+ (1141, 299, 716),
+ (1142, 716, 623),
+ (1144, 295, 839),
+ (1456, 840, 841),
+ (1146, 625, 636),
+ (1147, 636, 668),
+ (1149, 842, 825),
+ (1150, 825, 820),
+ (1151, 820, 843),
+ (1152, 843, 844),
+ (1153, 844, 816),
+ (1237, 878, 646),
+ (1154, 816, 845),
+ (1155, 845, 846),
+ (1156, 846, 629),
+ (1157, 629, 847),
+ (1158, 847, 848),
+ (1159, 848, 849),
+ (1160, 849, 850),
+ (1161, 850, 628),
+ (1162, 628, 851),
+ (1163, 839, 847),
+ (1165, 838, 173),
+ (1167, 852, 853),
+ (1168, 853, 854),
+ (1169, 855, 415),
+ (1171, 796, 856),
+ (1172, 856, 857),
+ (1173, 857, 737),
+ (1175, 736, 857),
+ (1176, 857, 856),
+ (1178, 620, 858),
+ (1179, 858, 665),
+ (1180, 665, 12),
+ (1181, 12, 32),
+ (1182, 32, 859),
+ (1183, 859, 660),
+ (1184, 660, 664),
+ (1185, 664, 657),
+ (1186, 657, 157),
+ (1187, 157, 860),
+ (1188, 860, 861),
+ (1189, 861, 646),
+ (1190, 646, 648),
+ (1191, 648, 862),
+ (1192, 862, 294),
+ (1194, 863, 855),
+ (1195, 855, 413),
+ (1197, 413, 415),
+ (1198, 415, 863),
+ (1200, 144, 801),
+ (1201, 801, 766),
+ (1202, 766, 864),
+ (1203, 864, 752),
+ (1204, 752, 865),
+ (1205, 865, 866),
+ (1206, 866, 867),
+ (1260, 493, 868),
+ (1262, 869, 185),
+ (1263, 185, 826),
+ (1207, 867, 870),
+ (1208, 788, 871),
+ (1209, 764, 872),
+ (1210, 873, 874),
+ (1212, 790, 491),
+ (1213, 491, 267),
+ (1215, 875, 750),
+ (1217, 786, 874),
+ (1218, 874, 875),
+ (1219, 875, 876),
+ (1220, 876, 866),
+ (1222, 865, 876),
+ (1223, 876, 873),
+ (1224, 873, 867),
+ (1226, 618, 859),
+ (1228, 868, 730),
+ (1230, 730, 619),
+ (1231, 619, 858),
+ (1233, 835, 877),
+ (1234, 29, 828),
+ (1236, 647, 878),
+ (1239, 599, 435),
+ (1241, 860, 651),
+ (1242, 651, 879),
+ (1243, 879, 599),
+ (1245, 880, 881),
+ (1246, 514, 517),
+ (1247, 517, 462),
+ (1249, 861, 650),
+ (1250, 650, 879),
+ (1251, 879, 293),
+ (1253, 730, 742),
+ (1254, 742, 726),
+ (1256, 868, 492),
+ (1257, 492, 514),
+ (1259, 514, 493),
+ (1264, 826, 882),
+ (1265, 882, 883),
+ (1266, 878, 880),
+ (1268, 499, 884),
+ (1269, 884, 885),
+ (1270, 885, 460),
+ (1272, 516, 460),
+ (1274, 743, 886),
+ (1275, 729, 887),
+ (1276, 739, 740),
+ (1278, 515, 888),
+ (1279, 432, 605),
+ (1281, 577, 774),
+ (1283, 889, 890),
+ (1284, 890, 891),
+ (1285, 891, 892),
+ (1286, 892, 562),
+ (1287, 562, 893),
+ (1288, 378, 894),
+ (1289, 837, 892),
+ (1291, 836, 891),
+ (1293, 890, 895),
+ (1295, 489, 576),
+ (1297, 896, 470),
+ (1299, 502, 505),
+ (1301, 470, 472),
+ (1303, 506, 889),
+ (1304, 889, 895),
+ (1305, 895, 382),
+ (1307, 480, 804),
+ (1308, 804, 897),
+ (1309, 258, 478),
+ (1311, 482, 258),
+ (1313, 864, 778),
+ (1314, 778, 765),
+ (1539, 898, 899),
+ (1316, 900, 901),
+ (1317, 902, 903),
+ (1318, 248, 904),
+ (1319, 234, 905),
+ (1320, 174, 303),
+ (1321, 303, 814),
+ (1322, 814, 175),
+ (1323, 175, 906),
+ (1325, 846, 907),
+ (1326, 845, 133),
+ (1328, 906, 908),
+ (1329, 843, 183),
+ (1330, 183, 829),
+ (1332, 130, 909),
+ (1334, 829, 184),
+ (1335, 184, 844),
+ (1337, 850, 849),
+ (1339, 910, 911),
+ (1341, 912, 906),
+ (1343, 911, 913),
+ (1345, 174, 914),
+ (1347, 911, 848),
+ (1349, 630, 302),
+ (1351, 862, 909),
+ (1352, 909, 131),
+ (1354, 299, 910),
+ (1355, 910, 913),
+ (1356, 913, 914),
+ (1357, 914, 173),
+ (1359, 615, 632),
+ (1361, 812, 133),
+ (1363, 643, 615),
+ (1365, 638, 631),
+ (1366, 631, 915),
+ (1368, 643, 916),
+ (1370, 702, 916),
+ (1372, 916, 702),
+ (1374, 915, 642),
+ (1376, 917, 583),
+ (1377, 583, 853),
+ (1378, 853, 314),
+ (1379, 314, 918),
+ (1380, 918, 919),
+ (1381, 919, 33),
+ (1383, 397, 920),
+ (1384, 920, 341),
+ (1386, 921, 922),
+ (1387, 922, 923),
+ (1388, 923, 350),
+ (1390, 922, 924),
+ (1391, 924, 396),
+ (1393, 925, 921),
+ (1394, 921, 926),
+ (1395, 926, 927),
+ (1397, 928, 929),
+ (1455, 947, 840),
+ (1398, 929, 930),
+ (1399, 930, 923),
+ (1401, 930, 931),
+ (1402, 929, 347),
+ (1404, 932, 933),
+ (1405, 933, 926),
+ (1407, 409, 934),
+ (1408, 934, 935),
+ (1410, 936, 928),
+ (1411, 928, 932),
+ (1413, 932, 927),
+ (1414, 927, 937),
+ (1416, 937, 938),
+ (1418, 939, 935),
+ (1419, 935, 940),
+ (1420, 940, 938),
+ (1422, 348, 936),
+ (1424, 933, 921),
+ (1426, 510, 941),
+ (1427, 941, 942),
+ (1429, 941, 509),
+ (1431, 943, 852),
+ (1432, 852, 944),
+ (1433, 944, 584),
+ (1434, 584, 945),
+ (1435, 945, 946),
+ (1439, 947, 948),
+ (1440, 948, 39),
+ (1442, 949, 948),
+ (1443, 948, 40),
+ (1445, 841, 72),
+ (1447, 840, 72),
+ (1449, 950, 71),
+ (1451, 951, 952),
+ (1453, 953, 950),
+ (1454, 950, 947),
+ (1457, 841, 954),
+ (1458, 955, 956),
+ (1459, 956, 402),
+ (1461, 957, 958),
+ (1463, 958, 400),
+ (1465, 957, 959),
+ (1466, 959, 121),
+ (1468, 960, 952),
+ (1470, 335, 961),
+ (1471, 962, 87),
+ (1473, 963, 368),
+ (1475, 559, 553),
+ (1476, 553, 964),
+ (1477, 381, 552),
+ (1479, 552, 965),
+ (1481, 551, 966),
+ (1482, 966, 967),
+ (1483, 967, 968),
+ (1484, 968, 380),
+ (1486, 551, 969),
+ (1541, 898, 970),
+ (1487, 969, 486),
+ (1489, 969, 487),
+ (1491, 559, 971),
+ (1492, 966, 965),
+ (1494, 972, 967),
+ (1495, 967, 973),
+ (1496, 973, 974),
+ (1497, 974, 550),
+ (1499, 974, 973),
+ (1500, 973, 968),
+ (1502, 549, 975),
+ (1503, 975, 378),
+ (1505, 548, 976),
+ (1506, 975, 977),
+ (1507, 978, 379),
+ (1509, 507, 979),
+ (1510, 542, 980),
+ (1511, 981, 982),
+ (1513, 112, 983),
+ (1514, 984, 985),
+ (1515, 985, 398),
+ (1517, 940, 411),
+ (1518, 411, 411),
+ (1520, 986, 587),
+ (1521, 587, 987),
+ (1523, 885, 988),
+ (1524, 989, 990),
+ (1525, 990, 991),
+ (1526, 990, 992),
+ (1527, 990, 993),
+ (1528, 994, 990),
+ (1530, 990, 995),
+ (1531, 996, 709),
+ (1532, 709, 997),
+ (1533, 998, 898),
+ (1534, 898, 899),
+ (1535, 899, 970),
+ (1536, 970, 999),
+ (1537, 999, 898),
+ (1543, 898, 999),
+ (1545, 334, 1000),
+ (1546, 69, 1001),
+ (1547, 1001, 1002),
+ (1548, 1003, 1004),
+ (1550, 1005, 1006),
+ (1552, 337, 1007),
+ (1553, 69, 1008),
+ (1554, 570, 1009),
+ (1555, 1009, 1010),
+ (1556, 1011, 1012),
+ (1557, 884, 772),
+ (1559, 1013, 1014),
+ (1613, 508, 129),
+ (1560, 1014, 1015),
+ (1562, 1016, 1014),
+ (1564, 1017, 1018),
+ (1565, 581, 1019),
+ (1566, 582, 1020),
+ (1567, 78, 1021),
+ (1568, 536, 1022),
+ (1569, 1022, 73),
+ (1571, 44, 539),
+ (1573, 537, 1023),
+ (1574, 538, 1024),
+ (1575, 317, 1025),
+ (1576, 317, 1026),
+ (1577, 319, 1027),
+ (1578, 318, 944),
+ (1580, 718, 1028),
+ (1581, 126, 1029),
+ (1582, 1029, 1030),
+ (1583, 1030, 405),
+ (1584, 405, 1031),
+ (1585, 1031, 1032),
+ (1586, 1032, 1033),
+ (1588, 403, 430),
+ (1589, 430, 1034),
+ (1590, 1034, 123),
+ (1592, 1032, 1035),
+ (1593, 1035, 1036),
+ (1595, 1035, 1037),
+ (1597, 1038, 405),
+ (1599, 1039, 1030),
+ (1601, 598, 1040),
+ (1602, 1036, 1041),
+ (1604, 1042, 1043),
+ (1606, 1042, 1044),
+ (1607, 1043, 1045),
+ (1608, 1046, 1047),
+ (1610, 1046, 1048),
+ (1611, 1047, 1049),
+ (1612, 128, 508),
+ (1615, 127, 426),
+ (1617, 215, 222),
+ (1619, 223, 707),
+ (1621, 707, 224),
+ (1623, 224, 216),
+ (1625, 216, 225),
+ (1627, 226, 211),
+ (1629, 211, 220),
+ (1631, 215, 221),
+ (1633, 640, 644),
+ (1635, 49, 390),
+ (1636, 390, 1050),
+ (1637, 1050, 1051),
+ (1638, 438, 1001),
+ (1639, 1001, 569),
+ (1640, 569, 104),
+ (1641, 104, 1052),
+ (1642, 1052, 338),
+ (1643, 338, 388),
+ (1644, 388, 384),
+ (1645, 384, 982),
+ (1646, 982, 1053),
+ (1647, 1053, 389),
+ (1648, 389, 107),
+ (1649, 107, 1054),
+ (1650, 1054, 448),
+ (1651, 448, 330),
+ (1652, 330, 325),
+ (1653, 325, 393),
+ (1654, 393, 1055),
+ (1655, 1055, 943),
+ (1657, 436, 1056),
+ (1658, 1056, 1029),
+ (1659, 1029, 601),
+ (1660, 601, 1057),
+ (1661, 1057, 1034),
+ (1662, 1034, 959),
+ (1663, 959, 439),
+ (1664, 439, 421),
+ (1665, 421, 447),
+ (1666, 447, 446),
+ (1667, 446, 1054),
+ (1668, 1054, 47),
+ (1669, 47, 485),
+ (1671, 604, 1009),
+ (1672, 1009, 68),
+ (1674, 1031, 600),
+ (1675, 600, 956),
+ (1676, 956, 985),
+ (1677, 985, 340),
+ (1678, 340, 920),
+ (1679, 920, 351),
+ (1680, 351, 924),
+ (1681, 924, 1058),
+ (1682, 1058, 412),
+ (1683, 412, 1055),
+ (1684, 1055, 35),
+ (1686, 1059, 579),
+ (1687, 579, 1060),
+ (1688, 1060, 81),
+ (1690, 82, 1061),
+ (1691, 1061, 1062),
+ (1692, 1062, 484),
+ (1693, 484, 1022),
+ (1694, 1022, 42),
+ (1696, 392, 371),
+ (1697, 371, 1063),
+ (1698, 1063, 1061),
+ (1699, 1061, 80),
+ (1700, 80, 580),
+ (1701, 580, 1064),
+ (1703, 89, 1065),
+ (1704, 1065, 51),
+ (1705, 51, 1053),
+ (1707, 1052, 61),
+ (1708, 61, 513),
+ (1709, 513, 534),
+ (1710, 534, 501),
+ (1711, 501, 498),
+ (1712, 498, 1065),
+ (1713, 1065, 392),
+ (1715, 461, 572),
+ (1716, 572, 610),
+ (1717, 610, 1066),
+ (1718, 1066, 1067),
+ (1719, 1067, 1068),
+ (1720, 1068, 607),
+ (1722, 711, 1069),
+ (1723, 1069, 1070),
+ (1724, 1070, 701),
+ (1725, 701, 1071),
+ (1726, 1071, 694),
+ (1727, 694, 609),
+ (1728, 609, 1072),
+ (1729, 1072, 456),
+ (1730, 456, 1067),
+ (1772, 1073, 946),
+ (1732, 715, 1074),
+ (1733, 1074, 1075),
+ (1734, 1075, 1076),
+ (1735, 1076, 710),
+ (1737, 1068, 455),
+ (1738, 455, 1077),
+ (1739, 1077, 608),
+ (1740, 608, 693),
+ (1741, 693, 1078),
+ (1742, 1078, 712),
+ (1743, 712, 1076),
+ (1744, 1076, 1079),
+ (1745, 1079, 1080),
+ (1746, 1080, 1081),
+ (1747, 1081, 1082),
+ (1748, 1066, 457),
+ (1749, 457, 1072),
+ (1750, 1072, 1077),
+ (1752, 1083, 1075),
+ (1753, 1075, 713),
+ (1755, 714, 1074),
+ (1756, 1074, 1084),
+ (1757, 1071, 1078),
+ (1759, 1078, 1070),
+ (1760, 1070, 700),
+ (1762, 1033, 1085),
+ (1763, 1085, 310),
+ (1764, 310, 307),
+ (1765, 307, 1086),
+ (1766, 1086, 1087),
+ (1767, 1087, 986),
+ (1768, 986, 1088),
+ (1769, 1088, 1089),
+ (1770, 1089, 406),
+ (1771, 406, 1073),
+ (1773, 946, 917),
+ (1774, 917, 1090),
+ (1775, 1090, 1091),
+ (1776, 1091, 1092),
+ (1777, 1092, 1093),
+ (1778, 1093, 1094),
+ (1779, 1094, 1064),
+ (1780, 1064, 1059),
+ (1781, 1059, 1095),
+ (1782, 1095, 1096),
+ (1783, 1096, 896),
+ (1785, 395, 1058),
+ (1786, 1058, 1097),
+ (1787, 1097, 934),
+ (1788, 934, 1098),
+ (1789, 1098, 1099),
+ (1790, 1099, 320),
+ (1791, 320, 586),
+ (1792, 586, 1089),
+ (1794, 987, 588),
+ (1795, 588, 1087),
+ (1797, 1063, 85),
+ (1798, 85, 1100),
+ (1799, 1100, 353),
+ (1801, 1050, 106),
+ (1803, 1062, 1101),
+ (1804, 370, 1100),
+ (1805, 1100, 1102),
+ (1807, 1102, 1103);
+
+create table e03.ways(
+ id integer,
+ source integer,
+ target integer
+);
+
+insert into e03.ways values
+ (1, 1, 2),
+ (2, 2, 3),
+ (3, 3, 4),
+ (4, 4, 5),
+ (5, 5, 6),
+ (7, 7, 8),
+ (8, 9, 10),
+ (9, 11, 12),
+ (10, 12, 13),
+ (11, 13, 14),
+ (12, 14, 15),
+ (13, 15, 16),
+ (15, 17, 18),
+ (16, 18, 19),
+ (17, 19, 20),
+ (18, 20, 21),
+ (19, 21, 22),
+ (20, 22, 23),
+ (21, 23, 24),
+ (22, 24, 25),
+ (23, 25, 26),
+ (24, 26, 27),
+ (25, 27, 28),
+ (26, 28, 29),
+ (27, 29, 30),
+ (28, 30, 31),
+ (29, 31, 32),
+ (31, 33, 34),
+ (32, 34, 35),
+ (33, 35, 36),
+ (34, 36, 37),
+ (35, 37, 38),
+ (36, 38, 39),
+ (37, 39, 40),
+ (38, 40, 41),
+ (39, 41, 42),
+ (40, 42, 43),
+ (41, 43, 44),
+ (42, 44, 45),
+ (43, 45, 46),
+ (44, 46, 47),
+ (45, 47, 48),
+ (46, 48, 49),
+ (47, 49, 50),
+ (48, 50, 51),
+ (49, 51, 52),
+ (50, 52, 53),
+ (51, 53, 54),
+ (52, 54, 55),
+ (53, 55, 56),
+ (54, 56, 57),
+ (55, 57, 58),
+ (56, 58, 59),
+ (57, 59, 60),
+ (58, 60, 61),
+ (59, 61, 62),
+ (60, 62, 63),
+ (61, 63, 64),
+ (62, 64, 65),
+ (63, 65, 66),
+ (64, 66, 67),
+ (65, 67, 68),
+ (66, 68, 69),
+ (67, 69, 70),
+ (69, 41, 71),
+ (70, 71, 72),
+ (71, 72, 73),
+ (72, 73, 74),
+ (73, 74, 75),
+ (74, 75, 76),
+ (75, 76, 77),
+ (76, 77, 78),
+ (77, 78, 79),
+ (78, 79, 80),
+ (79, 80, 81),
+ (80, 81, 82),
+ (81, 82, 83),
+ (82, 83, 84),
+ (83, 84, 85),
+ (84, 85, 86),
+ (85, 86, 87),
+ (86, 87, 88),
+ (87, 88, 89),
+ (88, 89, 90),
+ (89, 90, 91),
+ (90, 91, 92),
+ (91, 92, 93),
+ (92, 93, 94),
+ (93, 94, 95),
+ (94, 95, 96),
+ (95, 96, 97),
+ (96, 97, 98),
+ (97, 98, 99),
+ (98, 99, 100),
+ (99, 100, 101),
+ (100, 101, 102),
+ (101, 102, 103),
+ (102, 103, 62),
+ (103, 62, 104),
+ (105, 105, 106),
+ (106, 106, 48),
+ (107, 48, 107),
+ (108, 107, 108),
+ (109, 108, 109),
+ (110, 109, 110),
+ (111, 110, 111),
+ (112, 111, 112),
+ (113, 112, 113),
+ (114, 113, 114),
+ (115, 114, 115),
+ (116, 115, 116),
+ (117, 116, 117),
+ (118, 117, 118),
+ (119, 118, 119),
+ (120, 119, 120),
+ (121, 120, 121),
+ (122, 121, 122),
+ (124, 122, 123),
+ (125, 123, 124),
+ (126, 124, 125),
+ (127, 125, 126),
+ (128, 126, 127),
+ (129, 127, 128),
+ (130, 128, 129),
+ (132, 6, 130),
+ (133, 130, 131),
+ (134, 131, 132),
+ (135, 132, 133),
+ (136, 133, 134),
+ (137, 134, 135),
+ (138, 135, 136),
+ (139, 137, 138),
+ (140, 138, 139),
+ (141, 139, 140),
+ (142, 140, 141),
+ (143, 141, 142),
+ (144, 142, 143),
+ (146, 144, 145),
+ (148, 146, 147),
+ (149, 147, 148),
+ (150, 148, 149),
+ (151, 149, 150),
+ (152, 150, 151),
+ (153, 151, 152),
+ (154, 152, 153),
+ (155, 153, 154),
+ (156, 154, 155),
+ (157, 155, 156),
+ (159, 157, 158),
+ (160, 158, 159),
+ (162, 160, 161),
+ (163, 161, 162),
+ (164, 162, 163),
+ (165, 163, 164),
+ (166, 164, 165),
+ (167, 165, 166),
+ (168, 166, 167),
+ (169, 167, 168),
+ (170, 168, 169),
+ (171, 169, 170),
+ (172, 170, 171),
+ (173, 171, 172),
+ (174, 172, 159),
+ (176, 173, 174),
+ (178, 175, 176),
+ (179, 176, 177),
+ (180, 177, 178),
+ (181, 178, 179),
+ (182, 179, 180),
+ (183, 181, 178),
+ (184, 178, 182),
+ (185, 179, 183),
+ (186, 183, 184),
+ (188, 151, 185),
+ (190, 186, 187),
+ (191, 188, 189),
+ (192, 189, 190),
+ (193, 190, 191),
+ (194, 191, 192),
+ (195, 192, 193),
+ (196, 193, 194),
+ (197, 194, 195),
+ (198, 196, 197),
+ (199, 197, 198),
+ (200, 198, 199),
+ (202, 200, 201),
+ (203, 201, 197),
+ (204, 197, 202),
+ (205, 202, 203),
+ (206, 203, 204),
+ (207, 204, 205),
+ (209, 204, 199),
+ (211, 206, 207),
+ (212, 207, 208),
+ (213, 207, 209),
+ (214, 210, 211),
+ (216, 212, 213),
+ (217, 213, 214),
+ (218, 214, 215),
+ (220, 216, 217),
+ (221, 217, 218),
+ (223, 219, 220),
+ (224, 220, 221),
+ (225, 221, 222),
+ (226, 222, 223),
+ (227, 223, 224),
+ (228, 224, 225),
+ (229, 225, 226),
+ (230, 226, 219),
+ (232, 213, 227),
+ (234, 228, 229),
+ (235, 229, 227),
+ (236, 227, 230),
+ (237, 230, 231),
+ (239, 232, 233),
+ (240, 233, 234),
+ (241, 234, 235),
+ (243, 236, 237),
+ (244, 237, 238),
+ (245, 238, 239),
+ (246, 239, 240),
+ (247, 240, 241),
+ (248, 241, 242),
+ (249, 242, 243),
+ (250, 243, 244),
+ (251, 244, 245),
+ (252, 245, 246),
+ (253, 246, 247),
+ (254, 247, 248),
+ (255, 248, 249),
+ (256, 249, 250),
+ (257, 250, 251),
+ (258, 251, 252),
+ (259, 252, 253),
+ (260, 253, 254),
+ (261, 254, 255),
+ (262, 255, 256),
+ (263, 256, 257),
+ (265, 237, 235),
+ (266, 235, 258),
+ (268, 259, 260),
+ (269, 260, 261),
+ (270, 262, 263),
+ (272, 259, 263),
+ (274, 263, 264),
+ (275, 264, 265),
+ (276, 265, 266),
+ (277, 266, 267),
+ (278, 267, 268),
+ (280, 265, 269),
+ (281, 269, 270),
+ (282, 270, 271),
+ (283, 269, 266),
+ (285, 272, 218),
+ (286, 218, 231),
+ (287, 231, 272),
+ (289, 273, 274),
+ (291, 275, 274),
+ (292, 274, 246),
+ (294, 276, 277),
+ (295, 278, 279),
+ (296, 279, 280),
+ (297, 280, 281),
+ (298, 281, 282),
+ (299, 282, 283),
+ (300, 283, 284),
+ (301, 284, 285),
+ (302, 285, 286),
+ (303, 286, 276),
+ (304, 276, 287),
+ (305, 288, 289),
+ (306, 289, 290),
+ (307, 290, 257),
+ (309, 291, 292),
+ (310, 292, 293),
+ (312, 294, 295),
+ (314, 296, 288),
+ (315, 288, 289),
+ (316, 289, 286),
+ (317, 286, 285),
+ (319, 297, 298),
+ (320, 299, 300),
+ (321, 300, 301),
+ (322, 302, 303),
+ (324, 304, 305),
+ (325, 77, 306),
+ (373, 347, 348),
+ (327, 3, 307),
+ (328, 307, 308),
+ (330, 309, 310),
+ (331, 310, 4),
+ (333, 311, 312),
+ (334, 312, 313),
+ (335, 313, 314),
+ (336, 314, 315),
+ (337, 316, 317),
+ (338, 317, 318),
+ (339, 318, 319),
+ (341, 320, 321),
+ (342, 321, 322),
+ (343, 322, 323),
+ (345, 322, 324),
+ (347, 38, 325),
+ (348, 325, 326),
+ (349, 326, 327),
+ (350, 327, 328),
+ (351, 328, 329),
+ (352, 329, 330),
+ (353, 330, 43),
+ (355, 115, 331),
+ (356, 332, 333),
+ (357, 333, 334),
+ (358, 334, 335),
+ (359, 335, 336),
+ (361, 335, 337),
+ (362, 337, 338),
+ (363, 338, 59),
+ (365, 339, 340),
+ (366, 340, 341),
+ (367, 341, 342),
+ (368, 342, 343),
+ (369, 343, 344),
+ (370, 344, 345),
+ (371, 345, 346),
+ (372, 346, 347),
+ (374, 348, 349),
+ (376, 346, 350),
+ (377, 350, 351),
+ (378, 351, 352),
+ (380, 353, 354),
+ (381, 354, 355),
+ (382, 355, 356),
+ (383, 356, 357),
+ (384, 357, 358),
+ (385, 358, 359),
+ (386, 359, 360),
+ (387, 360, 361),
+ (388, 361, 362),
+ (389, 362, 363),
+ (390, 363, 364),
+ (391, 364, 365),
+ (392, 365, 366),
+ (393, 366, 367),
+ (394, 367, 368),
+ (395, 368, 369),
+ (396, 369, 370),
+ (397, 370, 86),
+ (398, 86, 371),
+ (400, 354, 372),
+ (401, 372, 373),
+ (402, 373, 374),
+ (403, 374, 375),
+ (404, 375, 376),
+ (405, 376, 377),
+ (406, 377, 378),
+ (407, 378, 379),
+ (408, 379, 380),
+ (409, 380, 381),
+ (410, 381, 382),
+ (411, 382, 383),
+ (413, 55, 384),
+ (414, 384, 385),
+ (415, 385, 336),
+ (416, 336, 386),
+ (417, 386, 387),
+ (418, 385, 388),
+ (419, 388, 58),
+ (421, 389, 50),
+ (422, 50, 390),
+ (423, 390, 391),
+ (424, 391, 392),
+ (425, 392, 88),
+ (427, 36, 393),
+ (428, 393, 394),
+ (429, 394, 395),
+ (430, 395, 396),
+ (431, 396, 352),
+ (432, 352, 397),
+ (433, 397, 339),
+ (434, 339, 398),
+ (435, 398, 399),
+ (436, 399, 400),
+ (437, 400, 401),
+ (438, 401, 402),
+ (439, 402, 403),
+ (440, 403, 404),
+ (441, 404, 405),
+ (443, 406, 407),
+ (444, 407, 316),
+ (445, 316, 321),
+ (446, 321, 323),
+ (447, 323, 408),
+ (448, 408, 409),
+ (449, 409, 410),
+ (450, 410, 411),
+ (451, 411, 411),
+ (452, 411, 412),
+ (453, 412, 394),
+ (455, 413, 414),
+ (457, 415, 414),
+ (459, 416, 417),
+ (460, 417, 418),
+ (462, 419, 420),
+ (463, 420, 421),
+ (464, 421, 116),
+ (465, 116, 422),
+ (466, 422, 423),
+ (467, 423, 424),
+ (469, 417, 422),
+ (471, 425, 426),
+ (473, 124, 427),
+ (474, 427, 428),
+ (476, 425, 428),
+ (477, 428, 416),
+ (478, 416, 121),
+ (479, 121, 429),
+ (481, 430, 401),
+ (483, 431, 432),
+ (484, 432, 433),
+ (485, 433, 434),
+ (486, 434, 291),
+ (487, 291, 435),
+ (488, 435, 436),
+ (489, 436, 437),
+ (490, 437, 431),
+ (492, 129, 332),
+ (493, 332, 438),
+ (494, 438, 70),
+ (495, 70, 437),
+ (497, 429, 427),
+ (499, 418, 120),
+ (500, 120, 439),
+ (501, 439, 420),
+ (502, 420, 440),
+ (503, 440, 441),
+ (504, 441, 442),
+ (505, 442, 328),
+ (507, 327, 443),
+ (509, 444, 419),
+ (510, 419, 440),
+ (512, 445, 446),
+ (513, 446, 441),
+ (514, 441, 447),
+ (515, 447, 114),
+ (517, 442, 448),
+ (518, 448, 46),
+ (520, 443, 449),
+ (522, 449, 450),
+ (524, 450, 451),
+ (526, 451, 452),
+ (528, 452, 444),
+ (529, 444, 399),
+ (531, 76, 453),
+ (532, 441, 452),
+ (534, 454, 455),
+ (535, 455, 456),
+ (536, 456, 457),
+ (537, 457, 458),
+ (538, 458, 459),
+ (539, 459, 460),
+ (540, 460, 461),
+ (541, 461, 462),
+ (543, 463, 464),
+ (545, 465, 464),
+ (547, 463, 465),
+ (548, 465, 464),
+ (549, 464, 466),
+ (551, 467, 468),
+ (552, 468, 469),
+ (554, 470, 471),
+ (555, 471, 472),
+ (556, 472, 473),
+ (557, 473, 474),
+ (558, 474, 475),
+ (592, 90, 502),
+ (559, 475, 476),
+ (560, 477, 236),
+ (561, 236, 478),
+ (563, 479, 480),
+ (564, 480, 481),
+ (566, 482, 483),
+ (567, 483, 297),
+ (613, 484, 485),
+ (614, 485, 105),
+ (615, 105, 391),
+ (682, 486, 487),
+ (568, 297, 488),
+ (569, 145, 489),
+ (571, 270, 268),
+ (573, 490, 138),
+ (575, 140, 491),
+ (576, 491, 263),
+ (578, 492, 493),
+ (579, 493, 494),
+ (580, 494, 495),
+ (581, 349, 496),
+ (583, 497, 498),
+ (584, 498, 92),
+ (586, 494, 499),
+ (587, 499, 466),
+ (589, 500, 501),
+ (590, 501, 94),
+ (593, 502, 503),
+ (594, 503, 504),
+ (596, 366, 505),
+ (597, 505, 506),
+ (598, 506, 507),
+ (599, 507, 504),
+ (600, 504, 91),
+ (602, 508, 509),
+ (603, 509, 510),
+ (604, 510, 333),
+ (606, 511, 512),
+ (607, 512, 511),
+ (609, 511, 513),
+ (610, 513, 101),
+ (612, 75, 484),
+ (617, 466, 514),
+ (619, 463, 515),
+ (620, 515, 516),
+ (621, 516, 517),
+ (623, 518, 93),
+ (625, 519, 520),
+ (626, 520, 521),
+ (627, 521, 74),
+ (629, 522, 521),
+ (631, 523, 520),
+ (633, 524, 52),
+ (637, 57, 525),
+ (638, 525, 526),
+ (640, 56, 525),
+ (642, 527, 528),
+ (644, 527, 529),
+ (645, 529, 530),
+ (647, 524, 529),
+ (649, 59, 531),
+ (651, 532, 533),
+ (652, 533, 531),
+ (653, 531, 60),
+ (655, 533, 512),
+ (657, 511, 534),
+ (658, 534, 99),
+ (660, 535, 95),
+ (662, 536, 537),
+ (663, 537, 538),
+ (664, 538, 539),
+ (665, 539, 540),
+ (667, 53, 530),
+ (669, 45, 540),
+ (671, 541, 43),
+ (673, 329, 326),
+ (675, 96, 542),
+ (676, 542, 543),
+ (677, 543, 544),
+ (678, 544, 545),
+ (679, 545, 546),
+ (680, 546, 547),
+ (681, 547, 486),
+ (683, 487, 548),
+ (684, 548, 549),
+ (685, 549, 550),
+ (686, 550, 551),
+ (687, 551, 552),
+ (688, 552, 553),
+ (689, 553, 554),
+ (691, 555, 543),
+ (693, 556, 544),
+ (695, 557, 545),
+ (697, 558, 546),
+ (699, 559, 560),
+ (701, 561, 562),
+ (702, 562, 560),
+ (704, 563, 564),
+ (705, 564, 37),
+ (707, 565, 564),
+ (709, 566, 386),
+ (711, 423, 566),
+ (713, 567, 79),
+ (715, 568, 569),
+ (716, 569, 65),
+ (718, 67, 570),
+ (719, 570, 571),
+ (721, 459, 572),
+ (722, 572, 573),
+ (723, 573, 462),
+ (725, 574, 573),
+ (727, 575, 434),
+ (729, 576, 577),
+ (730, 577, 578),
+ (731, 578, 579),
+ (732, 579, 580),
+ (733, 580, 581),
+ (734, 581, 582),
+ (735, 582, 312),
+ (736, 312, 583),
+ (737, 583, 584),
+ (738, 584, 585),
+ (739, 585, 407),
+ (740, 407, 586),
+ (741, 586, 587),
+ (742, 587, 588),
+ (743, 588, 589),
+ (744, 589, 590),
+ (745, 590, 591),
+ (746, 591, 592),
+ (747, 592, 593),
+ (748, 593, 594),
+ (749, 594, 308),
+ (750, 308, 309),
+ (751, 309, 595),
+ (752, 595, 596),
+ (753, 596, 597),
+ (754, 597, 304),
+ (755, 304, 496),
+ (756, 496, 598),
+ (855, 599, 293),
+ (757, 598, 600),
+ (758, 600, 404),
+ (759, 404, 601),
+ (760, 601, 125),
+ (762, 602, 503),
+ (764, 603, 520),
+ (766, 604, 605),
+ (767, 605, 606),
+ (768, 606, 607),
+ (769, 607, 454),
+ (770, 454, 571),
+ (771, 571, 604),
+ (773, 606, 433),
+ (775, 608, 609),
+ (776, 609, 458),
+ (777, 458, 610),
+ (779, 611, 144),
+ (781, 612, 145),
+ (782, 145, 477),
+ (783, 477, 469),
+ (784, 469, 481),
+ (785, 481, 611),
+ (786, 611, 612),
+ (788, 613, 489),
+ (789, 489, 470),
+ (790, 470, 482),
+ (791, 482, 478),
+ (792, 478, 613),
+ (794, 614, 615),
+ (796, 616, 617),
+ (797, 617, 618),
+ (798, 618, 11),
+ (799, 11, 619),
+ (800, 619, 620),
+ (801, 620, 621),
+ (802, 621, 622),
+ (803, 622, 413),
+ (805, 623, 624),
+ (807, 623, 625),
+ (809, 626, 627),
+ (810, 627, 624),
+ (811, 624, 628),
+ (813, 629, 630),
+ (814, 630, 173),
+ (816, 623, 631),
+ (817, 631, 632),
+ (818, 632, 633),
+ (819, 633, 634),
+ (820, 635, 636),
+ (822, 626, 635),
+ (824, 637, 3),
+ (825, 3, 638),
+ (826, 638, 639),
+ (828, 627, 640),
+ (830, 639, 633),
+ (832, 641, 642),
+ (833, 642, 643),
+ (835, 2, 637),
+ (837, 644, 645),
+ (838, 645, 639),
+ (839, 639, 641),
+ (841, 646, 647),
+ (842, 647, 132),
+ (844, 131, 648),
+ (846, 649, 650),
+ (847, 650, 651),
+ (848, 651, 652),
+ (849, 652, 616),
+ (851, 649, 653),
+ (852, 653, 6),
+ (854, 653, 599),
+ (856, 293, 654),
+ (857, 654, 655),
+ (858, 655, 656),
+ (859, 656, 657),
+ (860, 657, 156),
+ (862, 155, 658),
+ (863, 658, 659),
+ (864, 659, 660),
+ (866, 656, 661),
+ (867, 661, 662),
+ (868, 662, 617),
+ (870, 663, 658),
+ (871, 658, 664),
+ (872, 664, 652),
+ (874, 153, 663),
+ (876, 158, 154),
+ (878, 31, 13),
+ (880, 14, 665),
+ (882, 666, 621),
+ (884, 667, 666),
+ (886, 29, 667),
+ (888, 668, 5),
+ (890, 152, 659),
+ (892, 669, 670),
+ (893, 670, 671),
+ (894, 672, 233),
+ (896, 670, 245),
+ (898, 673, 674),
+ (899, 674, 675),
+ (901, 676, 273),
+ (982, 734, 735),
+ (902, 273, 238),
+ (904, 240, 673),
+ (905, 673, 675),
+ (906, 675, 677),
+ (907, 217, 678),
+ (952, 633, 679),
+ (908, 678, 680),
+ (909, 680, 681),
+ (910, 681, 682),
+ (911, 682, 683),
+ (912, 683, 684),
+ (913, 685, 686),
+ (914, 686, 687),
+ (915, 687, 688),
+ (916, 688, 689),
+ (917, 689, 690),
+ (918, 690, 691),
+ (919, 691, 692),
+ (920, 692, 693),
+ (921, 693, 694),
+ (923, 230, 695),
+ (924, 645, 696),
+ (925, 214, 697),
+ (926, 698, 699),
+ (927, 700, 701),
+ (929, 300, 702),
+ (931, 703, 704),
+ (933, 705, 565),
+ (934, 565, 706),
+ (935, 706, 306),
+ (937, 707, 678),
+ (939, 708, 709),
+ (940, 709, 710),
+ (941, 710, 711),
+ (942, 711, 712),
+ (1025, 773, 774),
+ (943, 712, 713),
+ (944, 713, 714),
+ (945, 714, 715),
+ (947, 716, 698),
+ (948, 698, 717),
+ (949, 313, 718),
+ (950, 718, 706),
+ (953, 679, 719),
+ (954, 719, 720),
+ (955, 720, 721),
+ (956, 721, 722),
+ (958, 723, 724),
+ (959, 724, 725),
+ (960, 725, 726),
+ (962, 727, 703),
+ (963, 703, 679),
+ (964, 679, 722),
+ (966, 483, 728),
+ (967, 621, 729),
+ (968, 729, 15),
+ (970, 730, 731),
+ (971, 731, 732),
+ (972, 622, 733),
+ (973, 734, 735),
+ (974, 735, 736),
+ (975, 736, 737),
+ (976, 737, 731),
+ (978, 730, 738),
+ (979, 738, 739),
+ (980, 739, 740),
+ (981, 740, 734),
+ (984, 741, 738),
+ (986, 742, 743),
+ (987, 743, 744),
+ (988, 744, 745),
+ (989, 745, 143),
+ (991, 746, 747),
+ (992, 747, 748),
+ (993, 748, 749),
+ (994, 749, 260),
+ (996, 750, 751),
+ (997, 751, 752),
+ (999, 725, 743),
+ (1000, 743, 753),
+ (1001, 754, 755),
+ (1002, 755, 756),
+ (1003, 756, 757),
+ (1004, 757, 758),
+ (1006, 759, 760),
+ (1007, 760, 761),
+ (1008, 761, 762),
+ (1010, 763, 758),
+ (1011, 758, 762),
+ (1012, 762, 764),
+ (1013, 764, 141),
+ (1015, 765, 766),
+ (1017, 767, 768),
+ (1018, 768, 769),
+ (1019, 769, 770),
+ (1020, 770, 142),
+ (1022, 771, 757),
+ (1024, 772, 773),
+ (1027, 744, 767),
+ (1028, 767, 763),
+ (1029, 763, 771),
+ (1030, 771, 765),
+ (1032, 775, 750),
+ (1033, 750, 776),
+ (1035, 724, 777),
+ (1036, 778, 779),
+ (1037, 779, 780),
+ (1039, 769, 781),
+ (1040, 779, 775),
+ (1041, 775, 782),
+ (1042, 783, 751),
+ (1044, 756, 784),
+ (1045, 755, 785),
+ (1046, 749, 786),
+ (1047, 786, 787),
+ (1049, 768, 745),
+ (1051, 770, 760),
+ (1052, 760, 788),
+ (1053, 788, 789),
+ (1055, 762, 790),
+ (1056, 790, 746),
+ (1057, 746, 263),
+ (1059, 748, 787),
+ (1060, 787, 776),
+ (1061, 776, 780),
+ (1062, 780, 754),
+ (1063, 754, 747),
+ (1065, 290, 791),
+ (1066, 674, 792),
+ (1067, 139, 793),
+ (1069, 794, 795),
+ (1111, 817, 830),
+ (1070, 795, 796),
+ (1071, 796, 737),
+ (1073, 789, 761),
+ (1075, 797, 798),
+ (1076, 264, 799),
+ (1077, 773, 800),
+ (1078, 801, 802),
+ (1079, 795, 803),
+ (1080, 804, 805),
+ (1081, 719, 806),
+ (1082, 720, 807),
+ (1083, 721, 808),
+ (1084, 808, 704),
+ (1086, 809, 808),
+ (1088, 810, 150),
+ (1090, 165, 811),
+ (1091, 811, 812),
+ (1092, 812, 813),
+ (1093, 814, 815),
+ (1094, 816, 817),
+ (1096, 818, 819),
+ (1097, 819, 820),
+ (1099, 821, 822),
+ (1101, 823, 824),
+ (1103, 825, 819),
+ (1105, 826, 827),
+ (1106, 811, 168),
+ (1108, 828, 30),
+ (1110, 829, 817),
+ (1112, 831, 828),
+ (1114, 177, 176),
+ (1116, 793, 797),
+ (1117, 797, 793),
+ (1121, 832, 528),
+ (1122, 528, 526),
+ (1123, 526, 54),
+ (1125, 833, 821),
+ (1126, 821, 822),
+ (1127, 822, 833),
+ (1129, 834, 823),
+ (1130, 823, 835),
+ (1131, 835, 834),
+ (1133, 383, 836),
+ (1134, 836, 837),
+ (1135, 837, 561),
+ (1136, 561, 554),
+ (1137, 554, 383),
+ (1139, 295, 838),
+ (1141, 299, 716),
+ (1142, 716, 623),
+ (1144, 295, 839),
+ (1456, 840, 841),
+ (1146, 625, 636),
+ (1147, 636, 668),
+ (1149, 842, 825),
+ (1150, 825, 820),
+ (1151, 820, 843),
+ (1152, 843, 844),
+ (1153, 844, 816),
+ (1237, 878, 646),
+ (1154, 816, 845),
+ (1155, 845, 846),
+ (1156, 846, 629),
+ (1157, 629, 847),
+ (1158, 847, 848),
+ (1159, 848, 849),
+ (1160, 849, 850),
+ (1161, 850, 628),
+ (1162, 628, 851),
+ (1163, 839, 847),
+ (1165, 838, 173),
+ (1167, 852, 853),
+ (1168, 853, 854),
+ (1169, 855, 415),
+ (1171, 796, 856),
+ (1172, 856, 857),
+ (1173, 857, 737),
+ (1175, 736, 857),
+ (1176, 857, 856),
+ (1178, 620, 858),
+ (1179, 858, 665),
+ (1180, 665, 12),
+ (1181, 12, 32),
+ (1182, 32, 859),
+ (1183, 859, 660),
+ (1184, 660, 664),
+ (1185, 664, 657),
+ (1186, 657, 157),
+ (1187, 157, 860),
+ (1188, 860, 861),
+ (1189, 861, 646),
+ (1190, 646, 648),
+ (1191, 648, 862),
+ (1192, 862, 294),
+ (1194, 863, 855),
+ (1195, 855, 413),
+ (1197, 413, 415),
+ (1198, 415, 863),
+ (1200, 144, 801),
+ (1201, 801, 766),
+ (1202, 766, 864),
+ (1203, 864, 752),
+ (1204, 752, 865),
+ (1205, 865, 866),
+ (1206, 866, 867),
+ (1260, 493, 868),
+ (1262, 869, 185),
+ (1263, 185, 826),
+ (1207, 867, 870),
+ (1208, 788, 871),
+ (1209, 764, 872),
+ (1210, 873, 874),
+ (1212, 790, 491),
+ (1213, 491, 267),
+ (1215, 875, 750),
+ (1217, 786, 874),
+ (1218, 874, 875),
+ (1219, 875, 876),
+ (1220, 876, 866),
+ (1222, 865, 876),
+ (1223, 876, 873),
+ (1224, 873, 867),
+ (1226, 618, 859),
+ (1228, 868, 730),
+ (1230, 730, 619),
+ (1231, 619, 858),
+ (1233, 835, 877),
+ (1234, 29, 828),
+ (1236, 647, 878),
+ (1239, 599, 435),
+ (1241, 860, 651),
+ (1242, 651, 879),
+ (1243, 879, 599),
+ (1245, 880, 881),
+ (1246, 514, 517),
+ (1247, 517, 462),
+ (1249, 861, 650),
+ (1250, 650, 879),
+ (1251, 879, 293),
+ (1253, 730, 742),
+ (1254, 742, 726),
+ (1256, 868, 492),
+ (1257, 492, 514),
+ (1259, 514, 493),
+ (1264, 826, 882),
+ (1265, 882, 883),
+ (1266, 878, 880),
+ (1268, 499, 884),
+ (1269, 884, 885),
+ (1270, 885, 460),
+ (1272, 516, 460),
+ (1274, 743, 886),
+ (1275, 729, 887),
+ (1276, 739, 740),
+ (1278, 515, 888),
+ (1279, 432, 605),
+ (1281, 577, 774),
+ (1283, 889, 890),
+ (1284, 890, 891),
+ (1285, 891, 892),
+ (1286, 892, 562),
+ (1287, 562, 893),
+ (1288, 378, 894),
+ (1289, 837, 892),
+ (1291, 836, 891),
+ (1293, 890, 895),
+ (1295, 489, 576),
+ (1297, 896, 470),
+ (1299, 502, 505),
+ (1301, 470, 472),
+ (1303, 506, 889),
+ (1304, 889, 895),
+ (1305, 895, 382),
+ (1307, 480, 804),
+ (1308, 804, 897),
+ (1309, 258, 478),
+ (1311, 482, 258),
+ (1313, 864, 778),
+ (1314, 778, 765),
+ (1539, 898, 899),
+ (1316, 900, 901),
+ (1317, 902, 903),
+ (1318, 248, 904),
+ (1319, 234, 905),
+ (1320, 174, 303),
+ (1321, 303, 814),
+ (1322, 814, 175),
+ (1323, 175, 906),
+ (1325, 846, 907),
+ (1326, 845, 133),
+ (1328, 906, 908),
+ (1329, 843, 183),
+ (1330, 183, 829),
+ (1332, 130, 909),
+ (1334, 829, 184),
+ (1335, 184, 844),
+ (1337, 850, 849),
+ (1339, 910, 911),
+ (1341, 912, 906),
+ (1343, 911, 913),
+ (1345, 174, 914),
+ (1347, 911, 848),
+ (1349, 630, 302),
+ (1351, 862, 909),
+ (1352, 909, 131),
+ (1354, 299, 910),
+ (1355, 910, 913),
+ (1356, 913, 914),
+ (1357, 914, 173),
+ (1359, 615, 632),
+ (1361, 812, 133),
+ (1363, 643, 615),
+ (1365, 638, 631),
+ (1366, 631, 915),
+ (1368, 643, 916),
+ (1370, 702, 916),
+ (1372, 916, 702),
+ (1374, 915, 642),
+ (1376, 917, 583),
+ (1377, 583, 853),
+ (1378, 853, 314),
+ (1379, 314, 918),
+ (1380, 918, 919),
+ (1381, 919, 33),
+ (1383, 397, 920),
+ (1384, 920, 341),
+ (1386, 921, 922),
+ (1387, 922, 923),
+ (1388, 923, 350),
+ (1390, 922, 924),
+ (1391, 924, 396),
+ (1393, 925, 921),
+ (1394, 921, 926),
+ (1395, 926, 927),
+ (1397, 928, 929),
+ (1455, 947, 840),
+ (1398, 929, 930),
+ (1399, 930, 923),
+ (1401, 930, 931),
+ (1402, 929, 347),
+ (1404, 932, 933),
+ (1405, 933, 926),
+ (1407, 409, 934),
+ (1408, 934, 935),
+ (1410, 936, 928),
+ (1411, 928, 932),
+ (1413, 932, 927),
+ (1414, 927, 937),
+ (1416, 937, 938),
+ (1418, 939, 935),
+ (1419, 935, 940),
+ (1420, 940, 938),
+ (1422, 348, 936),
+ (1424, 933, 921),
+ (1426, 510, 941),
+ (1427, 941, 942),
+ (1429, 941, 509),
+ (1431, 943, 852),
+ (1432, 852, 944),
+ (1433, 944, 584),
+ (1434, 584, 945),
+ (1435, 945, 946),
+ (1439, 947, 948),
+ (1440, 948, 39),
+ (1442, 949, 948),
+ (1443, 948, 40),
+ (1445, 841, 72),
+ (1447, 840, 72),
+ (1449, 950, 71),
+ (1451, 951, 952),
+ (1453, 953, 950),
+ (1454, 950, 947),
+ (1457, 841, 954),
+ (1458, 955, 956),
+ (1459, 956, 402),
+ (1461, 957, 958),
+ (1463, 958, 400),
+ (1465, 957, 959),
+ (1466, 959, 121),
+ (1468, 960, 952),
+ (1470, 335, 961),
+ (1471, 962, 87),
+ (1473, 963, 368),
+ (1475, 559, 553),
+ (1476, 553, 964),
+ (1477, 381, 552),
+ (1479, 552, 965),
+ (1481, 551, 966),
+ (1482, 966, 967),
+ (1483, 967, 968),
+ (1484, 968, 380),
+ (1486, 551, 969),
+ (1541, 898, 970),
+ (1487, 969, 486),
+ (1489, 969, 487),
+ (1491, 559, 971),
+ (1492, 966, 965),
+ (1494, 972, 967),
+ (1495, 967, 973),
+ (1496, 973, 974),
+ (1497, 974, 550),
+ (1499, 974, 973),
+ (1500, 973, 968),
+ (1502, 549, 975),
+ (1503, 975, 378),
+ (1505, 548, 976),
+ (1506, 975, 977),
+ (1507, 978, 379),
+ (1509, 507, 979),
+ (1510, 542, 980),
+ (1511, 981, 982),
+ (1513, 112, 983),
+ (1514, 984, 985),
+ (1515, 985, 398),
+ (1517, 940, 411),
+ (1518, 411, 411),
+ (1520, 986, 587),
+ (1521, 587, 987),
+ (1523, 885, 988),
+ (1524, 989, 990),
+ (1525, 990, 991),
+ (1526, 990, 992),
+ (1527, 990, 993),
+ (1528, 994, 990),
+ (1530, 990, 995),
+ (1531, 996, 709),
+ (1532, 709, 997),
+ (1533, 998, 898),
+ (1534, 898, 899),
+ (1535, 899, 970),
+ (1536, 970, 999),
+ (1537, 999, 898),
+ (1543, 898, 999),
+ (1545, 334, 1000),
+ (1546, 69, 1001),
+ (1547, 1001, 1002),
+ (1548, 1003, 1004),
+ (1550, 1005, 1006),
+ (1552, 337, 1007),
+ (1553, 69, 1008),
+ (1554, 570, 1009),
+ (1555, 1009, 1010),
+ (1556, 1011, 1012),
+ (1557, 884, 772),
+ (1559, 1013, 1014),
+ (1613, 508, 129),
+ (1560, 1014, 1015),
+ (1562, 1016, 1014),
+ (1564, 1017, 1018),
+ (1565, 581, 1019),
+ (1566, 582, 1020),
+ (1567, 78, 1021),
+ (1568, 536, 1022),
+ (1569, 1022, 73),
+ (1571, 44, 539),
+ (1573, 537, 1023),
+ (1574, 538, 1024),
+ (1575, 317, 1025),
+ (1576, 317, 1026),
+ (1577, 319, 1027),
+ (1578, 318, 944),
+ (1580, 718, 1028),
+ (1581, 126, 1029),
+ (1582, 1029, 1030),
+ (1583, 1030, 405),
+ (1584, 405, 1031),
+ (1585, 1031, 1032),
+ (1586, 1032, 1033),
+ (1588, 403, 430),
+ (1589, 430, 1034),
+ (1590, 1034, 123),
+ (1592, 1032, 1035),
+ (1593, 1035, 1036),
+ (1595, 1035, 1037),
+ (1597, 1038, 405),
+ (1599, 1039, 1030),
+ (1601, 598, 1040),
+ (1602, 1036, 1041),
+ (1604, 1042, 1043),
+ (1606, 1042, 1044),
+ (1607, 1043, 1045),
+ (1608, 1046, 1047),
+ (1610, 1046, 1048),
+ (1611, 1047, 1049),
+ (1612, 128, 508),
+ (1615, 127, 426),
+ (1617, 215, 222),
+ (1619, 223, 707),
+ (1621, 707, 224),
+ (1623, 224, 216),
+ (1625, 216, 225),
+ (1627, 226, 211),
+ (1629, 211, 220),
+ (1631, 215, 221),
+ (1633, 640, 644),
+ (1635, 49, 390),
+ (1636, 390, 1050),
+ (1637, 1050, 1051),
+ (1638, 438, 1001),
+ (1639, 1001, 569),
+ (1640, 569, 104),
+ (1641, 104, 1052),
+ (1642, 1052, 338),
+ (1643, 338, 388),
+ (1644, 388, 384),
+ (1645, 384, 982),
+ (1646, 982, 1053),
+ (1647, 1053, 389),
+ (1648, 389, 107),
+ (1649, 107, 1054),
+ (1650, 1054, 448),
+ (1651, 448, 330),
+ (1652, 330, 325),
+ (1653, 325, 393),
+ (1654, 393, 1055),
+ (1655, 1055, 943),
+ (1657, 436, 1056),
+ (1658, 1056, 1029),
+ (1659, 1029, 601),
+ (1660, 601, 1057),
+ (1661, 1057, 1034),
+ (1662, 1034, 959),
+ (1663, 959, 439),
+ (1664, 439, 421),
+ (1665, 421, 447),
+ (1666, 447, 446),
+ (1667, 446, 1054),
+ (1668, 1054, 47),
+ (1669, 47, 485),
+ (1671, 604, 1009),
+ (1672, 1009, 68),
+ (1674, 1031, 600),
+ (1675, 600, 956),
+ (1676, 956, 985),
+ (1677, 985, 340),
+ (1678, 340, 920),
+ (1679, 920, 351),
+ (1680, 351, 924),
+ (1681, 924, 1058),
+ (1682, 1058, 412),
+ (1683, 412, 1055),
+ (1684, 1055, 35),
+ (1686, 1059, 579),
+ (1687, 579, 1060),
+ (1688, 1060, 81),
+ (1690, 82, 1061),
+ (1691, 1061, 1062),
+ (1692, 1062, 484),
+ (1693, 484, 1022),
+ (1694, 1022, 42),
+ (1696, 392, 371),
+ (1697, 371, 1063),
+ (1698, 1063, 1061),
+ (1699, 1061, 80),
+ (1700, 80, 580),
+ (1701, 580, 1064),
+ (1703, 89, 1065),
+ (1704, 1065, 51),
+ (1705, 51, 1053),
+ (1707, 1052, 61),
+ (1708, 61, 513),
+ (1709, 513, 534),
+ (1710, 534, 501),
+ (1711, 501, 498),
+ (1712, 498, 1065),
+ (1713, 1065, 392),
+ (1715, 461, 572),
+ (1716, 572, 610),
+ (1717, 610, 1066),
+ (1718, 1066, 1067),
+ (1719, 1067, 1068),
+ (1720, 1068, 607),
+ (1722, 711, 1069),
+ (1723, 1069, 1070),
+ (1724, 1070, 701),
+ (1725, 701, 1071),
+ (1726, 1071, 694),
+ (1727, 694, 609),
+ (1728, 609, 1072),
+ (1729, 1072, 456),
+ (1730, 456, 1067),
+ (1772, 1073, 946),
+ (1732, 715, 1074),
+ (1733, 1074, 1075),
+ (1734, 1075, 1076),
+ (1735, 1076, 710),
+ (1737, 1068, 455),
+ (1738, 455, 1077),
+ (1739, 1077, 608),
+ (1740, 608, 693),
+ (1741, 693, 1078),
+ (1742, 1078, 712),
+ (1743, 712, 1076),
+ (1744, 1076, 1079),
+ (1745, 1079, 1080),
+ (1746, 1080, 1081),
+ (1747, 1081, 1082),
+ (1748, 1066, 457),
+ (1749, 457, 1072),
+ (1750, 1072, 1077),
+ (1752, 1083, 1075),
+ (1753, 1075, 713),
+ (1755, 714, 1074),
+ (1756, 1074, 1084),
+ (1757, 1071, 1078),
+ (1759, 1078, 1070),
+ (1760, 1070, 700),
+ (1762, 1033, 1085),
+ (1763, 1085, 310),
+ (1764, 310, 307),
+ (1765, 307, 1086),
+ (1766, 1086, 1087),
+ (1767, 1087, 986),
+ (1768, 986, 1088),
+ (1769, 1088, 1089),
+ (1770, 1089, 406),
+ (1771, 406, 1073),
+ (1773, 946, 917),
+ (1774, 917, 1090),
+ (1775, 1090, 1091),
+ (1776, 1091, 1092),
+ (1777, 1092, 1093),
+ (1778, 1093, 1094),
+ (1779, 1094, 1064),
+ (1780, 1064, 1059),
+ (1781, 1059, 1095),
+ (1782, 1095, 1096),
+ (1783, 1096, 896),
+ (1785, 395, 1058),
+ (1786, 1058, 1097),
+ (1787, 1097, 934),
+ (1788, 934, 1098),
+ (1789, 1098, 1099),
+ (1790, 1099, 320),
+ (1791, 320, 586),
+ (1792, 586, 1089),
+ (1794, 987, 588),
+ (1795, 588, 1087),
+ (1797, 1063, 85),
+ (1798, 85, 1100),
+ (1799, 1100, 353),
+ (1801, 1050, 106),
+ (1803, 1062, 1101),
+ (1804, 370, 1100),
+ (1805, 1100, 1102),
+ (1807, 1102, 1103);
+
diff --git a/src/common/src/CMakeLists.txt b/src/label_graph/test/pgrouting_brokengraph.result
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/label_graph/test/pgrouting_brokengraph.result
diff --git a/src/label_graph/test/pgrouting_brokengraph.test.sql b/src/label_graph/test/pgrouting_brokengraph.test.sql
new file mode 100644
index 0000000..f41b7f4
--- /dev/null
+++ b/src/label_graph/test/pgrouting_brokengraph.test.sql
@@ -0,0 +1,52 @@
+set client_min_messages to warning;
+SET search_path TO public;
+drop table if exists "ways";
+
+-- The following should be OK
+
+ select pgr_brokenGraph('ways');
+ select pgr_brokenGraph('Ways');
+ select pgr_brokenGraph('ways', 'id');
+ select pgr_brokenGraph('ways', 'id', 'source');
+ select pgr_brokenGraph('ways', 'id', 'source', 'target');
+ select pgr_brokenGraph('ways', 'id', 'source', 'target', 'subgraph');
+ select pgr_brokenGraph('ways', 'id', 'source', 'target', 'subgraph', 'id<100');
+
+ -- When table located in another schema e03
+ select pgr_brokenGraph('e03.ways');
+ select pgr_brokenGraph('e03.Ways');
+ select pgr_brokenGraph('e03.ways', 'id');
+ select pgr_brokenGraph('e03.ways', 'id', 'source');
+ select pgr_brokenGraph('e03.ways', 'id', 'source', 'target');
+ select pgr_brokenGraph('e03.ways', 'id', 'source', 'target', 'subgraph');
+ select pgr_brokenGraph('e03.ways', 'id', 'source', 'target', 'subgraph', 'id<100');
+
+ -- When using the named notation
+ select pgr_brokenGraph('e03.calles', target:='destino', subgraph:='subgraph', id:='gido', source:='salida');
+ select pgr_brokenGraph('e03.calles', rows_where:='gido<100', id:='gido', source:='salida', target:='destino', subgraph:='subgraph');
+
+-- The following should FAIL
+
+ select pgr_brokenGraph('id', 'ways');
+ select pgr_brokenGraph('ways', 'id', 'sourc', 'target');
+ select pgr_brokenGraph('ways', 'id', 'source', 'Target');
+ select pgr_brokenGraph('ways', 'id', 'source', 'target', 'subgraph', 'id<');
+
+ -- When table located in another schema e03
+ select pgr_brokenGraph('e03.calles');
+ select pgr_brokenGraph('e03.Calles');
+ select pgr_brokenGraph('id', 'e03.calles');
+ select pgr_brokenGraph('e03.calles', 'id', 'sourc', 'target');
+ select pgr_brokenGraph('e03.calles', 'gido', 'source', 'target', 'subgraph', 'id<');
+ select pgr_brokenGraph('e03.calles', 'gid', 'salida', 'target', 'subgraph', 'id<10');
+ select pgr_brokenGraph('e03.calles', 'gid', 'salida', 'destino', 'subgraph', 'id<10 AND id>100');
+
+ -- When using the named notation
+ select pgr_brokenGraph('e03.calles', target:='destino', subgraph:='subgraph', id:='gido');
+ select pgr_brokenGraph('e03.calles', target:='destino', subgraph:='subgraph', id:='gido', source:='salido');
+ select pgr_brokenGraph(rows_where:='gido<100', id:='gido', source:='salida', 'e03.calles', target:='destino', subgraph:='subgraph');
+
+-- The following should return "rows_where condition generated 0 rows"
+
+ select pgr_brokenGraph('ways', 'id', 'source', 'target', 'subgraph', 'id<10 AND id>100');
+ select pgr_brokenGraph('e03.calles', id:='gido', rows_where:='gido<100 AND gido>200', source:='salida', target:='destino', subgraph:='subgraph');
diff --git a/src/label_graph/test/test.conf b/src/label_graph/test/test.conf
new file mode 100644
index 0000000..021c65e
--- /dev/null
+++ b/src/label_graph/test/test.conf
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+
+%main::tests = (
+ 'any' => {
+ 'comment' => 'pgr_labelGraph tests for any versions.',
+ 'data' => [' '],
+ 'tests' => [qw(
+)],
+
+
+ },
+# 'vpg-vpgis' => {}, # for version specific tests
+# '8-1' => {}, # for pg 8.x and postgis 1.x
+# '9.2-2.1' => {}, # for pg 9.2 and postgis 2.1
+);
+
+1;
diff --git a/src/linecommand/src/Makefile b/src/linecommand/src/Makefile
new file mode 100644
index 0000000..9869da1
--- /dev/null
+++ b/src/linecommand/src/Makefile
@@ -0,0 +1,28 @@
+CC= g++
+CCFLAGS= -g -O3 -std=c++11 -Wall -pedantic
+LDFLAGS= -lboost_program_options -lpq
+INCFLAGS= -I /usr/include/postgresql/9.4/server/ -I /usr/include/postgresql/
+SOURCES= pgRouting.cpp ./../../common/src/signalhandler.cpp ./../../common/src/pgr_assert.cpp ./../../common/src/basePath_SSEC.cpp
+
+OBJECTS= $(SOURCES:.cpp=.o)
+TARGET= pgRouting
+
+all: $(OBJECTS) $(TARGET)
+
+$(TARGET): signalhandler.o pgr_assert.o pgRouting.o basePath_SSEC.o
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+$(TARGET).o: $(TARGET).cpp ./../../common/src/baseGraph.hpp ./../../common/src/pgr_types.h ./../../dijkstra/src/pgr_dijkstra.hpp ../../ksp/src/pgr_ksp.cpp ./../../common/src/basePath_SSEC.hpp
+ $(CC) $(CCFLAGS) $(INCFLAGS) -c $<
+
+%.o: %.cpp %.h
+ $(CC) $(CCFLAGS) $(INCFLAGS) -c $<
+
+%.o: %.cpp %.hpp
+ $(CC) $(CCFLAGS) $(INCFLAGS) -c $<
+
+valgrind: pgRouting
+ valgrind -v --track-origins=yes --undef-value-errors=yes --leak-check=full --show-leak-kinds=all ./mainP &> ./valgrindlog.txt
+clean:
+ rm -f *.o $(TARGET)
+
diff --git a/src/linecommand/src/dijkstra.cpp b/src/linecommand/src/dijkstra.cpp
new file mode 100644
index 0000000..eedb23b
--- /dev/null
+++ b/src/linecommand/src/dijkstra.cpp
@@ -0,0 +1,91 @@
+
+
+template <typename G>
+void process_dijkstra(G &graph, const std::vector<std::string> &tokens) {
+
+ std::string::size_type sz;
+ if (tokens[1].compare("from") != 0) {
+ std::cout << "missing 'from' kewyword\n";
+ return;
+ }
+
+ std::vector< int64_t > sources;
+ unsigned int i_ptr = 2;
+
+ for ( ; i_ptr < tokens.size(); ++i_ptr) {
+ if (tokens[i_ptr].compare("to") == 0) break;
+ try {
+ uint64_t start_vertex(stol(tokens[i_ptr], &sz));
+ sources.push_back(start_vertex);
+ } catch(...) {
+ break;
+ }
+ }
+
+ if (i_ptr == tokens.size() || tokens[i_ptr].compare("to") != 0) {
+ std::cout << "dijkstra: 'dist' kewyword not found\n";
+ return;
+ }
+
+ if (sources.size() == 0) {
+ std::cout << "dijkstra: No start value found\n";
+ return;
+ }
+
+ ++i_ptr;
+ if (i_ptr == tokens.size()) {
+ std::cout << "dijkstra: No 'to' values found\n";
+ return;
+ }
+
+ std::vector< int64_t > targets;
+ for ( ; i_ptr < tokens.size(); ++i_ptr) {
+ auto end_vertex(stol(tokens[i_ptr], &sz));
+ targets.push_back(end_vertex);
+ }
+
+
+ if (sources.size() == 1 && targets.size() == 1) {
+ // one to one
+ Path path;
+ graph.dijkstra(path, sources[0], targets[0]);
+ std::cout << "THE OPUTPUT ----> total cost: " << path.cost << "\n";
+ path.print_path();
+ path.clear();
+ } else if (sources.size() == 1 && targets.size() > 1){
+ std::deque<Path> paths;
+ // one to many
+ graph.dijkstra(paths, sources[0], targets);
+
+ std::cout << "THE OPUTPUTS ----> total outputs: " << paths.size() << "\n";
+ for (unsigned int i = 0; i < paths.size(); ++i) {
+ if (sizeof(paths[i]) == 0) continue; //no solution found
+ std::cout << "Path #" << i << " cost: " << paths[i].cost << "\n";
+ paths[i].print_path();
+ }
+ } else if (sources.size() > 1 && targets.size() == 1){
+ // many to 1
+ std::deque<Path> paths;
+ graph.dijkstra(paths, sources, targets[0]);
+
+
+ std::cout << "THE OPUTPUTS ----> total outputs: " << paths.size() << "\n";
+ for (unsigned int i = 0; i < paths.size(); ++i) {
+ if (sizeof(paths[i]) == 0) continue; //no solution found
+ std::cout << "Path #" << i << " cost: " << paths[i].cost << "\n";
+ paths[i].print_path();
+ }
+ } else {
+ //many to many
+ std::deque<Path> paths;
+ graph.dijkstra(paths, sources, targets);
+
+ std::cout << "THE OPUTPUTS ----> total outputs: " << paths.size() << "\n";
+ for (unsigned int i = 0; i < paths.size(); ++i) {
+ if (sizeof(paths[i]) == 0) continue; //no solution found
+ std::cout << "Path #" << i << " cost: " << paths[i].cost << "\n";
+ paths[i].print_path();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/linecommand/src/driving.cpp b/src/linecommand/src/driving.cpp
new file mode 100644
index 0000000..0ca5e9a
--- /dev/null
+++ b/src/linecommand/src/driving.cpp
@@ -0,0 +1,103 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+template <typename G>
+void process_drivingDistance(G &graph, const std::vector<std::string> &tokens) {
+
+ std::string::size_type sz;
+ if (tokens[1].compare("from") != 0) {
+ std::cout << "missing 'from' kewyword\n";
+ return;
+ }
+
+ std::vector< int64_t > sources;
+ unsigned int i_ptr = 2;
+
+ for ( ; i_ptr < tokens.size(); ++i_ptr) {
+ if (tokens[i_ptr].compare("dist") == 0) break;
+ try {
+ uint64_t start_vertex(stol(tokens[i_ptr], &sz));
+ sources.push_back(start_vertex);
+ } catch(...) {
+ break;
+ }
+ }
+
+ if (i_ptr == tokens.size() || tokens[i_ptr].compare("dist") != 0) {
+ std::cout << "drivDist: 'dist' kewyword not found\n";
+ return;
+ }
+
+ if (sources.size() == 0) {
+ std::cout << "drivDist: No start value found\n";
+ return;
+ }
+
+ ++i_ptr;
+ if (i_ptr == tokens.size()) {
+ std::cout << " 'distance' value not found\n";
+ return;
+ }
+
+ double distance = stod(tokens[i_ptr], &sz);
+
+ ++i_ptr;
+ bool equiCost(false);
+ if (i_ptr != tokens.size()) {
+ if (tokens[i_ptr].compare("equi") != 0) {
+ std::cout << " Unknown keyword '" << tokens[i_ptr] << "' found\n";
+ return;
+ } else {
+ equiCost = true;
+ }
+ }
+
+ std::cout << "found " << sources.size() << "starting locations\n";
+
+ if (sources.size() == 1) {
+ std::cout << "Performing pgr_DrivingDistance for single source\n";
+ Path path;
+ graph.dijkstra_dd(path, sources[0], distance);
+ std::cout << "\t\t\tTHE OPUTPUT\n";
+ std::cout << "seq\tfrom\tnode\tedge\tcost\n";
+ path.print_path();
+ } else {
+
+ std::deque< Path > paths;
+ graph.dijkstra_dd(paths, sources, distance);
+ if (equiCost == false) {
+ std::cout << "Performing pgr_DrivingDistance for multiple sources\n";
+ std::cout << "\t\t\tTHE OPUTPUT\n";
+ std::cout << "seq\tfrom\tnode\tedge\tcost\n";
+ for (const auto &path : paths) {
+ if (sizeof(path) == 0) return; //no solution found
+ path.print_path();
+ }
+ } else {
+ std::cout << "Performing pgr_DrivingDistance for multiple sources with equi-cost\n";
+ Path path = equi_cost(paths);
+ std::cout << "\t\t\tTHE EquiCost OPUTPUT\n";
+ std::cout << "seq\tfrom\tnode\tedge\tcost\n";
+ path.print_path();
+ }
+ }
+}
+
diff --git a/src/linecommand/src/pgRouting.cpp b/src/linecommand/src/pgRouting.cpp
new file mode 100644
index 0000000..60be22a
--- /dev/null
+++ b/src/linecommand/src/pgRouting.cpp
@@ -0,0 +1,415 @@
+/*PGR
+
+Copyright (c) 2015 Celia Virginia Vergara Castillo
+vicky_vergara at hotmail.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.
+
+*/
+
+/************************************************************************/
+/* $Id: MainP.cpp 65 2010-09-08 06:48:36Z yan.qi.asu $ */
+/************************************************************************/
+#include <boost/config.hpp>
+#include <string>
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+#include <boost/graph/adjacency_list.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <deque>
+#include <unistd.h>
+#include <libpq-fe.h>
+
+
+#include "postgres.h"
+#include "./../../common/src/pgr_types.h"
+#include "./../../common/src/basePath_SSEC.hpp"
+#include "./../../dijkstra/src/pgr_dijkstra.hpp"
+#include "./../../ksp/src/pgr_ksp.hpp"
+#include "./driving.cpp"
+#include "./dijkstra.cpp"
+
+
+
+/****************************************
+SIMULATES THE C CODE THAT LOADS THE DATA
+****************************************/
+void import_from_file(const std::string &input_file_name, pgr_edge_t *edges, unsigned int *count, int64_t start_vertex, int64_t end_vertex, bool &found) {
+ const char* file_name = input_file_name.c_str();
+
+ std::ifstream ifs(file_name);
+ if (!ifs) {
+ std::cerr << "The file " << file_name << " can not be opened!" << std::endl;
+ exit(1);
+ }
+
+ ifs >> (*count);
+
+ long edge_id; // , start_id, end_id;
+ //double edge_weight, reverse_weight;
+ bool s_found = false;
+ bool t_found = false;
+
+ unsigned int i = 0;
+ while (i < (*count) && ifs >> edge_id) {
+ if (edge_id == -1) break;
+ edges[i].id = edge_id;
+ ifs >> edges[i].source;
+ ifs >> edges[i].target;
+ ifs >> edges[i].cost;
+ ifs >> edges[i].reverse_cost;
+ // when loading checking if start and end are found
+ if (!s_found)
+ s_found = ((edges[i].source == start_vertex) || (edges[i].target == end_vertex));
+ if (!t_found)
+ t_found = ((edges[i].source == end_vertex) || (edges[i].target == end_vertex));
+ i++;
+ }
+ ifs.close();
+ found = s_found && t_found;
+}
+
+void get_options_description(po::options_description &od_desc) {
+ od_desc.add_options()
+ ("help", "Produce this help message.")
+ ("test,t", po::value<bool>()->default_value(false),
+ "For testing purposes.")
+ ("dbname,d", po::value<std::string>()->required(),
+ "Specifies the name of the database to connect to.")
+ ("host,h", po::value<std::string>()->default_value("localhost"),
+ "Specifies the host name of the machine on which the server is running.")
+ ("port,p", po::value<std::string>()->default_value("5432"),
+ "Port number to connect to at the server host.")
+ ("username,U", po::value<std::string>()->default_value(getlogin()),
+ "Connect to the database as the user username instead of the default.\n (You must have permission to do so, of course.)")
+ ("password,W", po::value<std::string>()->default_value(""),
+ "User's the password.\n")
+#if 0
+ ("no-password,w", po::value<bool>()->implicit_value(false),
+ "Never issue a password prompt.\n"
+ "If the server requires password authentication and a password is not available by other means such as a .pgpass file, the connection attempt will fail.\n"
+ "This option can be useful in batch jobs and scripts where no user is present to enter a password.")
+#endif
+ ;
+}
+
+
+int process_command_line(
+ po::variables_map &vm,
+ po::options_description &od_desc) {
+
+ if (vm.count("help")) {
+ std::cout << od_desc << "\n";
+ return 0;
+ }
+
+ if (vm.count("dbname"))
+ std::cout << "dbname = " << vm["dbname"].as<std::string>() << "\n";
+ else
+ std::cout << "Parameter: dbname missing\n";
+
+ if (vm.count("host"))
+ std::cout << "host = " << vm["host"].as<std::string>() << "\n";
+ else
+ std::cout << "Parameter: host missing\n";
+
+ if (vm.count("port"))
+ std::cout << "port = " << vm["port"].as<std::string>() << "\n";
+ else
+ std::cout << "Parameter: port missing\n";
+
+ if (vm.count("username"))
+ std::cout << "username = " << vm["username"].as<std::string>() << "\n";
+ else
+ std::cout << "Parameter: username missing\n";
+
+ if (vm.count("dbname") & vm.count("username") & vm.count("host")) {
+ std::cout << "Parameters: \n"
+ << vm["dbname"].as<std::string>() << "\n"
+ << vm["username"].as<std::string>() << "\n"
+ << vm["host"].as<std::string>() << ".\n";
+ return 2;
+ } else {
+ std::cout << "Missing parameter.\n";
+ std::cout << od_desc << "\n";
+ return 1;
+ }
+}
+
+
+static void
+exit_nicely(PGconn *conn)
+{
+ PQfinish(conn);
+ exit(1);
+}
+
+
+
+template <typename G>
+void process(G graph, pgr_edge_t *data_edges, int row_count) {
+ graph.initialize_graph(data_edges, row_count);
+ std::vector<int64_t> targets;
+ std::string::size_type sz;
+
+
+ // read the command and break into tokens
+ std::string cmd;
+ std::string buf;
+ std::vector<std::string> tokens;
+ while (true) {
+ std::cout << "\n\n\n\n\t\t COMMANDS\n\n "
+ << "\tDIJKSTRA\n"
+ << "(Input the command separating with spaces)\n"
+ << "\tdijkstra from to \n"
+ << "\tdijkstra from to1 to2 to3\n\n"
+ << "\tDRIVING DISTANCE\n"
+ << "(Use kewywords)\n"
+ << "\tdrivDist from <id> [<id> ...] dist <distance> [equi]\n"
+ << "\tend\n\n"
+ << ">>>";
+ tokens.clear();
+ targets.clear();
+ cmd = "";
+ std::getline(std::cin, cmd);
+ std::stringstream ss(cmd);
+ while (ss >> buf) {
+ tokens.push_back(buf);
+ }
+
+ if (tokens.size() == 0) {
+ std::cout << "No command received\n";
+ continue;
+ }
+
+ if (tokens[0].compare("end")==0) return;
+
+ if (tokens.size() < 2 ) {
+ std::cout << "Missing parameters\n";
+ continue;
+ }
+
+
+ if (tokens[0].compare("dijkstra") != 0
+ && tokens[0].compare("drivDist") != 0 ) {
+ std::cout << "Command: " << cmd << " not found\n";
+ continue;
+ }
+
+
+ if (tokens[0].compare("dijkstra") == 0) {
+ process_dijkstra(graph, tokens);
+ } else {
+#if 0
+ if (tokens[1].compare("from") == 0) {
+ std::cout << "missing 'from' kewyword";
+ }
+ start_vertex = stol(tokens[1], &sz);
+ if (tokens.size() == 2) {
+ Path path;
+ end_vertex = stol(tokens[2], &sz);
+ graph.dijkstra(path, start_vertex, end_vertex);
+ std::cout << "THE OPUTPUT ----> total cost: " << path.cost << "\n";
+ path.print_path();
+ path.clear();
+ } else {
+ std::deque<Path> paths;
+ for (unsigned int i = 2; i < tokens.size(); ++i) {
+ end_vertex = stol(tokens[i], &sz);
+ targets.push_back(end_vertex);
+ }
+
+ graph.dijkstra(paths, start_vertex, targets);
+
+ std::cout << "THE OPUTPUTS ----> total outputs: " << paths.size() << "\n";
+ for (unsigned int i = 0; i < paths.size(); ++i) {
+ if (sizeof(paths[i]) == 0) continue; //no solution found
+ std::cout << "Path #" << i << " cost: " << paths[i].cost << "\n";
+ paths[i].print_path();
+ }
+ }
+ } else if (tokens[0].compare("drivDist") == 0) {
+ #endif
+ process_drivingDistance(graph, tokens);
+ }
+ }
+}
+
+
+
+int main(int ac, char* av[]) {
+ po::options_description od_desc("Allowed options");
+ get_options_description(od_desc);
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(ac, av, od_desc), vm);
+ if (vm.count("help")) {
+ std::cout << od_desc << "\n";
+ return 0;
+ }
+
+ try{
+ po::notify(vm);
+ }
+ catch(...){
+ std::cout << od_desc << "\n";
+ return 0;
+ }
+
+ auto ret_val = process_command_line(vm, od_desc);
+ if (ret_val != 2) return ret_val;
+
+
+ auto db_dbase(vm["dbname"].as<std::string>());
+ db_dbase = "dbname = " + db_dbase;
+ auto db_host(vm["host"].as<std::string>());
+ auto db_port(vm["port"].as<std::string>());
+ auto db_username(vm["username"].as<std::string>());
+ auto db_pwd(vm["password"].as<std::string>());
+ auto test(vm["test"].as<bool>());
+ //auto db_no_pwd(vm["no-password"].as<std::string>());
+
+ const char *conninfo = db_dbase.c_str();
+ PGconn *conn;
+ PGresult *res;
+ int rec_count, col_count;
+
+
+ conn = PQconnectdb(conninfo);
+ /* Check to see that the backend connection was successfully made */
+ if (PQstatus(conn) != CONNECTION_OK)
+ {
+ fprintf(stderr, "Connection to database failed: %s",
+ PQerrorMessage(conn));
+ exit_nicely(conn);
+ exit(0);
+ }
+
+ std::string data_sql;
+ if (test) {
+ data_sql = "select id, source, target, cost, reverse_cost from edge_table order by id";
+ } else {
+ std::cout << "Input data query: ";
+ std::getline (std::cin,data_sql);
+ }
+ std::cout << "\nThe data is from:" << data_sql <<"\n";
+
+ res = PQexec(conn, data_sql.c_str());
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK) {
+ std::cout << "We did not get any data!\n";
+ exit_nicely(conn);
+ exit(1);
+ }
+
+ rec_count = PQntuples(res);
+ col_count = PQnfields(res);
+ if (col_count > 5 || col_count < 4) {
+ std::cout << "Max number of columns 5\n";
+ std::cout << "Min number of columns 4\n";
+ exit_nicely(conn);
+ exit(1);
+ }
+
+ auto id_fnum = PQfnumber(res, "id");
+ auto source_fnum = PQfnumber(res, "source");
+ auto target_fnum = PQfnumber(res, "target");
+ auto cost_fnum = PQfnumber(res, "cost");
+ auto reverse_fnum = PQfnumber(res, "reverse_cost");
+
+
+
+ pgr_edge_t *data_edges;
+ data_edges = (pgr_edge_t *) malloc(rec_count * sizeof(pgr_edge_t));
+
+
+ printf("We received %d records.\n", rec_count);
+ puts("==========================");
+
+
+
+ std::string::size_type sz;
+ std::string str;
+
+ for (int row = 0; row < rec_count; ++row) {
+ str = std::string(PQgetvalue(res, row, id_fnum));
+ data_edges[row].id = stol(str, &sz);
+
+ str = std::string(PQgetvalue(res, row, source_fnum));
+ data_edges[row].source = stol(str, &sz);
+
+ str = std::string(PQgetvalue(res, row, target_fnum));
+ data_edges[row].target = stol(str, &sz);
+
+ str = std::string(PQgetvalue(res, row, cost_fnum));
+ data_edges[row].cost = stod(str, &sz);
+
+ if (reverse_fnum != -1) {
+ str = std::string(PQgetvalue(res, row, reverse_fnum));
+ data_edges[row].reverse_cost = stod(str, &sz);
+ }
+#if 0
+ std::cout << "\tid: " << data_edges[row].id << "\t";
+ std::cout << "\tsource: " << data_edges[row].source << "\t";
+ std::cout << "\ttarget: " << data_edges[row].target << "\t";
+ std::cout << "\tcost: " << data_edges[row].cost << "\t";
+ if (reverse_fnum != -1) {
+ std::cout << "\treverse: " << data_edges[row].reverse_cost << "\t";
+ }
+ std::cout << "\n";
+#endif
+ }
+
+
+ puts("==========================");
+
+ PQclear(res);
+
+ PQfinish(conn);
+
+
+////////////////////// END READING DATA FROM DATABASE ///////////////////
+
+ std::string directed;
+ std::cout << "Is the graph directed? default[N] [Y,y]";
+ std::getline(std::cin,directed);
+ graphType gType = (directed.compare("Y")==0 || directed.compare("y")==0)? DIRECTED: UNDIRECTED;
+ bool directedFlag = (directed.compare("Y")==0 || directed.compare("y")==0)? true: false;
+
+
+
+ typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS,
+ boost_vertex_t, boost_edge_t > UndirectedGraph;
+ typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::bidirectionalS,
+ boost_vertex_t, boost_edge_t > DirectedGraph;
+
+ const int initial_size = 1;
+
+
+ Pgr_dijkstra< DirectedGraph > digraph(gType, initial_size);
+ Pgr_dijkstra< UndirectedGraph > undigraph(gType, initial_size);
+
+ if (directedFlag) {
+ process(digraph, data_edges, rec_count);
+ } else {
+ process(undigraph, data_edges, rec_count);
+ }
+}
+
+
diff --git a/src/shooting_star/sql/shooting_star.sql b/src/shooting_star/sql/shooting_star.sql
index d833255..458a811 100644
--- a/src/shooting_star/sql/shooting_star.sql
+++ b/src/shooting_star/sql/shooting_star.sql
@@ -14,7 +14,7 @@
--
-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--
diff --git a/src/shooting_star/src/shooting_star.c b/src/shooting_star/src/shooting_star.c
index 9178e50..5e761a2 100644
--- a/src/shooting_star/src/shooting_star.c
+++ b/src/shooting_star/src/shooting_star.c
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/shooting_star/src/shooting_star.h b/src/shooting_star/src/shooting_star.h
index f763348..e36fd34 100644
--- a/src/shooting_star/src/shooting_star.h
+++ b/src/shooting_star/src/shooting_star.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/shooting_star/src/shooting_star_boost_wrapper.cpp b/src/shooting_star/src/shooting_star_boost_wrapper.cpp
index a48f050..7f213bc 100644
--- a/src/shooting_star/src/shooting_star_boost_wrapper.cpp
+++ b/src/shooting_star/src/shooting_star_boost_wrapper.cpp
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/shooting_star/test/spss-any-00.test b/src/shooting_star/test/spss-any-00.test.sql
similarity index 100%
rename from src/shooting_star/test/spss-any-00.test
rename to src/shooting_star/test/spss-any-00.test.sql
diff --git a/src/shooting_star/test/spss-any-01.test b/src/shooting_star/test/spss-any-01.test.sql
similarity index 100%
rename from src/shooting_star/test/spss-any-01.test
rename to src/shooting_star/test/spss-any-01.test.sql
diff --git a/src/trsp/doc/index.rst b/src/trsp/doc/index.rst
index 084e268..28528bc 100644
--- a/src/trsp/doc/index.rst
+++ b/src/trsp/doc/index.rst
@@ -15,8 +15,8 @@ pgr_trsp - Turn Restriction Shortest Path (TRSP)
.. index::
single: pgr_trsp(text,integer,integer,boolean,boolean)
single: pgr_trsp(text,integer,integer,boolean,boolean,text)
- single: pgr_trsp(text,integer,double precision,integer,double precision,boolean,boolean)
- single: pgr_trsp(text,integer,double precision,integer,double precision,boolean,boolean,text)
+ single: pgr_trspViaVertices(text,integer,double precision,integer,double precision,boolean,boolean)
+ single: pgr_trspViaEdges(text,integer,double precision,integer,double precision,boolean,boolean,text)
module: trsp
Name
@@ -33,22 +33,33 @@ The turn restricted shorthest path (TRSP) is a shortest path algorithm that can
.. code-block:: sql
pgr_costResult[] pgr_trsp(sql text, source integer, target integer,
- directed boolean, has_rcost boolean [,restrict_sql text]);
+ directed boolean, has_rcost boolean [,restrict_sql text]);
.. code-block:: sql
- pgr_costResult[] pgr_trsp(sql text, source_edge integer, source_pos double precision,
- target_edge integer, target_pos double precision, directed boolean,
- has_rcost boolean [,restrict_sql text]);
+ pgr_costResult[] pgr_trsp(sql text, source_edge integer, source_pos float8,
+ target_edge integer, target_pos float8,
+ directed boolean, has_rcost boolean [,restrict_sql text]);
+.. code-block:: sql
+
+ pgr_costResult3[] pgr_trspViaVertices(sql text, vids integer[],
+ directed boolean, has_reverse_cost boolean
+ [, turn_restrict_sql text]);
+
+.. code-block:: sql
+
+ pgr_costResult3[] pgr_trspViaEdges(sql text, eids integer[], pcts float8[],
+ directed boolean, has_reverse_cost boolean
+ [, turn_restrict_sql text]);
Description
-------------------------------------------------------------------------------
The Turn Restricted Shortest Path algorithm (TRSP) is similar to the :ref:`shooting_star` in that you can specify turn restrictions.
-The TRSP setup is mostly the same as :ref:`Dijkstra shortest path <pgr_dijkstra>` with the addition of an optional turn restriction table. This makes adding turn restrictions to a road network much easier than trying to add them to Shooting Star where you had to ad the same edges multiple times if it was involved in a restriction.
+The TRSP setup is mostly the same as :ref:`Dijkstra shortest path <pgr_dijkstra>` with the addition of an optional turn restriction table. This provides an easy way of adding turn restrictions to a road network by placing them in a separate table.
:sql: a SQL query, which should return a set of rows with the following columns:
@@ -93,11 +104,64 @@ Returns set of :ref:`type_cost_result`:
:id2: edge ID (``-1`` for the last row)
:cost: cost to traverse from ``id1`` using ``id2``
-
.. rubric:: History
* New in version 2.0.0
+Support for Vias
+--------------------------------------------------------------------
+
+.. warning:: The Support for Vias functions are prototypes. Not all corner cases are being considered.
+
+
+We also have support for vias where you can say generate a from A to B to C, etc. We support both methods above only you pass an array of vertices or and array of edges and percentage position along the edge in two arrays.
+
+
+
+:sql: a SQL query, which should return a set of rows with the following columns:
+
+ .. code-block:: sql
+
+ SELECT id, source, target, cost, [,reverse_cost] FROM edge_table
+
+
+ :id: ``int4`` identifier of the edge
+ :source: ``int4`` identifier of the source vertex
+ :target: ``int4`` identifier of the target vertex
+ :cost: ``float8`` value, of the edge traversal cost. A negative cost will prevent the edge from being inserted in the graph.
+ :reverse_cost: (optional) the cost for the reverse traversal of the edge. This is only used when the ``directed`` and ``has_rcost`` parameters are ``true`` (see the above remark about negative costs).
+
+:vids: ``int4[]`` An ordered array of **NODE id** the path will go through from start to end.
+:directed: ``true`` if the graph is directed
+:has_rcost: if ``true``, the ``reverse_cost`` column of the SQL generated set of rows will be used for the cost of the traversal of the edge in the opposite direction.
+
+:restrict_sql: (optional) a SQL query, which should return a set of rows with the following columns:
+
+ .. code-block:: sql
+
+ SELECT to_cost, target_id, via_path FROM restrictions
+
+ :to_cost: ``float8`` turn restriction cost
+ :target_id: ``int4`` target id
+ :via_path: ``text`` commar seperated list of edges in the reverse order of ``rule``
+
+Another variant of TRSP allows to specify **EDGE id** together with a fraction to interpolate the position:
+
+:eids: ``int4`` An ordered array of **EDGE id** that the path has to traverse
+:pcts: ``float8`` An array of fractional positions along the respective edges in ``eids``, where 0.0 is the start of the edge and 1.0 is the end of the eadge.
+
+Returns set of :ref:`type_cost_result`:
+
+:seq: row sequence
+:id1: route ID
+:id2: node ID
+:id3: edge ID (``-1`` for the last row)
+:cost: cost to traverse from ``id2`` using ``id3``
+
+
+.. rubric:: History
+
+* Via Support prototypes new in version 2.1.0
Examples
-------------------------------------------------------------------------------
@@ -164,6 +228,71 @@ Then a query with turn restrictions is created as:
5 | 12 | -1 | 0
(6 rows)
+An example query using vertex ids and via points:
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_trspViaVertices(
+ 'SELECT id, source::INTEGER, target::INTEGER, cost,
+ reverse_cost FROM edge_table',
+ ARRAY[1,8,13,5]::INTEGER[],
+ true,
+ true,
+
+ 'SELECT to_cost, to_edge AS target_id, FROM_edge ||
+ coalesce('',''||via,'''') AS via_path FROM restrictions');
+
+ seq | id1 | id2 | id3 | cost
+ -----+-----+-----+-----+------
+ 1 | 1 | 1 | 1 | 1
+ 2 | 1 | 2 | 4 | 1
+ 3 | 1 | 5 | 8 | 1
+ 4 | 1 | 6 | 9 | 1
+ 5 | 1 | 9 | 16 | 1
+ 6 | 1 | 4 | 3 | 1
+ 7 | 1 | 3 | 5 | 1
+ 8 | 1 | 6 | 8 | 1
+ 9 | 1 | 5 | 7 | 1
+ 10 | 2 | 8 | 7 | 1
+ 11 | 2 | 5 | 10 | 1
+ 12 | 2 | 10 | 14 | 1
+ 13 | 3 | 13 | 14 | 1
+ 14 | 3 | 10 | 10 | 1
+ 15 | 3 | 5 | -1 | 0
+ (15 rows)
+
+
+
+An example query using edge ids and vias:
+
+.. code-block:: sql
+
+ SELECT * FROM pgr_trspViaEdges(
+ 'SELECT id, source::INTEGER, target::INTEGER,cost,
+ reverse_cost FROM edge_table',
+ ARRAY[1,11,6]::INTEGER[],
+ ARRAY[0.5, 0.5, 0.5]::FLOAT8[],
+ true,
+ true,
+
+ 'SELECT to_cost, to_edge AS target_id, FROM_edge ||
+ coalesce('',''||via,'''') AS via_path FROM restrictions');
+
+ seq | id1 | id2 | id3 | cost
+ -----+-----+-----+-----+------
+ 1 | 1 | -1 | 1 | 0.5
+ 2 | 1 | 2 | 4 | 1
+ 3 | 1 | 5 | 8 | 1
+ 4 | 1 | 6 | 11 | 1
+ 5 | 2 | 11 | 13 | 1
+ 6 | 2 | 12 | 15 | 1
+ 7 | 2 | 9 | 9 | 1
+ 8 | 2 | 6 | 8 | 1
+ 9 | 2 | 5 | 7 | 1
+ 10 | 2 | 8 | 6 | 0.5
+ (10 rows)
+
+
The queries use the :ref:`sampledata` network.
diff --git a/src/trsp/sql/CMakeLists.txt b/src/trsp/sql/CMakeLists.txt
index 51cab19..41d44e4 100644
--- a/src/trsp/sql/CMakeLists.txt
+++ b/src/trsp/sql/CMakeLists.txt
@@ -1,6 +1,8 @@
# Append in local scope
list(APPEND PACKAGE_SQL_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/routing_trsp.sql)
+ ${CMAKE_CURRENT_SOURCE_DIR}/routing_trsp.sql
+ ${CMAKE_CURRENT_SOURCE_DIR}/routing_trsp_vias.sql
+ )
# set in parent scope
set(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
diff --git a/src/trsp/sql/routing_trsp.sql b/src/trsp/sql/routing_trsp.sql
index d7dd55c..62e0088 100644
--- a/src/trsp/sql/routing_trsp.sql
+++ b/src/trsp/sql/routing_trsp.sql
@@ -13,7 +13,7 @@ CREATE OR REPLACE FUNCTION pgr_trsp(
has_reverse_cost boolean,
turn_restrict_sql text DEFAULT null)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting', 'turn_restrict_shortest_path_vertex'
+ AS '$libdir/librouting-2.1', 'turn_restrict_shortest_path_vertex'
LANGUAGE 'c' IMMUTABLE;
CREATE OR REPLACE FUNCTION pgr_trsp(
@@ -26,6 +26,6 @@ CREATE OR REPLACE FUNCTION pgr_trsp(
has_reverse_cost boolean,
turn_restrict_sql text DEFAULT null)
RETURNS SETOF pgr_costResult
- AS '$libdir/librouting', 'turn_restrict_shortest_path_edge'
+ AS '$libdir/librouting-2.1', 'turn_restrict_shortest_path_edge'
LANGUAGE 'c' IMMUTABLE;
diff --git a/src/trsp/sql/routing_trsp_vias.sql b/src/trsp/sql/routing_trsp_vias.sql
new file mode 100644
index 0000000..76473c7
--- /dev/null
+++ b/src/trsp/sql/routing_trsp_vias.sql
@@ -0,0 +1,168 @@
+create or replace function pgr_trspViaVertices(sql text, vids integer[], directed boolean, has_reverse_cost boolean, turn_restrict_sql text DEFAULT NULL::text)
+ RETURNS SETOF pgr_costresult3 AS
+$body$
+/*
+ * pgr_trsp(sql text, vids integer[], directed boolean, has_reverse_cost boolean, turn_restrict_sql text DEFAULT NULL::text)
+ *
+ * Compute TRSP with via points. We compute the path between vids[i] and vids[i+1] and chain the results together.
+ *
+ * NOTE: this is a prototype function, we can gain a lot of efficiencies by implementing this in C/C++
+ *
+*/
+declare
+ i integer;
+ rr pgr_costresult3;
+ lrr pgr_costresult3;
+ lrra boolean := false;
+ seq integer := 0;
+ seq2 integer := 0;
+
+begin
+ -- loop through each pair of vids and compute the path
+ for i in 1 .. array_length(vids, 1)-1 loop
+ seq2 := seq2 + 1;
+ for rr in select a.seq, seq2 as id1, a.id1 as id2, a.id2 as id3, a.cost
+ from pgr_trsp(sql, vids[i], vids[i+1], directed, has_reverse_cost, turn_restrict_sql) as a loop
+ -- filter out the individual path ends except the last one
+ -- we might not want to do this so we can know where the via points are in the path result
+ -- but this needs more thought
+ --raise notice 'rr: %', rr;
+ if rr.id3 = -1 then
+ lrr := rr;
+ lrra := true;
+ else
+ seq := seq + 1;
+ rr.seq := seq;
+ return next rr;
+ end if;
+ end loop;
+ end loop;
+
+ if lrra then
+ seq := seq + 1;
+ lrr.seq := seq;
+ return next lrr;
+ end if;
+ return;
+end;
+$body$
+ language plpgsql stable
+ cost 100
+ rows 1000;
+
+
+
+
+----------------------------------------------------------------------------------------------------------
+
+create or replace function pgr_trspViaEdges(sql text, eids integer[], pcts float8[], directed boolean, has_reverse_cost boolean, turn_restrict_sql text DEFAULT NULL::text)
+ RETURNS SETOF pgr_costresult3 AS
+$body$
+/*
+ * pgr_trsp(sql text, eids integer[], pcts float8[], directed boolean, has_reverse_cost boolean, turn_restrict_sql text DEFAULT NULL::text)
+ *
+ * Compute TRSP with edge_ids and pposition along edge. We compute the path between eids[i], pcts[i] and eids[i+1], pcts[i+1]
+ * and chain the results together.
+ *
+ * NOTE: this is a prototype function, we can gain a lot of efficiencies by implementing this in C/C++
+ *
+*/
+declare
+ i integer;
+ rr pgr_costresult3;
+ lrr pgr_costresult3;
+ first boolean := true;
+ seq integer := 0;
+ seq2 integer :=0;
+
+begin
+ if array_length(eids, 1) != array_length(pcts, 1) then
+ raise exception 'The length of arrays eids and pcts must be the same!';
+ end if;
+
+ -- loop through each pair of vids and compute the path
+ for i in 1 .. array_length(eids, 1)-1 loop
+ seq2 := seq2 + 1;
+ for rr in select a.seq, seq2 as id1, a.id1 as id2, a.id2 as id3, a.cost
+ from pgr_trsp(sql,
+ eids[i], pcts[i],
+ eids[i+1], pcts[i+1],
+ directed,
+ has_reverse_cost,
+ turn_restrict_sql) as a loop
+ -- combine intermediate via costs when cost is split across
+ -- two parts of a segment because it stops it and
+ -- restarts the next leg also on it
+ -- we might not want to do this so we can know where the via points are in the path result
+ -- but this needs more thought
+ --
+ -- there are multiple condition we have to deal with
+ -- between the end of one leg and start of the next
+ -- 1. same vertex_id. edge_id=-1; drop record with edge_id=-1
+ -- means: path ends on vertex
+ -- NOTICE: rr: (19,1,44570022,-1,0)
+ -- NOTICE: rr: (0,2,44570022,1768045,2.89691196717448)
+ -- 2. vertex_id=-1; sum cost components
+ -- means: path end/starts with the segment
+ -- NOTICE: rr: (11,2,44569628,1775909,9.32885885148532)
+ -- NOTICE: rr: (0,3,-1,1775909,0.771386350984395)
+
+ --raise notice 'rr: %', rr;
+ if first then
+ lrr := rr;
+ first := false;
+ else
+ if lrr.id3 = -1 then
+ lrr := rr;
+ elsif lrr.id3 = rr.id3 then
+ lrr.cost := lrr.cost + rr.cost;
+ if rr.id2 = -1 then
+ rr.id2 := lrr.id2;
+ end if;
+ else
+ seq := seq + 1;
+ lrr.seq := seq;
+ return next lrr;
+ lrr := rr;
+ end if;
+ end if;
+ end loop;
+ end loop;
+
+ seq := seq + 1;
+ lrr.seq := seq;
+ return next lrr;
+ return;
+end;
+$body$
+ language plpgsql stable
+ cost 100
+ rows 1000;
+
+
+----------------------------------------------------------------------------------------------------------
+/*this via functions are not documented they will be deleted on 2.2*/
+
+create or replace function pgr_trsp(sql text, vids integer[], directed boolean, has_reverse_cost boolean, turn_restrict_sql text DEFAULT NULL::text)
+ RETURNS SETOF pgr_costresult AS
+$body$
+begin
+ return query select seq, id2 as id1, id3 as id2, cost from pgr_trspVia( sql, vids, directed, has_reverse_cost, turn_restrict_sql);
+end;
+$body$
+ language plpgsql stable
+ cost 100
+ rows 1000;
+
+
+
+create or replace function pgr_trsp(sql text, eids integer[], pcts float8[], directed boolean, has_reverse_cost boolean, turn_restrict_sql text DEFAULT NULL::text)
+ RETURNS SETOF pgr_costresult AS
+$body$
+begin
+ return query select seq, id2 as id1, id3 as id2, cost from pgr_trspVia(sql, eids, pcts, directed, has_reverse_cost, turn_restrict_sql);
+end;
+$body$
+ language plpgsql stable
+ cost 100
+ rows 1000;
diff --git a/src/trsp/src/GraphDefinition.cpp b/src/trsp/src/GraphDefinition.cpp
old mode 100644
new mode 100755
index d7a97be..3b91d4b
--- a/src/trsp/src/GraphDefinition.cpp
+++ b/src/trsp/src/GraphDefinition.cpp
@@ -1,23 +1,43 @@
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
#include "GraphDefinition.h"
+// -------------------------------------------------------------------------
GraphDefinition::GraphDefinition(void)
{
- m_bIsturnRestrictOn = false;
- m_bIsGraphConstructed = false;
+ m_lStartEdgeId = -1;
+ m_lEndEdgeId = 0;
+ m_dStartpart = 0.0;
+ m_dEndPart = 0.0;
+ m_dCost = NULL;
+ m_bIsturnRestrictOn = false;
+ m_bIsGraphConstructed = false;
+ parent = NULL;
+ init();
}
+// -------------------------------------------------------------------------
GraphDefinition::~GraphDefinition(void)
{
}
+
+// -------------------------------------------------------------------------
void GraphDefinition::init()
{
- max_edge_id = 0;
- max_node_id = 0;
- isStartVirtual = false;
- isEndVirtual = false;
+ max_edge_id = 0;
+ max_node_id = 0;
+ isStartVirtual = false;
+ isEndVirtual = false;
}
+
+// -------------------------------------------------------------------------
void GraphDefinition::deleteall()
{
std::vector<GraphEdgeInfo*>::iterator it;
@@ -30,617 +50,850 @@ void GraphDefinition::deleteall()
delete [] m_dCost;
}
+
+// -------------------------------------------------------------------------
double GraphDefinition::construct_path(int ed_id, int v_pos)
{
- if(parent[ed_id].ed_ind[v_pos] == -1)
- {
- path_element_t pelement;
- GraphEdgeInfo* cur_edge = m_vecEdgeVector[ed_id];
- if(v_pos == 0)
- {
- pelement.vertex_id = cur_edge->m_lStartNode;
- pelement.cost = cur_edge->m_dCost;
- }
- else
- {
- pelement.vertex_id = cur_edge->m_lEndNode;
- pelement.cost = cur_edge->m_dReverseCost;
- }
- pelement.edge_id = cur_edge->m_lEdgeID;
-
- m_vecPath.push_back(pelement);
- return pelement.cost;
- }
- double ret = construct_path(parent[ed_id].ed_ind[v_pos], parent[ed_id].v_pos[v_pos]);
- path_element_t pelement;
- GraphEdgeInfo* cur_edge = m_vecEdgeVector[ed_id];
- if(v_pos == 0)
- {
- pelement.vertex_id = cur_edge->m_lStartNode;
- pelement.cost = m_dCost[ed_id].endCost - ret;// cur_edge.m_dCost;
- ret = m_dCost[ed_id].endCost;
- }
- else
- {
- pelement.vertex_id = cur_edge->m_lEndNode;
- pelement.cost = m_dCost[ed_id].startCost - ret;
- ret = m_dCost[ed_id].startCost;
- }
- pelement.edge_id = cur_edge->m_lEdgeID;
-
- m_vecPath.push_back(pelement);
-
- return ret;
+ if(parent[ed_id].ed_ind[v_pos] == -1)
+ {
+ path_element_t pelement;
+ GraphEdgeInfo* cur_edge = m_vecEdgeVector[ed_id];
+ if(v_pos == 0)
+ {
+ pelement.vertex_id = cur_edge->m_lStartNode;
+ pelement.cost = cur_edge->m_dCost;
+ }
+ else
+ {
+ pelement.vertex_id = cur_edge->m_lEndNode;
+ pelement.cost = cur_edge->m_dReverseCost;
+ }
+ pelement.edge_id = cur_edge->m_lEdgeID;
+
+ m_vecPath.push_back(pelement);
+ return pelement.cost;
+ }
+ double ret = construct_path(parent[ed_id].ed_ind[v_pos], parent[ed_id].v_pos[v_pos]);
+ path_element_t pelement;
+ GraphEdgeInfo* cur_edge = m_vecEdgeVector[ed_id];
+ if(v_pos == 0)
+ {
+ pelement.vertex_id = cur_edge->m_lStartNode;
+ pelement.cost = m_dCost[ed_id].endCost - ret;// cur_edge.m_dCost;
+ ret = m_dCost[ed_id].endCost;
+ }
+ else
+ {
+ pelement.vertex_id = cur_edge->m_lEndNode;
+ pelement.cost = m_dCost[ed_id].startCost - ret;
+ ret = m_dCost[ed_id].startCost;
+ }
+ pelement.edge_id = cur_edge->m_lEdgeID;
+
+ m_vecPath.push_back(pelement);
+
+ return ret;
}
-double GraphDefinition::getRestrictionCost(int edge_ind, GraphEdgeInfo& new_edge, bool isStart)
+
+// -------------------------------------------------------------------------
+double GraphDefinition::getRestrictionCost(
+ int edge_ind,
+ GraphEdgeInfo& new_edge,
+ bool isStart)
{
- double cost = 0.0;
- int edge_id = new_edge.m_lEdgeID;
- if(m_ruleTable.find(edge_id) == m_ruleTable.end())
- {
- return(0.0);
- }
- std::vector<Rule> vecRules = m_ruleTable[edge_id];
- int ruleIndex;
- int totalRule = vecRules.size();
- int st_edge_ind = edge_ind;
- for(ruleIndex = 0; ruleIndex < totalRule; ruleIndex++)
- {
- bool flag = true;
- int total_edge = vecRules[ruleIndex].precedencelist.size();
- int i;
- int v_pos = (isStart?0:1);
- edge_ind = st_edge_ind;
- for(i = 0; i < total_edge; i++)
- {
- if(edge_ind == -1)
- {
- flag = false;
- break;
- }
- if(vecRules[ruleIndex].precedencelist[i] != m_vecEdgeVector[edge_ind]->m_lEdgeID)
- {
- flag = false;
- break;
- }
- int parent_ind = parent[edge_ind].ed_ind[v_pos];
- v_pos = parent[edge_ind].v_pos[v_pos];
- edge_ind = parent_ind;
- }
- if(flag)
- cost += vecRules[ruleIndex].cost;
- }
- return cost;
+ double cost = 0.0;
+ int edge_id = new_edge.m_lEdgeID;
+ if(m_ruleTable.find(edge_id) == m_ruleTable.end())
+ {
+ return(0.0);
+ }
+ std::vector<Rule> vecRules = m_ruleTable[edge_id];
+ int ruleIndex;
+ int totalRule = vecRules.size();
+ int st_edge_ind = edge_ind;
+ for(ruleIndex = 0; ruleIndex < totalRule; ruleIndex++)
+ {
+ bool flag = true;
+ int total_edge = vecRules[ruleIndex].precedencelist.size();
+ int i;
+ int v_pos = (isStart?0:1);
+ edge_ind = st_edge_ind;
+ for(i = 0; i < total_edge; i++)
+ {
+ if(edge_ind == -1)
+ {
+ flag = false;
+ break;
+ }
+ if(vecRules[ruleIndex].precedencelist[i] != m_vecEdgeVector[edge_ind]->m_lEdgeID)
+ {
+ flag = false;
+ break;
+ }
+ int parent_ind = parent[edge_ind].ed_ind[v_pos];
+ v_pos = parent[edge_ind].v_pos[v_pos];
+ edge_ind = parent_ind;
+ }
+ if(flag)
+ cost += vecRules[ruleIndex].cost;
+ }
+ return cost;
}
-void GraphDefinition::explore(int cur_node, GraphEdgeInfo& cur_edge, bool isStart, LongVector &vecIndex, std::priority_queue<PDP, std::vector<PDP>, std::greater<PDP> > &que)
+
+// -------------------------------------------------------------------------
+void GraphDefinition::explore(
+ int cur_node,
+ GraphEdgeInfo& cur_edge,
+ bool isStart,
+ LongVector &vecIndex,
+ std::priority_queue<PDP, std::vector<PDP>,
+ std::greater<PDP> > &que)
{
- int i;
- double extCost = 0.0;
- GraphEdgeInfo* new_edge;
- int new_node;
- double totalCost;
- for(i = 0; i < vecIndex.size(); i++)
- {
- new_edge = m_vecEdgeVector[vecIndex[i]];
- extCost = 0.0;
- if(m_bIsturnRestrictOn)
- {
- extCost = getRestrictionCost(cur_edge.m_lEdgeIndex, *new_edge, isStart);
- }
- if(new_edge->m_lStartNode == cur_node)
- {
- if(new_edge->m_dCost >= 0.0)
- {
- new_node = new_edge->m_lEndNode;
-
- if(isStart)
- totalCost = m_dCost[cur_edge.m_lEdgeIndex].endCost + new_edge->m_dCost + extCost;
- else
- totalCost = m_dCost[cur_edge.m_lEdgeIndex].startCost + new_edge->m_dCost + extCost;
- if(totalCost < m_dCost[vecIndex[i]].endCost)
- {
- m_dCost[vecIndex[i]].endCost = totalCost;
- parent[new_edge->m_lEdgeIndex].v_pos[0] = (isStart?0:1);
- parent[new_edge->m_lEdgeIndex].ed_ind[0] = cur_edge.m_lEdgeIndex;
- que.push(std::make_pair(totalCost, std::make_pair(new_edge->m_lEdgeIndex, true)));
- }
- }
- }
- else
- {
- if(new_edge->m_dReverseCost >= 0.0)
- {
- new_node = new_edge->m_lStartNode;
- if(isStart)
- totalCost = m_dCost[cur_edge.m_lEdgeIndex].endCost + new_edge->m_dReverseCost + extCost;
- else
- totalCost = m_dCost[cur_edge.m_lEdgeIndex].startCost + new_edge->m_dReverseCost + extCost;
- if(totalCost < m_dCost[vecIndex[i]].startCost)
- {
- m_dCost[vecIndex[i]].startCost = totalCost;
- parent[new_edge->m_lEdgeIndex].v_pos[1] = (isStart?0:1);
- parent[new_edge->m_lEdgeIndex].ed_ind[1] = cur_edge.m_lEdgeIndex;
- que.push(std::make_pair(totalCost, std::make_pair(new_edge->m_lEdgeIndex, false)));
- }
- }
- }
- }
+ unsigned int i;
+ double extCost = 0.0;
+ GraphEdgeInfo* new_edge;
+ // int new_node;
+ double totalCost;
+ for(i = 0; i < vecIndex.size(); i++)
+ {
+ new_edge = m_vecEdgeVector[vecIndex[i]];
+ extCost = 0.0;
+ if(m_bIsturnRestrictOn)
+ {
+ extCost = getRestrictionCost(cur_edge.m_lEdgeIndex, *new_edge, isStart);
+ }
+ if(new_edge->m_lStartNode == cur_node)
+ {
+ if(new_edge->m_dCost >= 0.0)
+ {
+ //new_node = new_edge->m_lEndNode;
+
+ if(isStart)
+ totalCost = m_dCost[cur_edge.m_lEdgeIndex].endCost + new_edge->m_dCost + extCost;
+ else
+ totalCost = m_dCost[cur_edge.m_lEdgeIndex].startCost + new_edge->m_dCost + extCost;
+ if(totalCost < m_dCost[vecIndex[i]].endCost)
+ {
+ m_dCost[vecIndex[i]].endCost = totalCost;
+ parent[new_edge->m_lEdgeIndex].v_pos[0] = (isStart?0:1);
+ parent[new_edge->m_lEdgeIndex].ed_ind[0] = cur_edge.m_lEdgeIndex;
+ que.push(std::make_pair(totalCost, std::make_pair(new_edge->m_lEdgeIndex, true)));
+ }
+ }
+ }
+ else
+ {
+ if(new_edge->m_dReverseCost >= 0.0)
+ {
+ // new_node = new_edge->m_lStartNode;
+ if(isStart)
+ totalCost = m_dCost[cur_edge.m_lEdgeIndex].endCost + new_edge->m_dReverseCost + extCost;
+ else
+ totalCost = m_dCost[cur_edge.m_lEdgeIndex].startCost + new_edge->m_dReverseCost + extCost;
+ if(totalCost < m_dCost[vecIndex[i]].startCost)
+ {
+ m_dCost[vecIndex[i]].startCost = totalCost;
+ parent[new_edge->m_lEdgeIndex].v_pos[1] = (isStart?0:1);
+ parent[new_edge->m_lEdgeIndex].ed_ind[1] = cur_edge.m_lEdgeIndex;
+ que.push(std::make_pair(totalCost, std::make_pair(new_edge->m_lEdgeIndex, false)));
+ }
+ }
+ }
+ }
}
-int GraphDefinition::my_dijkstra(edge_t *edges, unsigned int edge_count, int start_edge_id, double start_part, int end_edge_id, double end_part,
- path_element_t **path, int *path_count, char **err_msg, std::vector<PDVI> &ruleList)
+
+// -------------------------------------------------------------------------
+int GraphDefinition::multi_dijkstra(
+ edge_t *edges,
+ unsigned int edge_count,
+ std::vector<int> vertices,
+ bool directed,
+ bool has_reverse_cost,
+ path_element_t **path,
+ int *path_count,
+ char **err_msg,
+ std::vector<PDVI> &ruleList)
{
- if(!m_bIsGraphConstructed)
- {
- init();
- construct_graph(edges, edge_count);
- m_bIsGraphConstructed = true;
- }
- GraphEdgeInfo* start_edge_info = m_vecEdgeVector[m_mapEdgeId2Index[start_edge_id]];
- edge_t start_edge;
- int start_vertex, end_vertex;
- m_dStartpart = start_part;
- m_dEndPart = end_part;
- m_lStartEdgeId = start_edge_id;
- m_lEndEdgeId = end_edge_id;
-
- if(start_part == 0.0)
- {
- start_vertex = start_edge_info->m_lStartNode;
- }
- else if(start_part == 1.0)
- {
- start_vertex = start_edge_info->m_lEndNode;
- }
- else
- {
- isStartVirtual = true;
- m_lStartEdgeId = start_edge_id;
- start_vertex = max_node_id + 1;
- max_node_id++;
- start_edge.id = max_edge_id + 1;
- max_edge_id++;
- start_edge.source = start_vertex;
- start_edge.reverse_cost = -1.0;
- if(start_edge_info->m_dCost >= 0.0)
- {
- start_edge.target = start_edge_info->m_lEndNode;
- start_edge.cost = (1.0 - start_part) * start_edge_info->m_dCost;
- addEdge(start_edge);
- edge_count++;
- }
- if(start_edge_info->m_dReverseCost >= 0.0)
- {
- start_edge.id = max_edge_id + 1;
- max_edge_id++;
- start_edge.target = start_edge_info->m_lStartNode;
- start_edge.cost = start_part * start_edge_info->m_dReverseCost;
- addEdge(start_edge);
- edge_count++;
- }
- }
-
- GraphEdgeInfo* end_edge_info = m_vecEdgeVector[m_mapEdgeId2Index[end_edge_id]];
- edge_t end_edge;
-
- if(end_part == 0.0)
- {
- end_vertex = end_edge_info->m_lStartNode;
- }
- else if(end_part == 1.0)
- {
- end_vertex = end_edge_info->m_lEndNode;
- }
- else
- {
- isEndVirtual = true;
- m_lEndEdgeId = end_edge_id;
- end_vertex = max_node_id + 1;
- max_node_id++;
- end_edge.id = max_edge_id + 1;
- max_edge_id++;
- end_edge.target = end_vertex;
- end_edge.reverse_cost = -1.0;
- if(end_edge_info->m_dCost >= 0.0)
- {
- end_edge.source = end_edge_info->m_lStartNode;
- end_edge.cost = end_part * end_edge_info->m_dCost;
- addEdge(end_edge);
- edge_count++;
- }
- if(end_edge_info->m_dReverseCost >= 0.0)
- {
- end_edge.source = end_edge_info->m_lEndNode;
- end_edge.id = max_edge_id + 1;
- end_edge.cost = (1.0 - end_part) * end_edge_info->m_dReverseCost;
- addEdge(end_edge);
- edge_count++;
- }
- }
-
- return(my_dijkstra(edges, edge_count, start_vertex, end_vertex, path, path_count, err_msg, ruleList));
+ construct_graph(edges, edge_count, has_reverse_cost, directed);
+ if(ruleList.size() > 0)
+ {
+ m_ruleTable.clear();
+ int total_rule = ruleList.size();
+ int i;
+ LongVector vecsource;
+ // int kk;
+ for(i = 0; i < total_rule; i++)
+ {
+ Rule rule;
+ rule.cost = ruleList[i].first;
+ int j;
+ int seq_cnt = ruleList[i].second.size();
+ for(j = 1; j < seq_cnt; j++)
+ {
+ rule.precedencelist.push_back(ruleList[i].second[j]);
+ }
+ int dest_edge_id = ruleList[i].second[0];
+ if(m_ruleTable.find(dest_edge_id) != m_ruleTable.end())
+ {
+ m_ruleTable[dest_edge_id].push_back(rule);
+ }
+ else
+ {
+ std::vector<Rule> temprules;
+ temprules.clear();
+ temprules.push_back(rule);
+ m_ruleTable.insert(std::make_pair(dest_edge_id, temprules));
+ }
+ }
+
+ m_bIsturnRestrictOn = true;
+ }
+ parent = new PARENT_PATH[edge_count + 1];
+ m_dCost = new CostHolder[edge_count + 1];
+ m_vecPath.clear();
+ int i;
+ int total_vertices = vertices.size();
+ for(i = 0; i < total_vertices - 1; i++)
+ {
+ int ret = my_dijkstra(vertices[i], vertices[i + 1], edge_count, err_msg);
+ if(ret < 0)
+ {
+ deleteall();
+ return -1;
+ }
+ }
+
+ *path = (path_element_t *) malloc(sizeof(path_element_t) * (m_vecPath.size() + 1));
+ *path_count = m_vecPath.size();
+
+ for(i = 0; i < *path_count; i++)
+ {
+ (*path)[i].vertex_id = m_vecPath[i].vertex_id;
+ (*path)[i].edge_id = m_vecPath[i].edge_id;
+ (*path)[i].cost = m_vecPath[i].cost;
+ }
+ deleteall();
+ return 0;
}
-int GraphDefinition:: my_dijkstra(edge_t *edges, unsigned int edge_count, int start_vertex, int end_vertex,
- path_element_t **path, int *path_count, char **err_msg, std::vector<PDVI> &ruleList)
+
+// -------------------------------------------------------------------------
+int GraphDefinition::my_dijkstra(int start_vertex, int end_vertex, unsigned int edge_count, char **err_msg)
{
- m_ruleTable.clear();
- int total_rule = ruleList.size();
- int i;
- LongVector vecsource;
- int kk;
- for(i = 0; i < total_rule; i++)
- {
- Rule rule;
- rule.cost = ruleList[i].first;
- int j;
- int seq_cnt = ruleList[i].second.size();
- for(j = 1; j < seq_cnt; j++)
- {
- rule.precedencelist.push_back(ruleList[i].second[j]);
- }
- int dest_edge_id = ruleList[i].second[0];
- if(m_ruleTable.find(dest_edge_id) != m_ruleTable.end())
- {
- m_ruleTable[dest_edge_id].push_back(rule);
- }
- else
- {
- std::vector<Rule> temprules;
- temprules.clear();
- temprules.push_back(rule);
- m_ruleTable.insert(std::make_pair(dest_edge_id, temprules));
- }
-
- if(isStartVirtual)
- {
- if(seq_cnt == 2 && ruleList[i].second[1] == m_lStartEdgeId)
- {
- vecsource = m_mapNodeId2Edge[start_vertex];
- for(kk = 0; kk < vecsource.size(); kk++)
- {
- rule.precedencelist.clear();
- rule.precedencelist.push_back(m_vecEdgeVector[vecsource[kk]]->m_lEdgeID);
- m_ruleTable[dest_edge_id].push_back(rule);
- }
- }
- }
- }
- if(isEndVirtual)
- {
- if(m_ruleTable.find(m_lEndEdgeId) != m_ruleTable.end())
- {
- std::vector<Rule> tmpRules = m_ruleTable[m_lEndEdgeId];
- vecsource = m_mapNodeId2Edge[end_vertex];
- for(kk = 0; kk < vecsource.size(); kk++)
- {
- m_ruleTable.insert(std::make_pair(m_vecEdgeVector[vecsource[kk]]->m_lEdgeID, tmpRules));
- }
- }
- }
- m_bIsturnRestrictOn = true;
- return(my_dijkstra(edges, edge_count, start_vertex, end_vertex, path, path_count, err_msg));
+ if(!m_bIsGraphConstructed)
+ {
+ *err_msg = (char *)"Graph not Ready!";
+ return -1;
+ }
+ unsigned int i;
+ for(i = 0; i <= edge_count; i++)
+ {
+ m_dCost[i].startCost = 1e15;
+ m_dCost[i].endCost = 1e15;
+ }
+
+ if(m_mapNodeId2Edge.find(start_vertex) == m_mapNodeId2Edge.end())
+ {
+ *err_msg = (char *)"Source Not Found";
+ deleteall();
+ return -1;
+ }
+
+ if(m_mapNodeId2Edge.find(end_vertex) == m_mapNodeId2Edge.end())
+ {
+ *err_msg = (char *)"Destination Not Found";
+ deleteall();
+ return -1;
+ }
+
+ std::priority_queue<PDP, std::vector<PDP>, std::greater<PDP> > que;
+ LongVector vecsource = m_mapNodeId2Edge[start_vertex];
+ GraphEdgeInfo* cur_edge = NULL;
+
+ for(i = 0; i < vecsource.size(); i++)
+ {
+ cur_edge = m_vecEdgeVector[vecsource[i]];
+ if(cur_edge->m_lStartNode == start_vertex)
+ {
+ if(cur_edge->m_dCost >= 0.0)
+ {
+ m_dCost[cur_edge->m_lEdgeIndex].endCost= cur_edge->m_dCost;
+ parent[cur_edge->m_lEdgeIndex].v_pos[0] = -1;
+ parent[cur_edge->m_lEdgeIndex].ed_ind[0] = -1;
+ que.push(std::make_pair(cur_edge->m_dCost, std::make_pair(cur_edge->m_lEdgeIndex, true)));
+ }
+ }
+ else
+ {
+ if(cur_edge->m_dReverseCost >= 0.0)
+ {
+ m_dCost[cur_edge->m_lEdgeIndex].startCost = cur_edge->m_dReverseCost;
+ parent[cur_edge->m_lEdgeIndex].v_pos[1] = -1;
+ parent[cur_edge->m_lEdgeIndex].ed_ind[1] = -1;
+ que.push(std::make_pair(cur_edge->m_dReverseCost, std::make_pair(cur_edge->m_lEdgeIndex, false)));
+ }
+ }
+ }
+
+ // int new_node;
+ int cur_node = -1;
+
+ while(!que.empty())
+ {
+ PDP cur_pos = que.top();
+ que.pop();
+ int cured_index = cur_pos.second.first;
+ cur_edge = m_vecEdgeVector[cured_index];
+ //GraphEdgeInfo* new_edge;
+
+ if(cur_pos.second.second) // explore edges connected to end node
+ {
+ cur_node = cur_edge->m_lEndNode;
+ if(cur_edge->m_dCost < 0.0)
+ continue;
+ if(cur_node == end_vertex)
+ break;
+ explore(cur_node, *cur_edge, true, cur_edge->m_vecEndConnedtedEdge, que);
+ }
+ else // explore edges connected to start node
+ {
+ cur_node = cur_edge->m_lStartNode;
+ if(cur_edge->m_dReverseCost < 0.0)
+ continue;
+ if(cur_node == end_vertex)
+ break;
+ explore(cur_node, *cur_edge, false, cur_edge->m_vecStartConnectedEdge, que);
+ }
+ }
+ if(cur_node != end_vertex)
+ {
+ *err_msg = (char *)"Path Not Found";
+ deleteall();
+ return -1;
+ }
+ else
+ {
+ // double total_cost; //set but not used
+ if(cur_node == cur_edge->m_lStartNode)
+ {
+ // total_cost = m_dCost[cur_edge->m_lEdgeIndex].startCost;
+ construct_path(cur_edge->m_lEdgeIndex, 1);
+ }
+ else
+ {
+ // total_cost = m_dCost[cur_edge->m_lEdgeIndex].endCost;
+ construct_path(cur_edge->m_lEdgeIndex, 0);
+ }
+ path_element_t pelement;
+ pelement.vertex_id = end_vertex;
+ pelement.edge_id = -1;
+ pelement.cost = 0.0;
+ m_vecPath.push_back(pelement);
+ }
+ return 0;
}
-int GraphDefinition:: my_dijkstra(edge_t *edges, unsigned int edge_count, int start_vertex, int end_vertex,
- path_element_t **path, int *path_count, char **err_msg)
+
+// -------------------------------------------------------------------------
+int GraphDefinition::my_dijkstra(edge_t *edges, unsigned int edge_count, int start_edge_id, double start_part, int end_edge_id, double end_part, bool directed, bool has_reverse_cost,
+ path_element_t **path, int *path_count, char **err_msg, std::vector<PDVI> &ruleList)
{
- if(!m_bIsGraphConstructed)
- {
- init();
- construct_graph(edges, edge_count);
- m_bIsGraphConstructed = true;
- }
-
- std::priority_queue<PDP, std::vector<PDP>, std::greater<PDP> > que;
- parent = new PARENT_PATH[edge_count + 1];
- m_dCost = new CostHolder[edge_count + 1];
- m_vecPath.clear();
-
- int i;
- for(i = 0; i <= edge_count; i++)
- {
- m_dCost[i].startCost = 1e15;
- m_dCost[i].endCost = 1e15;
- }
-
- if(m_mapNodeId2Edge.find(start_vertex) == m_mapNodeId2Edge.end())
- {
- *err_msg = (char *)"Source Not Found";
- deleteall();
- return -1;
- }
-
- if(m_mapNodeId2Edge.find(end_vertex) == m_mapNodeId2Edge.end())
- {
- *err_msg = (char *)"Destination Not Found";
- deleteall();
- return -1;
- }
-
- LongVector vecsource = m_mapNodeId2Edge[start_vertex];
- GraphEdgeInfo* cur_edge;
-
- for(i = 0; i < vecsource.size(); i++)
- {
- cur_edge = m_vecEdgeVector[vecsource[i]];
- if(cur_edge->m_lStartNode == start_vertex)
- {
- if(cur_edge->m_dCost >= 0.0)
- {
- m_dCost[cur_edge->m_lEdgeIndex].endCost= cur_edge->m_dCost;
- parent[cur_edge->m_lEdgeIndex].v_pos[0] = -1;
- parent[cur_edge->m_lEdgeIndex].ed_ind[0] = -1;
- que.push(std::make_pair(cur_edge->m_dCost, std::make_pair(cur_edge->m_lEdgeIndex, true)));
- }
- }
- else
- {
- if(cur_edge->m_dReverseCost >= 0.0)
- {
- m_dCost[cur_edge->m_lEdgeIndex].startCost = cur_edge->m_dReverseCost;
- parent[cur_edge->m_lEdgeIndex].v_pos[1] = -1;
- parent[cur_edge->m_lEdgeIndex].ed_ind[1] = -1;
- que.push(std::make_pair(cur_edge->m_dReverseCost, std::make_pair(cur_edge->m_lEdgeIndex, false)));
- }
- }
- }
- //parent[start_vertex].v_id = -1;
- //parent[start_vertex].ed_id = -1;
- //m_dCost[start_vertex] = 0.0;
-
- int new_node;
- int cur_node;
-
- while(!que.empty())
- {
- PDP cur_pos = que.top();
- que.pop();
- int cured_index = cur_pos.second.first;
- cur_edge = m_vecEdgeVector[cured_index];
- //GraphEdgeInfo* new_edge;
-
- if(cur_pos.second.second) // explore edges connected to end node
- {
- cur_node = cur_edge->m_lEndNode;
- if(cur_edge->m_dCost < 0.0)
- continue;
- if(cur_node == end_vertex)
- break;
- explore(cur_node, *cur_edge, true, cur_edge->m_vecEndConnedtedEdge, que);
- }
- else // explore edges connected to start node
- {
- cur_node = cur_edge->m_lStartNode;
- if(cur_edge->m_dReverseCost < 0.0)
- continue;
- if(cur_node == end_vertex)
- break;
- explore(cur_node, *cur_edge, false, cur_edge->m_vecStartConnectedEdge, que);
- }
- }
- if(cur_node != end_vertex)
- {
- if(m_lStartEdgeId == m_lEndEdgeId)
- {
- if(get_single_cost(1000.0, path, path_count))
- {
- return 0;
- }
- }
- *err_msg = (char *)"Path Not Found";
- deleteall();
- return -1;
- }
- else
- {
- double total_cost;
- if(cur_node == cur_edge->m_lStartNode)
- {
- total_cost = m_dCost[cur_edge->m_lEdgeIndex].startCost;
- construct_path(cur_edge->m_lEdgeIndex, 1);
- }
- else
- {
- total_cost = m_dCost[cur_edge->m_lEdgeIndex].endCost;
- construct_path(cur_edge->m_lEdgeIndex, 0);
- }
- path_element_t pelement;
- pelement.vertex_id = end_vertex;
- pelement.edge_id = -1;
- pelement.cost = 0.0;
- m_vecPath.push_back(pelement);
-
- if(m_lStartEdgeId == m_lEndEdgeId)
- {
- if(get_single_cost(total_cost, path, path_count))
- {
- return 0;
- }
- }
-
- *path = (path_element_t *) malloc(sizeof(path_element_t) * (m_vecPath.size() + 1));
- *path_count = m_vecPath.size();
-
- for(i = 0; i < *path_count; i++)
- {
- (*path)[i].vertex_id = m_vecPath[i].vertex_id;
- (*path)[i].edge_id = m_vecPath[i].edge_id;
- (*path)[i].cost = m_vecPath[i].cost;
- }
- if(isStartVirtual)
- {
- (*path)[0].vertex_id = -1;
- (*path)[0].edge_id = m_lStartEdgeId;
- }
- if(isEndVirtual)
- {
- *path_count = *path_count - 1;
- (*path)[*path_count - 1].edge_id = m_lEndEdgeId;
- }
- }
+ if(!m_bIsGraphConstructed)
+ {
+ init();
+ construct_graph(edges, edge_count, has_reverse_cost, directed);
+ m_bIsGraphConstructed = true;
+ }
+ GraphEdgeInfo* start_edge_info = m_vecEdgeVector[m_mapEdgeId2Index[start_edge_id]];
+ edge_t start_edge;
+ int start_vertex, end_vertex;
+ m_dStartpart = start_part;
+ m_dEndPart = end_part;
+ m_lStartEdgeId = start_edge_id;
+ m_lEndEdgeId = end_edge_id;
+
+ if(start_part == 0.0)
+ {
+ start_vertex = start_edge_info->m_lStartNode;
+ }
+ else if(start_part == 1.0)
+ {
+ start_vertex = start_edge_info->m_lEndNode;
+ }
+ else
+ {
+ isStartVirtual = true;
+ m_lStartEdgeId = start_edge_id;
+ start_vertex = max_node_id + 1;
+ max_node_id++;
+ start_edge.id = max_edge_id + 1;
+ max_edge_id++;
+ start_edge.source = start_vertex;
+ start_edge.reverse_cost = -1.0;
+ if(start_edge_info->m_dCost >= 0.0)
+ {
+ start_edge.target = start_edge_info->m_lEndNode;
+ start_edge.cost = (1.0 - start_part) * start_edge_info->m_dCost;
+ addEdge(start_edge);
+ edge_count++;
+ }
+ if(start_edge_info->m_dReverseCost >= 0.0)
+ {
+ start_edge.id = max_edge_id + 1;
+ max_edge_id++;
+ start_edge.target = start_edge_info->m_lStartNode;
+ start_edge.cost = start_part * start_edge_info->m_dReverseCost;
+ addEdge(start_edge);
+ edge_count++;
+ }
+ }
+
+ GraphEdgeInfo* end_edge_info = m_vecEdgeVector[m_mapEdgeId2Index[end_edge_id]];
+ edge_t end_edge;
+
+ if(end_part == 0.0)
+ {
+ end_vertex = end_edge_info->m_lStartNode;
+ }
+ else if(end_part == 1.0)
+ {
+ end_vertex = end_edge_info->m_lEndNode;
+ }
+ else
+ {
+ isEndVirtual = true;
+ m_lEndEdgeId = end_edge_id;
+ end_vertex = max_node_id + 1;
+ max_node_id++;
+ end_edge.id = max_edge_id + 1;
+ max_edge_id++;
+ end_edge.target = end_vertex;
+ end_edge.reverse_cost = -1.0;
+ if(end_edge_info->m_dCost >= 0.0)
+ {
+ end_edge.source = end_edge_info->m_lStartNode;
+ end_edge.cost = end_part * end_edge_info->m_dCost;
+ addEdge(end_edge);
+ edge_count++;
+ }
+ if(end_edge_info->m_dReverseCost >= 0.0)
+ {
+ end_edge.source = end_edge_info->m_lEndNode;
+ end_edge.id = max_edge_id + 1;
+ end_edge.cost = (1.0 - end_part) * end_edge_info->m_dReverseCost;
+ addEdge(end_edge);
+ edge_count++;
+ }
+ }
+
+ return(my_dijkstra(edges, edge_count, start_vertex, end_vertex, directed, has_reverse_cost, path, path_count, err_msg, ruleList));
+}
+
+
+// -------------------------------------------------------------------------
+int GraphDefinition:: my_dijkstra(edge_t *edges, unsigned int edge_count, int start_vertex, int end_vertex, bool directed, bool has_reverse_cost,
+ path_element_t **path, int *path_count, char **err_msg, std::vector<PDVI> &ruleList)
+{
+ m_ruleTable.clear();
+ int total_rule = ruleList.size();
+ int i;
+ LongVector vecsource;
+ unsigned int kk;
+ for(i = 0; i < total_rule; i++)
+ {
+ Rule rule;
+ rule.cost = ruleList[i].first;
+ int j;
+ int seq_cnt = ruleList[i].second.size();
+ for(j = 1; j < seq_cnt; j++)
+ {
+ rule.precedencelist.push_back(ruleList[i].second[j]);
+ }
+ int dest_edge_id = ruleList[i].second[0];
+ if(m_ruleTable.find(dest_edge_id) != m_ruleTable.end())
+ {
+ m_ruleTable[dest_edge_id].push_back(rule);
+ }
+ else
+ {
+ std::vector<Rule> temprules;
+ temprules.clear();
+ temprules.push_back(rule);
+ m_ruleTable.insert(std::make_pair(dest_edge_id, temprules));
+ }
+
+ if(isStartVirtual)
+ {
+ if(seq_cnt == 2 && ruleList[i].second[1] == m_lStartEdgeId)
+ {
+ vecsource = m_mapNodeId2Edge[start_vertex];
+ for(kk = 0; kk < vecsource.size(); kk++)
+ {
+ rule.precedencelist.clear();
+ rule.precedencelist.push_back(m_vecEdgeVector[vecsource[kk]]->m_lEdgeID);
+ m_ruleTable[dest_edge_id].push_back(rule);
+ }
+ }
+ }
+ }
+ if(isEndVirtual)
+ {
+ if(m_ruleTable.find(m_lEndEdgeId) != m_ruleTable.end())
+ {
+ std::vector<Rule> tmpRules = m_ruleTable[m_lEndEdgeId];
+ vecsource = m_mapNodeId2Edge[end_vertex];
+ for(kk = 0; kk < vecsource.size(); kk++)
+ {
+ m_ruleTable.insert(std::make_pair(m_vecEdgeVector[vecsource[kk]]->m_lEdgeID, tmpRules));
+ }
+ }
+ }
+ m_bIsturnRestrictOn = true;
+ return(my_dijkstra(edges, edge_count, start_vertex, end_vertex, directed, has_reverse_cost, path, path_count, err_msg));
+}
+
+
+// -------------------------------------------------------------------------
+int GraphDefinition:: my_dijkstra(edge_t *edges, unsigned int edge_count, int start_vertex, int end_vertex, bool directed, bool has_reverse_cost,
+ path_element_t **path, int *path_count, char **err_msg)
+{
+ if(!m_bIsGraphConstructed)
+ {
+ init();
+ construct_graph(edges, edge_count, has_reverse_cost, directed);
+ m_bIsGraphConstructed = true;
+ }
+
+ std::priority_queue<PDP, std::vector<PDP>, std::greater<PDP> > que;
+ parent = new PARENT_PATH[edge_count + 1];
+ m_dCost = new CostHolder[edge_count + 1];
+ m_vecPath.clear();
+
+ unsigned int i;
+ for(i = 0; i <= edge_count; i++)
+ {
+ m_dCost[i].startCost = 1e15;
+ m_dCost[i].endCost = 1e15;
+ }
+
+ if(m_mapNodeId2Edge.find(start_vertex) == m_mapNodeId2Edge.end())
+ {
+ *err_msg = (char *)"Source Not Found";
+ deleteall();
+ return -1;
+ }
+
+ if(m_mapNodeId2Edge.find(end_vertex) == m_mapNodeId2Edge.end())
+ {
+ *err_msg = (char *)"Destination Not Found";
+ deleteall();
+ return -1;
+ }
+
+ LongVector vecsource = m_mapNodeId2Edge[start_vertex];
+ GraphEdgeInfo* cur_edge = NULL;
+
+ for(i = 0; i < vecsource.size(); i++)
+ {
+ cur_edge = m_vecEdgeVector[vecsource[i]];
+ if(cur_edge->m_lStartNode == start_vertex)
+ {
+ if(cur_edge->m_dCost >= 0.0)
+ {
+ m_dCost[cur_edge->m_lEdgeIndex].endCost= cur_edge->m_dCost;
+ parent[cur_edge->m_lEdgeIndex].v_pos[0] = -1;
+ parent[cur_edge->m_lEdgeIndex].ed_ind[0] = -1;
+ que.push(std::make_pair(cur_edge->m_dCost, std::make_pair(cur_edge->m_lEdgeIndex, true)));
+ }
+ }
+ else
+ {
+ if(cur_edge->m_dReverseCost >= 0.0)
+ {
+ m_dCost[cur_edge->m_lEdgeIndex].startCost = cur_edge->m_dReverseCost;
+ parent[cur_edge->m_lEdgeIndex].v_pos[1] = -1;
+ parent[cur_edge->m_lEdgeIndex].ed_ind[1] = -1;
+ que.push(std::make_pair(cur_edge->m_dReverseCost, std::make_pair(cur_edge->m_lEdgeIndex, false)));
+ }
+ }
+ }
+ //parent[start_vertex].v_id = -1;
+ //parent[start_vertex].ed_id = -1;
+ //m_dCost[start_vertex] = 0.0;
+
+ // int new_node;
+ int cur_node = -1;
+
+ while(!que.empty())
+ {
+ PDP cur_pos = que.top();
+ que.pop();
+ int cured_index = cur_pos.second.first;
+ cur_edge = m_vecEdgeVector[cured_index];
+ //GraphEdgeInfo* new_edge;
+
+ if(cur_pos.second.second) // explore edges connected to end node
+ {
+ cur_node = cur_edge->m_lEndNode;
+ if(cur_edge->m_dCost < 0.0)
+ continue;
+ if(cur_node == end_vertex)
+ break;
+ explore(cur_node, *cur_edge, true, cur_edge->m_vecEndConnedtedEdge, que);
+ }
+ else // explore edges connected to start node
+ {
+ cur_node = cur_edge->m_lStartNode;
+ if(cur_edge->m_dReverseCost < 0.0)
+ continue;
+ if(cur_node == end_vertex)
+ break;
+ explore(cur_node, *cur_edge, false, cur_edge->m_vecStartConnectedEdge, que);
+ }
+ }
+ if(cur_node != end_vertex)
+ {
+ if(m_lStartEdgeId == m_lEndEdgeId)
+ {
+ if(get_single_cost(1000.0, path, path_count))
+ {
+ return 0;
+ }
+ }
+ *err_msg = (char *)"Path Not Found";
+ deleteall();
+ return -1;
+ }
+ else
+ {
+ double total_cost;
+ if(cur_node == cur_edge->m_lStartNode)
+ {
+ total_cost = m_dCost[cur_edge->m_lEdgeIndex].startCost;
+ construct_path(cur_edge->m_lEdgeIndex, 1);
+ }
+ else
+ {
+ total_cost = m_dCost[cur_edge->m_lEdgeIndex].endCost;
+ construct_path(cur_edge->m_lEdgeIndex, 0);
+ }
+ path_element_t pelement;
+ pelement.vertex_id = end_vertex;
+ pelement.edge_id = -1;
+ pelement.cost = 0.0;
+ m_vecPath.push_back(pelement);
+
+ if(m_lStartEdgeId == m_lEndEdgeId)
+ {
+ if(get_single_cost(total_cost, path, path_count))
+ {
+ return 0;
+ }
+ }
+
+ *path = (path_element_t *) malloc(sizeof(path_element_t) * (m_vecPath.size() + 1));
+ *path_count = m_vecPath.size();
+
+ for(int i = 0; i < *path_count; i++)
+ {
+ (*path)[i].vertex_id = m_vecPath[i].vertex_id;
+ (*path)[i].edge_id = m_vecPath[i].edge_id;
+ (*path)[i].cost = m_vecPath[i].cost;
+ }
+ if(isStartVirtual)
+ {
+ (*path)[0].vertex_id = -1;
+ (*path)[0].edge_id = m_lStartEdgeId;
+ }
+ if(isEndVirtual)
+ {
+ *path_count = *path_count - 1;
+ (*path)[*path_count - 1].edge_id = m_lEndEdgeId;
+ }
+ }
deleteall();
- return 0;
+ return 0;
}
+
+// -------------------------------------------------------------------------
bool GraphDefinition::get_single_cost(double total_cost, path_element_t **path, int *path_count)
{
- GraphEdgeInfo* start_edge_info = m_vecEdgeVector[m_mapEdgeId2Index[m_lStartEdgeId]];
- if(m_dEndPart >= m_dStartpart)
- {
- if(start_edge_info->m_dCost >= 0.0 && start_edge_info->m_dCost * (m_dEndPart - m_dStartpart) <= total_cost)
- {
- *path = (path_element_t *) malloc(sizeof(path_element_t) * (1));
- *path_count = 1;
- (*path)[0].vertex_id = -1;
- (*path)[0].edge_id = m_lStartEdgeId;
- (*path)[0].cost = start_edge_info->m_dCost * (m_dEndPart - m_dStartpart);
-
- return true;
- }
- }
- else
- {
- if(start_edge_info->m_dReverseCost >= 0.0 && start_edge_info->m_dReverseCost * (m_dStartpart - m_dEndPart) <= total_cost)
- {
- *path = (path_element_t *) malloc(sizeof(path_element_t) * (1));
- *path_count = 1;
- (*path)[0].vertex_id = -1;
- (*path)[0].edge_id = m_lStartEdgeId;
- (*path)[0].cost = start_edge_info->m_dReverseCost * (m_dStartpart - m_dEndPart);
-
- return true;
- }
- }
- return false;
-
+ GraphEdgeInfo* start_edge_info = m_vecEdgeVector[m_mapEdgeId2Index[m_lStartEdgeId]];
+ if(m_dEndPart >= m_dStartpart)
+ {
+ if(start_edge_info->m_dCost >= 0.0 && start_edge_info->m_dCost * (m_dEndPart - m_dStartpart) <= total_cost)
+ {
+ *path = (path_element_t *) malloc(sizeof(path_element_t) * (1));
+ *path_count = 1;
+ (*path)[0].vertex_id = -1;
+ (*path)[0].edge_id = m_lStartEdgeId;
+ (*path)[0].cost = start_edge_info->m_dCost * (m_dEndPart - m_dStartpart);
+
+ return true;
+ }
+ }
+ else
+ {
+ if(start_edge_info->m_dReverseCost >= 0.0 && start_edge_info->m_dReverseCost * (m_dStartpart - m_dEndPart) <= total_cost)
+ {
+ *path = (path_element_t *) malloc(sizeof(path_element_t) * (1));
+ *path_count = 1;
+ (*path)[0].vertex_id = -1;
+ (*path)[0].edge_id = m_lStartEdgeId;
+ (*path)[0].cost = start_edge_info->m_dReverseCost * (m_dStartpart - m_dEndPart);
+
+ return true;
+ }
+ }
+ return false;
+
}
-bool GraphDefinition::construct_graph(edge_t* edges, int edge_count)
+
+// -------------------------------------------------------------------------
+bool GraphDefinition::construct_graph(edge_t* edges, int edge_count, bool has_reverse_cost, bool directed)
{
- int i;
- for(i = 0; i < edge_count; i++)
- {
- addEdge(edges[i]);
- }
- return true;
+ int i;
+ for(i = 0; i < edge_count; i++)
+ {
+ if(!has_reverse_cost)
+ {
+ if(directed)
+ {
+ edges[i].reverse_cost = -1.0;
+ }
+ else
+ {
+ edges[i].reverse_cost = edges[i].cost;
+ }
+ }
+ addEdge(edges[i]);
+ }
+ m_bIsGraphConstructed = true;
+ return true;
}
+
+// -------------------------------------------------------------------------
bool GraphDefinition::connectEdge(GraphEdgeInfo& firstEdge, GraphEdgeInfo& secondEdge, bool bIsStartNodeSame)
{
- if(bIsStartNodeSame)
- {
- if(firstEdge.m_dReverseCost >= 0.0)
- firstEdge.m_vecStartConnectedEdge.push_back(secondEdge.m_lEdgeIndex);
- if(firstEdge.m_lStartNode == secondEdge.m_lStartNode)
- {
- if(secondEdge.m_dReverseCost >= 0.0)
- secondEdge.m_vecStartConnectedEdge.push_back(firstEdge.m_lEdgeIndex);
- }
- else
- {
- if(secondEdge.m_dCost >= 0.0)
- secondEdge.m_vecEndConnedtedEdge.push_back(firstEdge.m_lEdgeIndex);
- }
- }
- else
- {
- if(firstEdge.m_dCost >= 0.0)
- firstEdge.m_vecEndConnedtedEdge.push_back(secondEdge.m_lEdgeIndex);
- if(firstEdge.m_lEndNode == secondEdge.m_lStartNode)
- {
- if(secondEdge.m_dReverseCost >= 0.0)
- secondEdge.m_vecStartConnectedEdge.push_back(firstEdge.m_lEdgeIndex);
- }
- else
- {
- if(secondEdge.m_dCost >= 0.0)
- secondEdge.m_vecEndConnedtedEdge.push_back(firstEdge.m_lEdgeIndex);
- }
- }
-
- return true;
+ if(bIsStartNodeSame)
+ {
+ if(firstEdge.m_dReverseCost >= 0.0)
+ firstEdge.m_vecStartConnectedEdge.push_back(secondEdge.m_lEdgeIndex);
+ if(firstEdge.m_lStartNode == secondEdge.m_lStartNode)
+ {
+ if(secondEdge.m_dReverseCost >= 0.0)
+ secondEdge.m_vecStartConnectedEdge.push_back(firstEdge.m_lEdgeIndex);
+ }
+ else
+ {
+ if(secondEdge.m_dCost >= 0.0)
+ secondEdge.m_vecEndConnedtedEdge.push_back(firstEdge.m_lEdgeIndex);
+ }
+ }
+ else
+ {
+ if(firstEdge.m_dCost >= 0.0)
+ firstEdge.m_vecEndConnedtedEdge.push_back(secondEdge.m_lEdgeIndex);
+ if(firstEdge.m_lEndNode == secondEdge.m_lStartNode)
+ {
+ if(secondEdge.m_dReverseCost >= 0.0)
+ secondEdge.m_vecStartConnectedEdge.push_back(firstEdge.m_lEdgeIndex);
+ }
+ else
+ {
+ if(secondEdge.m_dCost >= 0.0)
+ secondEdge.m_vecEndConnedtedEdge.push_back(firstEdge.m_lEdgeIndex);
+ }
+ }
+
+ return true;
}
+
+// -------------------------------------------------------------------------
bool GraphDefinition::addEdge(edge_t edgeIn)
{
- long lTest;
- Long2LongMap::iterator itMap = m_mapEdgeId2Index.find(edgeIn.id);
- if(itMap != m_mapEdgeId2Index.end())
- return false;
+ // long lTest;
+ Long2LongMap::iterator itMap = m_mapEdgeId2Index.find(edgeIn.id);
+ if(itMap != m_mapEdgeId2Index.end())
+ return false;
-
- GraphEdgeInfo* newEdge = new GraphEdgeInfo();
+
+ GraphEdgeInfo* newEdge = new GraphEdgeInfo();
newEdge->m_vecStartConnectedEdge.clear();
newEdge->m_vecEndConnedtedEdge.clear();
newEdge->m_vecRestrictedEdge.clear();
- newEdge->m_lEdgeID = edgeIn.id;
- newEdge->m_lEdgeIndex = m_vecEdgeVector.size();
- newEdge->m_lStartNode = edgeIn.source;
- newEdge->m_lEndNode = edgeIn.target;
- newEdge->m_dCost = edgeIn.cost;
- newEdge->m_dReverseCost = edgeIn.reverse_cost;
-
- if(edgeIn.id > max_edge_id)
- {
- max_edge_id = edgeIn.id;
- }
-
- if(newEdge->m_lStartNode > max_node_id)
- {
- max_node_id = newEdge->m_lStartNode;
- }
- if(newEdge->m_lEndNode > max_node_id)
- {
- max_node_id = newEdge->m_lEndNode;
- }
-
- //Searching the start node for connectivity
- Long2LongVectorMap::iterator itNodeMap = m_mapNodeId2Edge.find(edgeIn.source);
- if(itNodeMap != m_mapNodeId2Edge.end())
- {
- //Connect current edge with existing edge with start node
- //connectEdge(
- long lEdgeCount = itNodeMap->second.size();
- long lEdgeIndex;
- for(lEdgeIndex = 0; lEdgeIndex < lEdgeCount; lEdgeIndex++)
- {
- long lEdge = itNodeMap->second.at(lEdgeIndex);
- connectEdge(*newEdge, *m_vecEdgeVector[lEdge], true);
- }
- }
-
-
- //Searching the end node for connectivity
- itNodeMap = m_mapNodeId2Edge.find(edgeIn.target);
- if(itNodeMap != m_mapNodeId2Edge.end())
- {
- //Connect current edge with existing edge with end node
- //connectEdge(
- long lEdgeCount = itNodeMap->second.size();
- long lEdgeIndex;
- for(lEdgeIndex = 0; lEdgeIndex < lEdgeCount; lEdgeIndex++)
- {
- long lEdge = itNodeMap->second.at(lEdgeIndex);
- connectEdge(*newEdge, *m_vecEdgeVector[lEdge], false);
- }
- }
-
-
-
- //Add this node and edge into the data structure
- m_mapNodeId2Edge[edgeIn.source].push_back(newEdge->m_lEdgeIndex);
- m_mapNodeId2Edge[edgeIn.target].push_back(newEdge->m_lEdgeIndex);
-
-
- //Adding edge to the list
- m_mapEdgeId2Index.insert(std::make_pair(newEdge->m_lEdgeID, m_vecEdgeVector.size()));
- m_vecEdgeVector.push_back(newEdge);
-
- //
-
-
- return true;
+ newEdge->m_lEdgeID = edgeIn.id;
+ newEdge->m_lEdgeIndex = m_vecEdgeVector.size();
+ newEdge->m_lStartNode = edgeIn.source;
+ newEdge->m_lEndNode = edgeIn.target;
+ newEdge->m_dCost = edgeIn.cost;
+ newEdge->m_dReverseCost = edgeIn.reverse_cost;
+
+ if(edgeIn.id > max_edge_id)
+ {
+ max_edge_id = edgeIn.id;
+ }
+
+ if(newEdge->m_lStartNode > max_node_id)
+ {
+ max_node_id = newEdge->m_lStartNode;
+ }
+ if(newEdge->m_lEndNode > max_node_id)
+ {
+ max_node_id = newEdge->m_lEndNode;
+ }
+
+ //Searching the start node for connectivity
+ Long2LongVectorMap::iterator itNodeMap = m_mapNodeId2Edge.find(edgeIn.source);
+ if(itNodeMap != m_mapNodeId2Edge.end())
+ {
+ //Connect current edge with existing edge with start node
+ //connectEdge(
+ long lEdgeCount = itNodeMap->second.size();
+ long lEdgeIndex;
+ for(lEdgeIndex = 0; lEdgeIndex < lEdgeCount; lEdgeIndex++)
+ {
+ long lEdge = itNodeMap->second.at(lEdgeIndex);
+ connectEdge(*newEdge, *m_vecEdgeVector[lEdge], true);
+ }
+ }
+
+
+ //Searching the end node for connectivity
+ itNodeMap = m_mapNodeId2Edge.find(edgeIn.target);
+ if(itNodeMap != m_mapNodeId2Edge.end())
+ {
+ //Connect current edge with existing edge with end node
+ //connectEdge(
+ long lEdgeCount = itNodeMap->second.size();
+ long lEdgeIndex;
+ for(lEdgeIndex = 0; lEdgeIndex < lEdgeCount; lEdgeIndex++)
+ {
+ long lEdge = itNodeMap->second.at(lEdgeIndex);
+ connectEdge(*newEdge, *m_vecEdgeVector[lEdge], false);
+ }
+ }
+
+
+
+ //Add this node and edge into the data structure
+ m_mapNodeId2Edge[edgeIn.source].push_back(newEdge->m_lEdgeIndex);
+ m_mapNodeId2Edge[edgeIn.target].push_back(newEdge->m_lEdgeIndex);
+
+
+ //Adding edge to the list
+ m_mapEdgeId2Index.insert(std::make_pair(newEdge->m_lEdgeID, m_vecEdgeVector.size()));
+ m_vecEdgeVector.push_back(newEdge);
+
+ //
+
+
+ return true;
}
diff --git a/src/trsp/src/GraphDefinition.h b/src/trsp/src/GraphDefinition.h
index aee1575..96fb156 100644
--- a/src/trsp/src/GraphDefinition.h
+++ b/src/trsp/src/GraphDefinition.h
@@ -1,128 +1,157 @@
-#ifndef GRAPHDEFINITION_H
-#define GRAPHDEFINITION_H
-
-#include <vector>
-#include <map>
-#include <queue>
-#include <string>
-#include <stdlib.h>
-#include <iostream>
-#include "trsp.h"
-
-typedef std::vector<long> LongVector;
-typedef std::vector<LongVector> VectorOfLongVector;
-typedef std::pair<int, bool> PIB;
-typedef std::pair<double, PIB> PDP;
-typedef std::pair<double, std::vector<int> > PDVI;
-
-/*
-typedef struct edge
-{
- int id;
- int source;
- int target;
- double cost;
- double reverse_cost;
-} edge_t;
-
-typedef struct path_element
-{
- int vertex_id;
- int edge_id;
- double cost;
-}path_element_t;
-*/
-
-typedef struct{
- int ed_ind[2];
- int v_pos[2];
-}PARENT_PATH;
-
-typedef struct{
- double cost;
- std::vector<int> precedencelist;
-}Rule;
-
-typedef struct{
- double startCost, endCost;
-}CostHolder;
-
-typedef std::map<int, std::vector<Rule> > RuleTable;
-
-
-
-class GraphEdgeInfo
-{
-public:
- long m_lEdgeID;
- long m_lEdgeIndex;
- short m_sDirection;
- double m_dCost;
- double m_dReverseCost;
- LongVector m_vecStartConnectedEdge;
- LongVector m_vecEndConnedtedEdge;
- //LongVector m_vecConnectedNode;
- bool m_bIsLeadingRestrictedEdge;
- VectorOfLongVector m_vecRestrictedEdge;
-
- long m_lStartNode;
- long m_lEndNode;
-};
-
-
-
-
-typedef std::vector<GraphEdgeInfo*> GraphEdgeVector;
-typedef std::map<long,LongVector> Long2LongVectorMap;
-typedef std::map<long,long> Long2LongMap;
-
-
-
-
-class GraphDefinition
-{
-public:
- GraphDefinition(void);
- ~GraphDefinition(void);
-
- int my_dijkstra(edge_t *edges, unsigned int edge_count, int start_vertex, int end_vertex,
- path_element_t **path, int *path_count, char **err_msg);
- int my_dijkstra(edge_t *edges, unsigned int edge_count, int start_vertex, int end_vertex,
- path_element_t **path, int *path_count, char **err_msg, std::vector<PDVI> &ruleList);
- int my_dijkstra(edge_t *edges, unsigned int edge_count, int start_edge, double start_part, int end_edge, double end_part,
- path_element_t **path, int *path_count, char **err_msg, std::vector<PDVI> &ruleList);
-
-
-private:
- bool construct_graph(edge_t *edges, int edge_count);
- double construct_path(int ed_id, int v_pos);
- void explore(int cur_node, GraphEdgeInfo& cur_edge, bool isStart, LongVector &vecIndex, std::priority_queue<PDP, std::vector<PDP>, std::greater<PDP> > &que);
- double getRestrictionCost(int cur_node, GraphEdgeInfo& new_edge, bool isStart);
- bool addEdge(edge edgeIn);
- bool connectEdge(GraphEdgeInfo& firstEdge, GraphEdgeInfo& secondEdge, bool bIsStartNodeSame);
- bool get_single_cost(double total_cost, path_element_t **path, int *path_count);
- void init();
- void deleteall();
-
-private:
- GraphEdgeVector m_vecEdgeVector;
- Long2LongMap m_mapEdgeId2Index;
- Long2LongVectorMap m_mapNodeId2Edge;
- int max_node_id;
- int max_edge_id;
- int m_lStartEdgeId;
- int m_lEndEdgeId;
- double m_dStartpart;
- double m_dEndPart;
- bool isStartVirtual;
- bool isEndVirtual;
-
- std::vector <path_element_t> m_vecPath;
- PARENT_PATH *parent;
- CostHolder *m_dCost;
- RuleTable m_ruleTable;
- bool m_bIsturnRestrictOn;
- bool m_bIsGraphConstructed;
-};
-
-#endif
+#ifndef GRAPHDEFINITION_H
+#define GRAPHDEFINITION_H
+
+#include <vector>
+#include <map>
+#include <queue>
+#include <string>
+#include <stdlib.h>
+#include <iostream>
+
+#include "trsp.h"
+
+//using namespace std;
+
+typedef std::vector<long> LongVector;
+typedef std::vector<LongVector> VectorOfLongVector;
+typedef std::pair<int, bool> PIB;
+typedef std::pair<double, PIB> PDP;
+typedef std::pair<double, std::vector<int> > PDVI;
+
+/*
+typedef struct edge
+{
+ int id;
+ int source;
+ int target;
+ double cost;
+ double reverse_cost;
+} edge_t;
+
+typedef struct path_element
+{
+ int vertex_id;
+ int edge_id;
+ double cost;
+}path_element_t;
+*/
+
+typedef struct{
+ int ed_ind[2];
+ int v_pos[2];
+} PARENT_PATH;
+
+typedef struct{
+ double cost;
+ std::vector<int> precedencelist;
+} Rule;
+
+typedef struct{
+ double startCost, endCost;
+} CostHolder;
+
+typedef std::map<int, std::vector<Rule> > RuleTable;
+
+
+
+class GraphEdgeInfo
+{
+public:
+ long m_lEdgeID;
+ long m_lEdgeIndex;
+ short m_sDirection;
+ double m_dCost;
+ double m_dReverseCost;
+ LongVector m_vecStartConnectedEdge;
+ LongVector m_vecEndConnedtedEdge;
+ //LongVector m_vecConnectedNode;
+ bool m_bIsLeadingRestrictedEdge;
+ VectorOfLongVector m_vecRestrictedEdge;
+
+ long m_lStartNode;
+ long m_lEndNode;
+};
+
+
+
+
+typedef std::vector<GraphEdgeInfo*> GraphEdgeVector;
+typedef std::map<long,LongVector> Long2LongVectorMap;
+typedef std::map<long,long> Long2LongMap;
+
+
+
+
+class GraphDefinition
+{
+public:
+ GraphDefinition(void);
+ ~GraphDefinition(void);
+
+ int my_dijkstra(int start_vertex, int end_vertex,
+ unsigned int edge_count, char** err_msg);
+
+ int my_dijkstra(edge_t *edges, unsigned int edge_count,
+ int start_vertex, int end_vertex,
+ bool directed, bool has_reverse_cost,
+ path_element_t **path, int *path_count,
+ char **err_msg);
+
+ int my_dijkstra(edge_t *edges, unsigned int edge_count,
+ int start_vertex, int end_vertex,
+ bool directed, bool has_reverse_cost,
+ path_element_t **path, int *path_count,
+ char **err_msg,
+ std::vector<PDVI> &ruleList);
+
+ int my_dijkstra(edge_t *edges, unsigned int edge_count,
+ int start_edge, double start_part,
+ int end_edge, double end_part,
+ bool directed, bool has_reverse_cost,
+ path_element_t **path, int *path_count,
+ char **err_msg,
+ std::vector<PDVI> &ruleList);
+
+ int multi_dijkstra(edge_t *edges, unsigned int edge_count,
+ std::vector<int> vertices,
+ bool directed, bool has_reverse_cost,
+ path_element_t **path, int *path_count,
+ char **err_msg,
+ std::vector<PDVI> &ruleList);
+
+ bool construct_graph(edge_t *edges, int edge_count,
+ bool has_reverse_cost, bool directed);
+
+
+private:
+ double construct_path(int ed_id, int v_pos);
+ void explore(int cur_node, GraphEdgeInfo& cur_edge, bool isStart, LongVector &vecIndex, std::priority_queue<PDP, std::vector<PDP>, std::greater<PDP> > &que);
+ double getRestrictionCost(int cur_node, GraphEdgeInfo& new_edge, bool isStart);
+ bool addEdge(edge edgeIn);
+ bool connectEdge(GraphEdgeInfo& firstEdge, GraphEdgeInfo& secondEdge, bool bIsStartNodeSame);
+ bool get_single_cost(double total_cost, path_element_t **path, int *path_count);
+ void init();
+ void deleteall();
+
+private:
+ GraphEdgeVector m_vecEdgeVector;
+ Long2LongMap m_mapEdgeId2Index;
+ Long2LongVectorMap m_mapNodeId2Edge;
+ int max_node_id;
+ int max_edge_id;
+ int m_lStartEdgeId;
+ int m_lEndEdgeId;
+ double m_dStartpart;
+ double m_dEndPart;
+ bool isStartVirtual;
+ bool isEndVirtual;
+
+ std::vector <path_element_t> m_vecPath;
+ PARENT_PATH *parent;
+ CostHolder *m_dCost;
+ RuleTable m_ruleTable;
+ bool m_bIsturnRestrictOn;
+ bool m_bIsGraphConstructed;
+};
+
+#endif
diff --git a/src/trsp/src/trsp.c b/src/trsp/src/trsp.c
index 5ea2537..3f2c62f 100644
--- a/src/trsp/src/trsp.c
+++ b/src/trsp/src/trsp.c
@@ -276,9 +276,12 @@ static int compute_trsp(
edge_t *edges = NULL;
int total_tuples = 0;
+#ifndef _MSC_VER
edge_columns_t edge_columns = {.id= -1, .source= -1, .target= -1,
.cost= -1, .reverse_cost= -1};
-
+#else // _MSC_VER
+ edge_columns_t edge_columns = {-1, -1, -1, -1, -1};
+#endif //_MSC_VER
restrict_t *restricts = NULL;
int total_restrict_tuples = 0;
restrict_columns_t restrict_columns = {.target_id= -1, .via_path= -1,
@@ -410,7 +413,7 @@ static int compute_trsp(
//DBG("edgeID: %i SRc:%i - %i, cost: %f", edges[z].id,edges[z].source, edges[z].target,edges[z].cost);
}
-
+
DBG("Min vertex id: %i , Max vid: %i",v_min_id,v_max_id);
DBG("Total %i edge tuples", total_tuples);
@@ -503,6 +506,10 @@ static int compute_trsp(
if (dovertex) {
DBG("Calling trsp_node_wrapper\n");
+ /** hack always returns 0 -1 when installed on EDB VC++ 64-bit without this **/
+ #if defined(__MINGW64__)
+ elog(NOTICE,"Calling trsp_node_wrapper\n");
+ #endif
ret = trsp_node_wrapper(edges, total_tuples,
restricts, total_restrict_tuples,
start_id, end_id,
@@ -565,7 +572,10 @@ turn_restrict_shortest_path_vertex(PG_FUNCTION_ARGS)
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int path_count = 0;
+
int ret = -1;
+ if (ret == -1) {}; // to avoid warning set but not used
+
int i;
// create a function context for cross-call persistence
@@ -590,7 +600,10 @@ turn_restrict_shortest_path_vertex(PG_FUNCTION_ARGS)
DBG("Calling compute_trsp");
- ret = compute_trsp(text2char(PG_GETARG_TEXT_P(0)),
+
+ ret =
+
+ compute_trsp(text2char(PG_GETARG_TEXT_P(0)),
1, // do vertex
PG_GETARG_INT32(1),
0.5,
@@ -689,7 +702,9 @@ turn_restrict_shortest_path_edge(PG_FUNCTION_ARGS)
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
int path_count = 0;
+#ifdef DEBUG
int ret = -1;
+#endif
int i;
double s_pos;
double e_pos;
@@ -734,7 +749,10 @@ turn_restrict_shortest_path_edge(PG_FUNCTION_ARGS)
DBG("Calling compute_trsp");
- ret = compute_trsp(text2char(PG_GETARG_TEXT_P(0)),
+#ifdef DEBUG
+ ret =
+#endif
+ compute_trsp(text2char(PG_GETARG_TEXT_P(0)),
0, //sdo edge
PG_GETARG_INT32(1),
s_pos,
diff --git a/src/trsp/src/trsp.h b/src/trsp/src/trsp.h
index b29132a..0948655 100644
--- a/src/trsp/src/trsp.h
+++ b/src/trsp/src/trsp.h
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/trsp/src/trsp_core.cpp b/src/trsp/src/trsp_core.cpp
index f85fd1e..21801c5 100644
--- a/src/trsp/src/trsp_core.cpp
+++ b/src/trsp/src/trsp_core.cpp
@@ -1,105 +1,110 @@
-#include "GraphDefinition.h"
-#include "utils.h"
-
-
-int trsp_node_wrapper(
- edge_t *edges,
- unsigned int edge_count,
- restrict_t *restricts,
- int restrict_count,
- int start_vertex,
- int end_vertex,
- bool directed,
- bool has_reverse_cost,
- path_element_t **path,
- int *path_count,
- char **err_msg
- )
-{
- try {
-
- std::vector<PDVI> ruleTable;
-
- int i, j;
- ruleTable.clear();
- for (i=0; i<restrict_count; i++) {
- std::vector<int> seq;
- seq.clear();
- seq.push_back(restricts[i].target_id);
- for(j = 0; j<MAX_RULE_LENGTH && restricts[i].via[j]>-1; j++)
- {
- seq.push_back(restricts[i].via[j]);
- }
- ruleTable.push_back(make_pair(restricts[i].to_cost, seq));
- }
-
- GraphDefinition gdef;
- int res = gdef.my_dijkstra(edges, edge_count, start_vertex, end_vertex, path, path_count, err_msg, ruleTable);
-
-
- if (res < 0)
- return res;
- else
- return EXIT_SUCCESS;
- }
- catch(std::exception& e) {
- *err_msg = (char *) e.what();
- return -1;
- }
- catch(...) {
- *err_msg = (char *) "Caught unknown exception!";
- return -1;
- }
-}
-
-int trsp_edge_wrapper(
- edge_t *edges,
- unsigned int edge_count,
- restrict_t *restricts,
- int restrict_count,
- int start_edge,
- double start_pos,
- int end_edge,
- double end_pos,
- bool directed,
- bool has_reverse_cost,
- path_element_t **path,
- int *path_count,
- char **err_msg
- )
-{
- try {
-
- std::vector<PDVI> ruleTable;
-
- int i, j;
- ruleTable.clear();
- for (i=0; i<restrict_count; i++) {
- std::vector<int> seq;
- seq.clear();
- seq.push_back(restricts[i].target_id);
- for(j = 0; j<MAX_RULE_LENGTH && restricts[i].via[j]>-1; j++)
- {
- seq.push_back(restricts[i].via[j]);
- }
- ruleTable.push_back(make_pair(restricts[i].to_cost, seq));
- }
-
- GraphDefinition gdef;
- int res = gdef.my_dijkstra(edges, edge_count, start_edge, start_pos, end_edge, end_pos, path, path_count, err_msg, ruleTable);
-
-
- if (res < 0)
- return res;
- else
- return EXIT_SUCCESS;
- }
- catch(std::exception& e) {
- *err_msg = (char *) e.what();
- return -1;
- }
- catch(...) {
- *err_msg = (char *) "Caught unknown exception!";
- return -1;
- }
-}
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#include "GraphDefinition.h"
+#include "utils.h"
+
+
+int trsp_node_wrapper(
+ edge_t *edges,
+ unsigned int edge_count,
+ restrict_t *restricts,
+ int restrict_count,
+ int start_vertex,
+ int end_vertex,
+ bool directed,
+ bool has_reverse_cost,
+ path_element_t **path,
+ int *path_count,
+ char **err_msg
+ )
+{
+ try {
+
+ std::vector<PDVI> ruleTable;
+
+ int i, j;
+ ruleTable.clear();
+ for (i=0; i<restrict_count; i++) {
+ std::vector<int> seq;
+ seq.clear();
+ seq.push_back(restricts[i].target_id);
+ for(j = 0; j<MAX_RULE_LENGTH && restricts[i].via[j]>-1; j++)
+ {
+ seq.push_back(restricts[i].via[j]);
+ }
+ ruleTable.push_back(make_pair(restricts[i].to_cost, seq));
+ }
+
+ GraphDefinition gdef;
+ int res = gdef.my_dijkstra(edges, edge_count, start_vertex, end_vertex, directed, has_reverse_cost, path, path_count, err_msg, ruleTable);
+
+
+ if (res < 0)
+ return res;
+ else
+ return EXIT_SUCCESS;
+ }
+ catch(std::exception& e) {
+ *err_msg = (char *) e.what();
+ return -1;
+ }
+ catch(...) {
+ *err_msg = (char *) "Caught unknown exception!";
+ return -1;
+ }
+}
+
+int trsp_edge_wrapper(
+ edge_t *edges,
+ unsigned int edge_count,
+ restrict_t *restricts,
+ int restrict_count,
+ int start_edge,
+ double start_pos,
+ int end_edge,
+ double end_pos,
+ bool directed,
+ bool has_reverse_cost,
+ path_element_t **path,
+ int *path_count,
+ char **err_msg
+ )
+{
+ try {
+
+ std::vector<PDVI> ruleTable;
+
+ int i, j;
+ ruleTable.clear();
+ for (i=0; i<restrict_count; i++) {
+ std::vector<int> seq;
+ seq.clear();
+ seq.push_back(restricts[i].target_id);
+ for(j = 0; j<MAX_RULE_LENGTH && restricts[i].via[j]>-1; j++)
+ {
+ seq.push_back(restricts[i].via[j]);
+ }
+ ruleTable.push_back(make_pair(restricts[i].to_cost, seq));
+ }
+
+ GraphDefinition gdef;
+ int res = gdef.my_dijkstra(edges, edge_count, start_edge, start_pos, end_edge, end_pos, directed, has_reverse_cost, path, path_count, err_msg, ruleTable);
+
+
+ if (res < 0)
+ return res;
+ else
+ return EXIT_SUCCESS;
+ }
+ catch(std::exception& e) {
+ *err_msg = (char *) e.what();
+ return -1;
+ }
+ catch(...) {
+ *err_msg = (char *) "Caught unknown exception!";
+ return -1;
+ }
+}
diff --git a/src/trsp/test/test.conf b/src/trsp/test/test.conf
index e348576..720778f 100644
--- a/src/trsp/test/test.conf
+++ b/src/trsp/test/test.conf
@@ -3,8 +3,8 @@
%main::tests = (
'any' => {
'comment' => 'TRSP test for any versions.',
- 'data' => ['trsp-any-00.data'],
- 'tests' => [qw(trsp-any-00 trsp-any-01 trsp-any-02 trsp-any-03)]
+ 'data' => ['trsp-any-00.data', 'trsp-issue244.data'],
+ 'tests' => [qw(trsp-any-00 trsp-any-01 trsp-any-02 trsp-any-03 trsp_vias-any-04 trsp-issue244)]
},
# 'vpg-vpgis' => {}, # for version specific tests
# '8-1' => {}, # for pg 8.x and postgis 1.x
diff --git a/src/trsp/test/trsp-any-00.rest b/src/trsp/test/trsp-any-00.result
similarity index 100%
rename from src/trsp/test/trsp-any-00.rest
rename to src/trsp/test/trsp-any-00.result
diff --git a/src/trsp/test/trsp-any-00.test b/src/trsp/test/trsp-any-00.test.sql
similarity index 100%
rename from src/trsp/test/trsp-any-00.test
rename to src/trsp/test/trsp-any-00.test.sql
diff --git a/src/trsp/test/trsp-any-01.rest b/src/trsp/test/trsp-any-01.result
similarity index 100%
rename from src/trsp/test/trsp-any-01.rest
rename to src/trsp/test/trsp-any-01.result
diff --git a/src/trsp/test/trsp-any-01.test b/src/trsp/test/trsp-any-01.test.sql
similarity index 74%
rename from src/trsp/test/trsp-any-01.test
rename to src/trsp/test/trsp-any-01.test.sql
index 7ff7963..f812f5a 100644
--- a/src/trsp/test/trsp-any-01.test
+++ b/src/trsp/test/trsp-any-01.test.sql
@@ -1,3 +1,4 @@
+set log_min_messages='NOTICE'; /** hack to force EDB to log so uses hack elog for test **/
select * from pgr_trsp(
'select eid as id, source::integer, target::integer, cost, reverse_cost from edges1',
1, -- node_id of start
diff --git a/src/trsp/test/trsp-any-02.rest b/src/trsp/test/trsp-any-02.result
similarity index 100%
rename from src/trsp/test/trsp-any-02.rest
rename to src/trsp/test/trsp-any-02.result
diff --git a/src/trsp/test/trsp-any-02.test b/src/trsp/test/trsp-any-02.test.sql
similarity index 100%
rename from src/trsp/test/trsp-any-02.test
rename to src/trsp/test/trsp-any-02.test.sql
diff --git a/src/trsp/test/trsp-any-03.rest b/src/trsp/test/trsp-any-03.result
similarity index 100%
rename from src/trsp/test/trsp-any-03.rest
rename to src/trsp/test/trsp-any-03.result
diff --git a/src/trsp/test/trsp-any-03.test b/src/trsp/test/trsp-any-03.test.sql
similarity index 80%
rename from src/trsp/test/trsp-any-03.test
rename to src/trsp/test/trsp-any-03.test.sql
index aa598ae..5f66fe1 100644
--- a/src/trsp/test/trsp-any-03.test
+++ b/src/trsp/test/trsp-any-03.test.sql
@@ -1,3 +1,4 @@
+set log_min_messages='NOTICE'; /** hack to force EDB to log so uses hack elog for test **/
select * from pgr_trsp(
'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
1, -- node_id of start
diff --git a/src/trsp/test/trsp-issue244.data b/src/trsp/test/trsp-issue244.data
new file mode 100644
index 0000000..73cc764
--- /dev/null
+++ b/src/trsp/test/trsp-issue244.data
@@ -0,0 +1,42 @@
+DROP TABLE IF EXISTS edge_table_i244 CASCADE;
+CREATE TABLE edge_table_i244 (
+ id serial,
+ dir character varying,
+ source integer,
+ target integer,
+ cost double precision,
+ reverse_cost double precision,
+ x1 double precision,
+ y1 double precision,
+ x2 double precision,
+ y2 double precision,
+ the_geom geometry
+);
+
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,0, 2,1);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES (-1, 1, 2,1, 3,1);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES (-1, 1, 3,1, 4,1);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,1, 2,2);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,1, 3,2);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 0,2, 1,2);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 1,2, 2,2);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,2, 3,2);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 3,2, 4,2);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,2, 2,3);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,2, 3,3);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 2,3, 3,3);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1,-1, 3,3, 4,3);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 2,3, 2,4);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 4,2, 4,3);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 4,1, 4,2);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 0.5,3.5, 1.999999999999,3.5);
+INSERT INTO edge_table_i244 (cost,reverse_cost,x1,y1,x2,y2) VALUES ( 1, 1, 3.5,2.3, 3.5,4);
+
+UPDATE edge_table_i244 SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)),
+dir = CASE WHEN (cost>0 and reverse_cost>0) THEN 'B' -- both ways
+WHEN (cost>0 and reverse_cost<0) THEN 'FT' -- direction of the LINESSTRING
+WHEN (cost<0 and reverse_cost>0) THEN 'TF' -- reverse direction
+ELSE '' END;
+
+SELECT pgr_createTopology('edge_table_i244',0.001);
+
diff --git a/src/trsp/test/trsp-issue244.result b/src/trsp/test/trsp-issue244.result
new file mode 100644
index 0000000..c40aaa7
--- /dev/null
+++ b/src/trsp/test/trsp-issue244.result
@@ -0,0 +1,6 @@
+0|7|6|1
+1|8|7|1
+2|5|8|1
+3|6|11|1
+4|11|13|1
+5|12|-1|0
diff --git a/src/trsp/test/trsp-issue244.test.sql b/src/trsp/test/trsp-issue244.test.sql
new file mode 100644
index 0000000..a780bc0
--- /dev/null
+++ b/src/trsp/test/trsp-issue244.test.sql
@@ -0,0 +1,2 @@
+set log_min_messages='NOTICE'; /** hack to force EDB to log so uses hack elog for test **/
+SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_trsp('SELECT id, source, target, cost FROM edge_table_i244',7, 12, false, false);
diff --git a/src/trsp/test/trsp_vias-any-04.result b/src/trsp/test/trsp_vias-any-04.result
new file mode 100644
index 0000000..4d0737d
--- /dev/null
+++ b/src/trsp/test/trsp_vias-any-04.result
@@ -0,0 +1,45 @@
+1|1|1|1|1
+2|1|2|4|1
+3|1|7|8|1
+4|2|8|8|1
+5|2|7|10|1
+6|2|10|14|1
+7|3|13|14|1
+8|3|10|10|1
+9|3|7|7|1
+10|3|6|6|1
+11|3|5|-1|0
+---------------------------
+1|1|-1|1|0.5
+2|1|2|4|1
+3|1|7|8|1
+4|1|8|11|1
+5|2|11|13|1
+6|2|12|15|1
+7|2|9|9|1
+8|2|8|8|1
+9|2|7|7|1
+10|2|6|6|0.5
+---------------------------
+1|1|-1|1|0.5
+2|1|2|4|1
+3|1|7|8|1
+4|1|8|11|1
+5|2|11|13|1
+6|2|12|15|1
+7|2|9|9|1
+8|2|8|8|1
+9|2|7|7|1
+10|2|6|6|0.5
+---------------------------
+1|1|-1|1|0.5
+2|1|2|4|1
+3|1|7|8|1
+4|1|8|11|1
+5|2|11|13|1
+6|2|12|15|1
+7|2|9|9|1
+8|2|8|8|1
+9|2|7|7|1
+10|2|6|6|0.5
+---------------------------
diff --git a/src/trsp/test/trsp_vias-any-04.test.sql b/src/trsp/test/trsp_vias-any-04.test.sql
new file mode 100644
index 0000000..6630fa9
--- /dev/null
+++ b/src/trsp/test/trsp_vias-any-04.test.sql
@@ -0,0 +1,40 @@
+set client_min_messages = NOTICE;
+
+select * from pgr_trspViaVertices(
+ 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
+ ARRAY[1,8,13,5]::integer[], -- array of vids
+ true, -- directed graph?
+ true, -- has_reverse_cost?
+ -- include the turn restrictions
+ 'select to_cost, teid as target_id, feid||coalesce('',''||via,'''') as via_path from restrictions1');
+
+\echo '---------------------------'
+select * from pgr_trspViaEdges(
+ 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
+ ARRAY[1,11,6]::integer[], -- array of eids
+ ARRAY[0.5, 0.5, 0.5]::float8[], -- array of pcts
+ true, -- directed graph?
+ true, -- has_reverse_cost?
+ -- include the turn restrictions
+ 'select to_cost, teid as target_id, feid||coalesce('',''||via,'''') as via_path from restrictions1');
+\echo '---------------------------'
+select * from pgr_trspViaEdges(
+ 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
+ ARRAY[1,11,6]::integer[], -- array of eids
+ ARRAY[0.5, 0.5, 0.5]::float8[], -- array of pcts
+ true, -- directed graph?
+ true, -- has_reverse_cost?
+ -- include the turn restrictions
+ 'select to_cost, teid as target_id, feid||coalesce('',''||via,'''') as via_path from restrictions1');
+\echo '---------------------------'
+select * from pgr_trspViaEdges(
+ 'select eid as id, source::integer, target::integer,cost, reverse_cost from edges1',
+ ARRAY[1,11,6]::integer[], -- array of eids
+ ARRAY[0.5, 0.5, 0.5]::float8[], -- array of pcts
+ true, -- directed graph?
+ true, -- has_reverse_cost?
+ -- include the turn restrictions
+ 'select to_cost, teid as target_id, feid||coalesce('',''||via,'''') as via_path from restrictions1');
+\echo '---------------------------'
+
+set client_min_messages = DEBUG;
diff --git a/src/tsp/sql/routing_tsp.sql b/src/tsp/sql/routing_tsp.sql
index e0580f6..730cf0c 100644
--- a/src/tsp/sql/routing_tsp.sql
+++ b/src/tsp/sql/routing_tsp.sql
@@ -19,5 +19,5 @@ CREATE OR REPLACE FUNCTION pgr_tsp(matrix float8[][], startpt integer, endpt int
--CREATE OR REPLACE FUNCTION pgr_tsp(matrix float8[][], startpt integer, OUT seq integer, OUT id integer)
RETURNS SETOF record
- AS '$libdir/librouting_tsp', 'tsp_matrix'
+ AS '$libdir/librouting-2.1', 'tsp_matrix'
LANGUAGE c IMMUTABLE STRICT;
diff --git a/src/tsp/src/CMakeLists.txt b/src/tsp/src/CMakeLists.txt
index 94e20f9..8dd7193 100644
--- a/src/tsp/src/CMakeLists.txt
+++ b/src/tsp/src/CMakeLists.txt
@@ -1,28 +1,34 @@
-set(LIBRARY_OUTPUT_PATH ../../../lib/)
-
-include_directories(${PGROUTING_INCLUDE_DIRECTORIES} ${POSTGRESQL_INCLUDE_DIR})
-if(WIN32)
- include_directories(${POSTGRESQL_INCLUDE_DIR}/port/win32)
-endif(WIN32)
-
-if(APPLE)
- set(LIBRARY_MODE_TARGET "MODULE")
-else(APPLE)
- set(LIBRARY_MODE_TARGET "SHARED")
-endif(APPLE)
-
-add_library(routing_tsp ${LIBRARY_MODE_TARGET} tsp2.c tsp.h tsplib.c)
-
-if(WIN32)
- if(MSVC)
- set_target_properties(routing_tsp PROPERTIES COMPILE_FLAGS "-DHAVE_GETHOSTNAME")
- endif(MSVC)
-endif(WIN32)
-
-if(APPLE)
- set_target_properties(routing_tsp
- PROPERTIES
- LINK_FLAGS "-bundle_loader ${POSTGRESQL_EXECUTABLE} -bundle")
-endif(APPLE)
-
-install(TARGETS routing_tsp DESTINATION ${LIBRARY_INSTALL_PATH})
+ADD_LIBRARY(tsp OBJECT
+ tsp2.c
+ tsplib.c
+)
+
+
+#set(LIBRARY_OUTPUT_PATH ../../../lib/)
+
+#include_directories(${PGROUTING_INCLUDE_DIRECTORIES} ${POSTGRESQL_INCLUDE_DIR})
+#if(WIN32)
+ #include_directories(${POSTGRESQL_INCLUDE_DIR}/port/win32)
+#endif(WIN32)
+
+#if(APPLE)
+ #set(LIBRARY_MODE_TARGET "MODULE")
+#else(APPLE)
+ #set(LIBRARY_MODE_TARGET "SHARED")
+#endif(APPLE)
+
+#add_library(routing_tsp ${LIBRARY_MODE_TARGET} tsp2.c tsp.h tsplib.c)
+
+#if(WIN32)
+ #if(MSVC)
+ #set_target_properties(routing_tsp PROPERTIES COMPILE_FLAGS "-DHAVE_GETHOSTNAME")
+ #endif(MSVC)
+#endif(WIN32)
+
+#if(APPLE)
+ #set_target_properties(routing_tsp
+ #PROPERTIES
+ #LINK_FLAGS "-bundle_loader ${POSTGRESQL_EXECUTABLE} -bundle")
+#endif(APPLE)
+
+#install(TARGETS routing_tsp DESTINATION ${LIBRARY_INSTALL_PATH})
diff --git a/src/tsp/src/OBSOLETE/tsp.c b/src/tsp/src/OBSOLETE/tsp.c
index 18e1667..3fb49ea 100644
--- a/src/tsp/src/OBSOLETE/tsp.c
+++ b/src/tsp/src/OBSOLETE/tsp.c
@@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
diff --git a/src/tsp/src/tsp.h b/src/tsp/src/tsp.h
index 4a12de6..2e86f11 100644
--- a/src/tsp/src/tsp.h
+++ b/src/tsp/src/tsp.h
@@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
@@ -26,7 +26,7 @@
#define DTYPE double
#include "postgres.h"
-#include "dijkstra.h"
+#include "../../common/src/pgr_types.h"
typedef struct point
{
diff --git a/src/tsp/src/tsp2.c b/src/tsp/src/tsp2.c
index 6977581..43e406e 100644
--- a/src/tsp/src/tsp2.c
+++ b/src/tsp/src/tsp2.c
@@ -13,13 +13,14 @@
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "utils/array.h"
+#include "utils/lsyscache.h"
#if PGSQL_VERSION > 92
#include "access/htup_details.h"
#endif
#include "fmgr.h"
-#ifdef PG_MODULE_MAGIC
+#ifndef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
@@ -42,7 +43,7 @@ PG_MODULE_MAGIC;
static DTYPE *get_pgarray(int *num, ArrayType *input)
{
- int ndims, *dims, *lbs;
+ int ndims, *dims; // , *lbs;
bool *nulls;
Oid i_eltype;
int16 i_typlen;
@@ -72,7 +73,7 @@ static DTYPE *get_pgarray(int *num, ArrayType *input)
/* get various pieces of data from the input array */
ndims = ARR_NDIM(input);
dims = ARR_DIMS(input);
- lbs = ARR_LBOUND(input);
+ // lbs = ARR_LBOUND(input);
if (ndims != 2 || dims[0] != dims[1]) {
elog(ERROR, "Error: matrix[num][num] in its definition.");
@@ -145,7 +146,7 @@ static int solve_tsp(DTYPE *matrix, int num, int start, int end, int **results)
int i;
int *ids;
DTYPE fit;
- char *err_msg;
+ char *err_msg = NULL;
DBG("In solve_tsp: num: %d, start: %d, end: %d", num, start, end);
@@ -210,7 +211,7 @@ tsp_matrix(PG_FUNCTION_ARGS)
int call_cntr;
int max_calls;
TupleDesc tuple_desc;
- AttInMetadata *attinmeta;
+ // AttInMetadata *attinmeta;
DTYPE *matrix;
int *tsp_res;
diff --git a/src/tsp/src/tsplib.c b/src/tsp/src/tsplib.c
index e4c064c..41e5af0 100644
--- a/src/tsp/src/tsplib.c
+++ b/src/tsp/src/tsplib.c
@@ -91,6 +91,8 @@ static int a;
static int b;
static int arr[55];
+int Rand();
+
void initRand (int seed)
{
int i, ii;
@@ -192,6 +194,7 @@ int findEulerianPath(TSP *tsp)
}
//DBG("findEulerianPath: 1");
+ k = -1;
j = -1;
d = maxd;
dis[0] = -1;
@@ -269,7 +272,7 @@ int findEulerianPath(TSP *tsp)
DTYPE pathLength (TSP *tsp)
{
- int i, j, k;
+ unsigned int i;
DTYPE len = 0;
int *iorder = tsp->iorder;
@@ -366,7 +369,7 @@ DTYPE getReverseCost (TSP *tsp, Path p)
void doReverse(TSP *tsp, Path p)
{
- int i, j, nswaps, first, last, tmp;
+ int i, nswaps, first, last, tmp;
int *iorder = tsp->iorder;
int n = tsp->n;
diff --git a/src/tsp/test/tsp-any-00.rest b/src/tsp/test/tsp-any-00.result
similarity index 100%
rename from src/tsp/test/tsp-any-00.rest
rename to src/tsp/test/tsp-any-00.result
diff --git a/src/tsp/test/tsp-any-00.test b/src/tsp/test/tsp-any-00.test.sql
similarity index 100%
rename from src/tsp/test/tsp-any-00.test
rename to src/tsp/test/tsp-any-00.test.sql
diff --git a/src/tsp/test/tsp-any-01.rest b/src/tsp/test/tsp-any-01.result
similarity index 100%
rename from src/tsp/test/tsp-any-01.rest
rename to src/tsp/test/tsp-any-01.result
diff --git a/src/tsp/test/tsp-any-01.test b/src/tsp/test/tsp-any-01.test.sql
similarity index 100%
rename from src/tsp/test/tsp-any-01.test
rename to src/tsp/test/tsp-any-01.test.sql
diff --git a/src/tsp/test/tsp-any-03.rest b/src/tsp/test/tsp-any-03.result
similarity index 100%
rename from src/tsp/test/tsp-any-03.rest
rename to src/tsp/test/tsp-any-03.result
diff --git a/src/tsp/test/tsp-any-03.test b/src/tsp/test/tsp-any-03.test.sql
similarity index 100%
rename from src/tsp/test/tsp-any-03.test
rename to src/tsp/test/tsp-any-03.test.sql
diff --git a/src/tsp/test/tsp-any-04.rest b/src/tsp/test/tsp-any-04.result
similarity index 100%
rename from src/tsp/test/tsp-any-04.rest
rename to src/tsp/test/tsp-any-04.result
diff --git a/src/tsp/test/tsp-any-04.test b/src/tsp/test/tsp-any-04.test.sql
similarity index 100%
rename from src/tsp/test/tsp-any-04.test
rename to src/tsp/test/tsp-any-04.test.sql
diff --git a/src/tsp/test/tsp-any-05.rest b/src/tsp/test/tsp-any-05.result
similarity index 100%
rename from src/tsp/test/tsp-any-05.rest
rename to src/tsp/test/tsp-any-05.result
diff --git a/src/tsp/test/tsp-any-05.test b/src/tsp/test/tsp-any-05.test.sql
similarity index 100%
rename from src/tsp/test/tsp-any-05.test
rename to src/tsp/test/tsp-any-05.test.sql
diff --git a/src/vrp_basic/CMakeLists.txt b/src/vrp_basic/CMakeLists.txt
new file mode 100644
index 0000000..db45096
--- /dev/null
+++ b/src/vrp_basic/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(PACKAGE_SQL_FILES "")
+add_subdirectory(sql)
+set(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
+
+subdirs(doc src test)
+
+
diff --git a/src/common/src/CMakeLists.txt b/src/vrp_basic/doc/CMakeLists.txt
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/vrp_basic/doc/CMakeLists.txt
diff --git a/doc/src/changelog/index.rst b/src/vrp_basic/doc/index.rst
old mode 100644
new mode 100755
similarity index 64%
copy from doc/src/changelog/index.rst
copy to src/vrp_basic/doc/index.rst
index 0534c0b..fa7c4fa
--- a/doc/src/changelog/index.rst
+++ b/src/vrp_basic/doc/index.rst
@@ -7,17 +7,14 @@
Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
****************************************************************************
-.. _change_log:
+.. _pgr_vrp_basic:
-Release Notes
+pgr_vrpOneDepot
===============================================================================
- - :ref:`changelog_2_0`
- - :ref:`changelog_1_x`
+No documentation available from the original developer
-.. toctree::
- :hidden:
-
- pgRouting 2.0 Release Notes <2_0>
- pgRouting 1.x Release Notes <1_x>
+.. warning:: this function is experimental and there is no assurance that it will work
+* :ref:`type_cost_result`
+* http://en.wikipedia.org/wiki/Vehicle_routing_problem
diff --git a/src/ksp/sql/CMakeLists.txt b/src/vrp_basic/sql/CMakeLists.txt
similarity index 70%
copy from src/ksp/sql/CMakeLists.txt
copy to src/vrp_basic/sql/CMakeLists.txt
index dd5c7d9..7fccc6e 100644
--- a/src/ksp/sql/CMakeLists.txt
+++ b/src/vrp_basic/sql/CMakeLists.txt
@@ -1,7 +1,8 @@
# Append in local scope
LIST(APPEND PACKAGE_SQL_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/routing_ksp.sql)
-
+ ${CMAKE_CURRENT_SOURCE_DIR}/routing_vrp.sql
+)
+
# set in parent scope
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
diff --git a/src/vrp_basic/sql/routing_vrp.sql b/src/vrp_basic/sql/routing_vrp.sql
new file mode 100644
index 0000000..3ac868b
--- /dev/null
+++ b/src/vrp_basic/sql/routing_vrp.sql
@@ -0,0 +1,23 @@
+-----------------------------------------------------------------------
+-- Core function for vrp with sigle depot computation
+-- See README for description
+-----------------------------------------------------------------------
+--
+--
+
+create or replace function pgr_vrpOneDepot(
+ order_sql text,
+ vehicle_sql text,
+ cost_sql text,
+ depot_id integer,
+
+ OUT oid integer,
+ OUT opos integer,
+ OUT vid integer,
+ OUT tarrival integer,
+ OUT tdepart integer)
+returns setof record as
+'$libdir/librouting-2.1', 'vrp'
+LANGUAGE c VOLATILE STRICT;
+
+
diff --git a/src/vrp_basic/src/CMakeLists.txt b/src/vrp_basic/src/CMakeLists.txt
new file mode 100644
index 0000000..ee21d95
--- /dev/null
+++ b/src/vrp_basic/src/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(vrp_basic OBJECT
+ VRP.c
+ VRP_core.cpp
+ VRP_Solver.cpp)
+
+
diff --git a/src/vrp_basic/src/Orders.txt b/src/vrp_basic/src/Orders.txt
new file mode 100644
index 0000000..f4b621a
--- /dev/null
+++ b/src/vrp_basic/src/Orders.txt
@@ -0,0 +1,102 @@
+ CUST_NO. XCOORD. YCOORD. DEMAND READY_TIME DUE_Time SERVICE_TIME
+ 1 40.00 50.00 0.00 0.00 240.00 0.00
+ 2 25.00 85.00 20.00 145.00 175.00 10.00
+ 3 22.00 75.00 30.00 50.00 80.00 10.00
+ 4 22.00 85.00 10.00 109.00 139.00 10.00
+ 5 20.00 80.00 40.00 141.00 171.00 10.00
+ 6 20.00 85.00 20.00 41.00 71.00 10.00
+ 7 18.00 75.00 20.00 95.00 125.00 10.00
+ 8 15.00 75.00 20.00 79.00 109.00 10.00
+ 9 15.00 80.00 10.00 91.00 121.00 10.00
+ 10 10.00 35.00 20.00 91.00 121.00 10.00
+ 11 10.00 40.00 30.00 119.00 149.00 10.00
+ 12 8.00 40.00 40.00 59.00 89.00 10.00
+ 13 8.00 45.00 20.00 64.00 94.00 10.00
+ 14 5.00 35.00 10.00 142.00 172.00 10.00
+ 15 5.00 45.00 10.00 35.00 65.00 10.00
+ 16 2.00 40.00 20.00 58.00 88.00 10.00
+ 17 0.00 40.00 20.00 72.00 102.00 10.00
+ 18 0.00 45.00 20.00 149.00 179.00 10.00
+ 19 44.00 5.00 20.00 87.00 117.00 10.00
+ 20 42.00 10.00 40.00 72.00 102.00 10.00
+ 21 42.00 15.00 10.00 122.00 152.00 10.00
+ 22 40.00 5.00 10.00 67.00 97.00 10.00
+ 23 40.00 15.00 40.00 92.00 122.00 10.00
+ 24 38.00 5.00 30.00 65.00 95.00 10.00
+ 25 38.00 15.00 10.00 148.00 178.00 10.00
+ 26 35.00 5.00 20.00 154.00 184.00 10.00
+ 27 95.00 30.00 30.00 115.00 145.00 10.00
+ 28 95.00 35.00 20.00 62.00 92.00 10.00
+ 29 92.00 30.00 10.00 62.00 92.00 10.00
+ 30 90.00 35.00 10.00 67.00 97.00 10.00
+ 31 88.00 30.00 10.00 74.00 104.00 10.00
+ 32 88.00 35.00 20.00 61.00 91.00 10.00
+ 33 87.00 30.00 10.00 131.00 161.00 10.00
+ 34 85.00 25.00 10.00 51.00 81.00 10.00
+ 35 85.00 35.00 30.00 111.00 141.00 10.00
+ 36 67.00 85.00 20.00 139.00 169.00 10.00
+ 37 65.00 85.00 40.00 43.00 73.00 10.00
+ 38 65.00 82.00 10.00 124.00 154.00 10.00
+ 39 62.00 80.00 30.00 75.00 105.00 10.00
+ 40 60.00 80.00 10.00 37.00 67.00 10.00
+ 41 60.00 85.00 30.00 85.00 115.00 10.00
+ 42 58.00 75.00 20.00 92.00 122.00 10.00
+ 43 55.00 80.00 10.00 33.00 63.00 10.00
+ 44 55.00 85.00 20.00 128.00 158.00 10.00
+ 45 55.00 82.00 10.00 64.00 94.00 10.00
+ 46 20.00 82.00 10.00 37.00 67.00 10.00
+ 47 18.00 80.00 10.00 113.00 143.00 10.00
+ 48 2.00 45.00 10.00 45.00 75.00 10.00
+ 49 42.00 5.00 10.00 151.00 181.00 10.00
+ 50 42.00 12.00 10.00 104.00 134.00 10.00
+ 51 72.00 35.00 30.00 116.00 146.00 10.00
+ 52 55.00 20.00 19.00 83.00 113.00 10.00
+ 53 25.00 30.00 3.00 52.00 82.00 10.00
+ 54 20.00 50.00 5.00 91.00 121.00 10.00
+ 55 55.00 60.00 16.00 139.00 169.00 10.00
+ 56 30.00 60.00 16.00 140.00 170.00 10.00
+ 57 50.00 35.00 19.00 130.00 160.00 10.00
+ 58 30.00 25.00 23.00 96.00 126.00 10.00
+ 59 15.00 10.00 20.00 152.00 182.00 10.00
+ 60 10.00 20.00 19.00 42.00 72.00 10.00
+ 61 15.00 60.00 17.00 155.00 185.00 10.00
+ 62 45.00 65.00 9.00 66.00 96.00 10.00
+ 63 65.00 35.00 3.00 52.00 82.00 10.00
+ 64 65.00 20.00 6.00 39.00 69.00 10.00
+ 65 45.00 30.00 17.00 53.00 83.00 10.00
+ 66 35.00 40.00 16.00 11.00 41.00 10.00
+ 67 41.00 37.00 16.00 133.00 163.00 10.00
+ 68 64.00 42.00 9.00 70.00 100.00 10.00
+ 69 40.00 60.00 21.00 144.00 174.00 10.00
+ 70 31.00 52.00 27.00 41.00 71.00 10.00
+ 71 35.00 69.00 23.00 180.00 210.00 10.00
+ 72 65.00 55.00 14.00 65.00 95.00 10.00
+ 73 63.00 65.00 8.00 30.00 60.00 10.00
+ 74 2.00 60.00 5.00 77.00 107.00 10.00
+ 75 20.00 20.00 8.00 141.00 171.00 10.00
+ 76 5.00 5.00 16.00 74.00 104.00 10.00
+ 77 60.00 12.00 31.00 75.00 105.00 10.00
+ 78 23.00 3.00 7.00 150.00 180.00 10.00
+ 79 8.00 56.00 27.00 90.00 120.00 10.00
+ 80 6.00 68.00 30.00 89.00 119.00 10.00
+ 81 47.00 47.00 13.00 192.00 222.00 10.00
+ 82 49.00 58.00 10.00 86.00 116.00 10.00
+ 83 27.00 43.00 9.00 42.00 72.00 10.00
+ 84 37.00 31.00 14.00 35.00 65.00 10.00
+ 85 57.00 29.00 18.00 96.00 126.00 10.00
+ 86 63.00 23.00 2.00 87.00 117.00 10.00
+ 87 21.00 24.00 28.00 87.00 117.00 10.00
+ 88 12.00 24.00 13.00 90.00 120.00 10.00
+ 89 24.00 58.00 19.00 67.00 97.00 10.00
+ 90 67.00 5.00 25.00 144.00 174.00 10.00
+ 91 37.00 47.00 6.00 86.00 116.00 10.00
+ 92 49.00 42.00 13.00 167.00 197.00 10.00
+ 93 53.00 43.00 14.00 14.00 44.00 10.00
+ 94 61.00 52.00 3.00 178.00 208.00 10.00
+ 95 57.00 48.00 23.00 95.00 125.00 10.00
+ 96 56.00 37.00 6.00 34.00 64.00 10.00
+ 97 55.00 54.00 26.00 132.00 162.00 10.00
+ 98 4.00 18.00 35.00 120.00 150.00 10.00
+ 99 26.00 52.00 9.00 46.00 76.00 10.00
+ 100 26.00 35.00 15.00 77.00 107.00 10.00
+ 101 31.00 67.00 3.00 180.00 210.00 10.00
\ No newline at end of file
diff --git a/src/vrp_basic/src/Tester.cpp b/src/vrp_basic/src/Tester.cpp
new file mode 100644
index 0000000..cb4d40e
--- /dev/null
+++ b/src/vrp_basic/src/Tester.cpp
@@ -0,0 +1,266 @@
+/*PGR
+
+Copyright (c) 2013 Khondoker Md. Razequl Islam
+ziboncsedu at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include "VRP_Solver.h"
+#include "Utils.h"
+
+char buff[1005];
+
+CVRPSolver solver;
+
+// Load orders from the order file. The first order represents the depot.
+// TODO: file names are hard coded, it should be changed to commandline argument.
+void loadOrders()
+{
+ FILE *fp = fopen("Orders.txt", "rt");
+ if(fp == NULL)
+ {
+ fprintf(stderr, "Order file not found!\n");
+ }
+ bool bGotDepot = false;
+ // OrderId XCord YCord Demand StartTime EndTime ServiceTime
+ while(fgets(buff, 1000, fp))
+ {
+ if(strlen(buff) == 0)
+ break;
+ StringTokenizer tokenizer;
+ tokenizer.parse(buff, " \t");
+ StringVector vecToken;
+ tokenizer.getTokens(vecToken);
+
+ if(vecToken.size() != 7)
+ continue;
+
+ if(!isdigit(vecToken[0][0]))
+ continue;
+
+ if (!bGotDepot)
+ {
+ // This order represents Deopot
+ CDepotInfo depot;
+ int id = atoi(vecToken[0].c_str());
+ depot.setDepotId(id);
+
+ Point pt;
+
+ pt.X = atof(vecToken[1].c_str());
+ pt.Y = atof(vecToken[2].c_str());
+
+ depot.setDepotLocation(pt);
+
+ int openTime = atoi(vecToken[4].c_str());
+ depot.setOpenTime(openTime);
+
+ int closeTime = atoi(vecToken[5].c_str());
+ depot.setCloseTime(closeTime);
+
+ solver.addDepot(depot);
+ bGotDepot = true;
+ }
+ else
+ {
+ // This is an order
+ COrderInfo order;
+ int id = atoi(vecToken[0].c_str());
+ order.setOrderId(id);
+
+ Point pt;
+
+ pt.X = atof(vecToken[1].c_str());
+ pt.Y = atof(vecToken[2].c_str());
+
+ order.setOrderLocation(pt);
+
+ int demand = atoi(vecToken[3].c_str());
+ order.setOrderUnit(demand);
+
+ int openTime = atoi(vecToken[4].c_str());
+ order.setOpenTime(openTime);
+
+ int closeTime = atoi(vecToken[5].c_str());
+ order.setCloseTime(closeTime);
+
+ int serviceTime = atoi(vecToken[6].c_str());
+ order.setServiceTime(serviceTime);
+
+ solver.addOrder(order);
+ }
+ }
+ fclose(fp);
+}
+
+// Load vehicles from vehicle file.
+// TODO: file names are hard coded, it should be changed to commandline argument.
+
+void loadVehicles()
+{
+ FILE *fp = fopen("Vehicles.txt", "rt");
+
+ if(fp == NULL)
+ {
+ fprintf(stderr, "Vehicle file not found!\n");
+ }
+ // VehicleId Capacity
+ // In terms of cost all the vehicle will have default cost of 1 for the first version
+ while(fgets(buff, 1000, fp))
+ {
+ if(strlen(buff) == 0)
+ break;
+ StringTokenizer tokenizer;
+ tokenizer.parse(buff, " \t");
+ StringVector vecToken;
+ tokenizer.getTokens(vecToken);
+
+ if(vecToken.size() != 2)
+ continue;
+
+ if(!isdigit(vecToken[0][0]))
+ continue;
+
+ CVehicleInfo vehicle;
+
+ int id = atoi(vecToken[0].c_str());
+ vehicle.setId(id);
+
+ int capcity = atoi(vecToken[1].c_str());
+ vehicle.setCapacity(capcity);
+
+ vehicle.setCostPerKM(1);
+
+ solver.addVehicle(vehicle);
+ }
+ fclose(fp);
+}
+
+// Load the cost matrix
+// TODO: file names are hard coded, it should be changed to commandline argument.
+void loadDistanceMatrix()
+{
+ FILE *fp = fopen("Distance.txt", "rt");
+ if(fp == NULL)
+ {
+ fprintf(stderr, "Cost file not found!\n");
+ return;
+ }
+
+ // From To Cost
+ while(fgets(buff, 1000, fp))
+ {
+ if(strlen(buff) == 0)
+ break;
+ StringTokenizer tokenizer;
+ tokenizer.parse(buff, " \t");
+ StringVector vecToken;
+ tokenizer.getTokens(vecToken);
+
+ if(vecToken.size() != 3)
+ continue;
+
+ if(!isdigit(vecToken[0][0]))
+ continue;
+
+ int fromId = atoi(vecToken[0].c_str());
+ int toId = atoi(vecToken[1].c_str());
+ CostPack cpack;
+ cpack.cost = cpack.distance = atof(vecToken[2].c_str());
+ cpack.traveltime = cpack.cost;
+
+ if(fromId == 1)
+ solver.addDepotToOrderCost(fromId, toId, cpack);
+ else if(toId == 1)
+ solver.addOrderToDepotCost(fromId, toId, cpack);
+ else
+ solver.addOrderToOrderCost(fromId, toId, cpack);
+ }
+ fclose(fp);
+}
+
+// Print the solution to a file.
+// TODO: Currently prints on a fixed file. Later the file name will be taken as a command line argument
+
+bool print_solution(std::string strError)
+{
+ FILE *fp = fopen("result.txt", "wt");
+ if(fp == NULL)
+ {
+ strError = "Could not open file";
+ return false;
+ }
+ CSolutionInfo solution;
+ bool bOK = solver.getSolution(solution, strError);
+ if(bOK == false)
+ return false;
+
+ int totalRoute = solution.getTourInfoVector().size();
+ CTourInfo ctour;
+
+ fprintf(fp, "Total Number of Route: %d\n", totalRoute);
+ fprintf(fp, "Total Cost: %.3lf\n", solution.getTotalCost());
+ fprintf(fp, "Total Distance: %.3lf\n", solution.getTotalDistance());
+ fprintf(fp, "Total TravelTime: %.3lf\n", solution.getTotalTravelTime());
+
+ for(int i = 0; i < totalRoute; i++)
+ {
+ ctour = solution.getTour(i);
+ fprintf(fp, "Route No. %d: \n", i + 1);
+ fprintf(fp, "Vehicle Id: %d\n", ctour.getVehicleId());
+ fprintf(fp, "Starting Depot Id: %d\n", ctour.getStartDepot());
+ fprintf(fp, "End Depot Id: %d\n", ctour.getEndDepot());
+
+ std::vector<int> vecOrder = ctour.getOrderVector();
+ int totalOrder = vecOrder.size();
+ fprintf(fp, "Visited Order Ids: ");
+ for(int j = 0; j < totalOrder; j++)
+ {
+ if(j > 0)
+ fprintf(fp, " ");
+ fprintf(fp, "%d", vecOrder[j]);
+ if(j < totalOrder - 1)
+ fprintf(fp, ",");
+ }
+ fprintf(fp, "\n");
+ }
+
+ fclose(fp);
+ return true;
+}
+
+int main()
+{
+ loadOrders();
+ loadVehicles();
+ loadDistanceMatrix();
+
+ std::string strError;
+ bool bIsOK = solver.solveVRP(strError);
+
+ if(!bIsOK)
+ {
+ fprintf(stderr, "Error Occurred: %s\n", strError.c_str());
+ }
+ else
+ {
+ print_solution(strError);
+ }
+
+
+ return 0;
+}
diff --git a/src/vrp_basic/src/Utils.h b/src/vrp_basic/src/Utils.h
new file mode 100644
index 0000000..91b4444
--- /dev/null
+++ b/src/vrp_basic/src/Utils.h
@@ -0,0 +1,108 @@
+/*PGR
+
+Copyright (c) 2013 Khondoker Md. Razequl Islam
+ziboncsedu at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <string>
+#include <map>
+#include <vector>
+#include <queue>
+#include <iostream>
+
+
+
+typedef std::vector<int> IntVector;
+typedef std::vector<double> DoubleVector;
+typedef std::vector<std::string> StringVector;
+
+
+class StringOperation
+{
+
+public:
+
+ static std::string TRIMWHITESPACE(std::string strInput)
+ {
+ std::string strOut = strInput;
+ std::string strWht = " \f\n\r\t\v";
+
+ strOut.erase(0,strOut.find_first_not_of(strWht));
+ strOut.erase(strOut.find_last_not_of(strWht) + 1);
+ return strOut;
+ };
+};
+
+class StringTokenizer
+{
+public:
+ StringTokenizer()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ vecTokens.clear();
+ strInput = "";
+ }
+
+ bool parse(std::string strInput, std::string chDelim)
+ {
+ char *ptr = strtok((char *)strInput.c_str(), chDelim.c_str());
+ while(ptr != NULL)
+ {
+ std::string str = ptr;
+ vecTokens.push_back(str);
+ ptr = strtok(NULL, chDelim.c_str());
+ }
+ return true;
+ }
+
+ size_t getTokenCount()
+ {
+ return vecTokens.size();
+ }
+
+ bool getToken(std::string& strToken, long iTokenIndex)
+ {
+ long lTokenCount = vecTokens.size();
+ if(iTokenIndex < 0 || iTokenIndex < lTokenCount)
+ {
+ strToken = vecTokens[iTokenIndex];
+ return true;
+ }
+ return false;
+ }
+
+ bool getTokens(StringVector& vecTokensRef)
+ {
+ vecTokensRef = vecTokens;
+ return true;
+ }
+
+private:
+ std::string strInput;
+ StringVector vecTokens;
+
+};
+
+#endif
diff --git a/src/vrp_basic/src/VRP.c b/src/vrp_basic/src/VRP.c
new file mode 100644
index 0000000..2ede79d
--- /dev/null
+++ b/src/vrp_basic/src/VRP.c
@@ -0,0 +1,922 @@
+/*PGR
+
+Copyright (c) 2013 Khondoker Md. Razequl Islam
+ziboncsedu at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include "VRP.h"
+
+#include "postgres.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "catalog/pg_type.h"
+#if PGSQL_VERSION > 92
+#include "access/htup_details.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <search.h>
+
+#include "string.h"
+#include "math.h"
+
+#include "fmgr.h"
+
+
+
+#undef qsort
+
+//-------------------------------------------------------------------------
+
+/*
+ * Define this to have profiling enabled
+ */
+//#define PROFILE
+
+#ifdef PROFILE
+#include <sys/time.h>
+
+struct timeval prof_astar, prof_store, prof_extract, prof_total;
+long proftime[5];
+long profipts1, profipts2, profopts;
+
+#define profstart(x) do { gettimeofday(&x, NULL); } while (0);
+#define profstop(n, x) do { struct timeval _profstop; \
+ long _proftime; \
+ gettimeofday(&_profstop, NULL); \
+ _proftime = ( _profstop.tv_sec*1000000+_profstop.tv_usec) - \
+ ( x.tv_sec*1000000+x.tv_usec); \
+ elog(NOTICE, \
+ "PRF(%s) %lu (%f ms)", \
+ (n), \
+ _proftime, _proftime / 1000.0); \
+ } while (0);
+
+#else
+
+#define profstart(x) do { } while (0);
+#define profstop(n, x) do { } while (0);
+
+#endif // PROFILE
+
+
+// ------------------------------------------------------------------------
+
+Datum vrp(PG_FUNCTION_ARGS);
+
+#undef DEBUG
+//#define DEBUG 1
+
+#ifdef DEBUG
+#define DBG(format, arg...) \
+ elog(NOTICE, format , ## arg)
+#else
+#define DBG(format, arg...) do { ; } while (0)
+#endif
+
+// The number of tuples to fetch from the SPI cursor at each iteration
+#define TUPLIMIT 1000
+
+#ifndef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+typedef struct vehicle_columns
+{
+ int vehicle_id;
+ int capacity;
+
+} vehicle_columns_t;
+
+typedef struct order_columns
+{
+ int id;
+ int order_unit;
+ int open_time;
+ int close_time;
+ int service_time;
+
+ int x;
+ int y;
+} order_columns_t;
+
+typedef struct distance_columns
+{
+ int src_id;
+ int dest_id;
+ int cost;
+ int distance;
+ int traveltime;
+} distance_columns_t;
+
+
+//float DISTANCE[MAX_TOWNS][MAX_TOWNS];
+//float x[MAX_TOWNS],y[MAX_TOWNS];
+int total_tuples;
+
+static char *
+text2char(text *in)
+{
+ char *out = (char*)palloc(VARSIZE(in));
+
+ memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
+ out[VARSIZE(in) - VARHDRSZ] = '\0';
+ return out;
+}
+
+static int
+finish(int *code)
+{
+ *code = SPI_finish();
+ if (*code != SPI_OK_FINISH )
+ {
+ elog(ERROR,"couldn't disconnect from SPI");
+ return -1 ;
+ }
+ return 0;
+}
+
+
+
+static int
+fetch_distance_columns(SPITupleTable *tuptable, distance_columns_t *distance_columns)
+{
+ DBG("Fetching distance");
+
+ distance_columns->src_id = SPI_fnumber(SPI_tuptable->tupdesc, "src_id");
+ distance_columns->dest_id = SPI_fnumber(SPI_tuptable->tupdesc, "dest_id");
+ distance_columns->cost = SPI_fnumber(SPI_tuptable->tupdesc, "cost");
+ distance_columns->distance = SPI_fnumber(SPI_tuptable->tupdesc, "distance");
+ distance_columns->traveltime = SPI_fnumber(SPI_tuptable->tupdesc, "traveltime");
+ if (distance_columns->src_id == SPI_ERROR_NOATTRIBUTE ||
+ distance_columns->dest_id == SPI_ERROR_NOATTRIBUTE ||
+ distance_columns->cost == SPI_ERROR_NOATTRIBUTE ||
+ distance_columns->distance == SPI_ERROR_NOATTRIBUTE ||
+ distance_columns->traveltime == SPI_ERROR_NOATTRIBUTE)
+ {
+ elog(ERROR, "Error, query must return columns "
+ "'src_id', 'dest_id', 'cost', 'distance' and 'traveltime'");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void
+fetch_distance(HeapTuple *tuple, TupleDesc *tupdesc,
+ distance_columns_t *distance_columns, vrp_cost_element_t *dist, int t)
+{
+ Datum binval;
+ bool isnull;
+
+ DBG("fetch_distance: src_id col:%i", distance_columns->src_id);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, distance_columns->src_id, &isnull);
+
+ DBG("back from SPI_getbinval for src_id");
+ DBG("binval=%i", binval);
+
+ if (isnull)
+ elog(ERROR, "src_id contains a null value");
+
+ dist->src_id = DatumGetInt32(binval);
+
+ DBG("back from DatumGetInt32");
+ DBG("src_id=%i", dist->src_id);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, distance_columns->dest_id, &isnull);
+ if (isnull)
+ elog(ERROR, "dest_id contains a null value");
+
+ dist->dest_id = DatumGetInt32(binval);
+
+ DBG("dest_id=%i", dist->dest_id);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, distance_columns->cost, &isnull);
+
+ if (isnull)
+ elog(ERROR, "cost contains a null value");
+
+ dist->cost = DatumGetFloat8(binval);
+
+ DBG("cost=%lf", dist->cost);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, distance_columns->distance, &isnull);
+ if (isnull)
+ elog(ERROR, "distance contains a null value");
+
+ dist->distance = DatumGetFloat8(binval);
+
+ DBG("distance=%lf", dist->distance);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, distance_columns->traveltime, &isnull);
+
+ if (isnull)
+ elog(ERROR, "traveltime contains a null value");
+
+ dist->traveltime = DatumGetFloat8(binval);
+
+ DBG("traveltime=%lf", dist->traveltime);
+
+ //DBG("dist[%i][%i] = %f\n", from_point, to_point, value);
+
+
+ //DBG("dist[%i(%i:%i)][%i(%i:%i)] = %f\n", from, from_order, from_point, to, to_order, to_point, *(dist + (num_rows * from) + to));
+
+}
+
+static int
+fetch_order_columns(SPITupleTable *tuptable, order_columns_t *order_columns)
+{
+ DBG("Fetching order");
+
+ //order_columns->id = SPI_fnumber(SPI_tuptable->tupdesc, "id");
+ order_columns->id = SPI_fnumber(SPI_tuptable->tupdesc, "id");
+ order_columns->order_unit = SPI_fnumber(SPI_tuptable->tupdesc, "order_unit");
+ order_columns->open_time = SPI_fnumber(SPI_tuptable->tupdesc, "open_time");
+ order_columns->close_time = SPI_fnumber(SPI_tuptable->tupdesc, "close_time");
+ order_columns->service_time = SPI_fnumber(SPI_tuptable->tupdesc, "service_time");
+ order_columns->x = SPI_fnumber(SPI_tuptable->tupdesc, "x");
+ order_columns->y = SPI_fnumber(SPI_tuptable->tupdesc, "y");
+ if (//order_columns->id == SPI_ERROR_NOATTRIBUTE ||
+ order_columns->id == SPI_ERROR_NOATTRIBUTE ||
+ order_columns->open_time == SPI_ERROR_NOATTRIBUTE ||
+ order_columns->order_unit == SPI_ERROR_NOATTRIBUTE ||
+ order_columns->close_time == SPI_ERROR_NOATTRIBUTE ||
+ order_columns->service_time == SPI_ERROR_NOATTRIBUTE ||
+ order_columns->x == SPI_ERROR_NOATTRIBUTE ||
+ order_columns->y == SPI_ERROR_NOATTRIBUTE
+ )
+ {
+ // elog(ERROR, "Error, query must return columns "
+ // "'id', 'order_id', 'pu_time', 'do_time', 'pu_time_window', 'do_time_window', 'from_x', 'to_x', 'from_y', 'to_y' and 'size'");
+ elog(ERROR, "Error, query must return columns "
+ //"'id',
+ "'id', 'order_unit', 'open_time', 'close_time', 'service_time', 'x', 'y'");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+fetch_order(HeapTuple *tuple, TupleDesc *tupdesc,
+ order_columns_t *order_columns, vrp_orders_t *order, int t)
+{
+ Datum binval;
+ bool isnull;
+
+ DBG("inside fetch_order\n");
+
+ //binval = SPI_getbinval(*tuple, *tupdesc, order_columns->id, &isnull);
+ //
+ // DBG("got binval\n");
+ //
+ //if (isnull)
+ // elog(ERROR, "id contains a null value");
+ //
+ //order->id = DatumGetInt32(binval);
+ order->id = t+1;
+
+ DBG("id = %i\n", order->id);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, order_columns->id, &isnull);
+ if (isnull)
+ elog(ERROR, "order_id contains a null value");
+
+ order->id = DatumGetInt32(binval);
+
+ DBG("order_id = %i\n", order->id);
+
+
+ binval = SPI_getbinval(*tuple, *tupdesc, order_columns->order_unit, &isnull);
+ if (isnull)
+ elog(ERROR, "order_unit contains a null value");
+
+ order->order_unit = DatumGetInt32(binval);
+
+ DBG("order_unit = %i\n", order->order_unit);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, order_columns->open_time, &isnull);
+ if (isnull)
+ elog(ERROR, "open_time contains a null value");
+
+ order->open_time = DatumGetInt32(binval);
+
+ DBG("open_time = %i\n", order->open_time);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, order_columns->close_time, &isnull);
+ if (isnull)
+ elog(ERROR, "close_time contains a null value");
+
+ order->close_time = DatumGetInt32(binval);
+
+ DBG("close_time = %d\n", order->close_time);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, order_columns->service_time, &isnull);
+ if (isnull)
+ elog(ERROR, "service_time contains a null value");
+
+ order->service_time = DatumGetInt32(binval);
+
+ DBG("service_time = %d\n", order->service_time);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, order_columns->x, &isnull);
+ if (isnull)
+ elog(ERROR, "x contains a null value");
+
+ order->x = DatumGetFloat8(binval);
+
+ DBG("x = %f\n", order->x);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, order_columns->y, &isnull);
+ if (isnull)
+ elog(ERROR, "y contains a null value");
+
+ order->y = DatumGetFloat8(binval);
+
+ DBG("doUT = %f\n", order->y);
+
+}
+
+static int
+fetch_vehicle_columns(SPITupleTable *tuptable, vehicle_columns_t *vehicle_columns)
+{
+ DBG("Fetching order");
+
+ vehicle_columns->vehicle_id = SPI_fnumber(SPI_tuptable->tupdesc, "vehicle_id");
+ vehicle_columns->capacity = SPI_fnumber(SPI_tuptable->tupdesc, "capacity");
+
+ if (vehicle_columns->vehicle_id == SPI_ERROR_NOATTRIBUTE ||
+ vehicle_columns->capacity == SPI_ERROR_NOATTRIBUTE
+ )
+ {
+ elog(ERROR, "Error, query must return columns "
+ "'id' and 'capacity'");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+fetch_vehicle(HeapTuple *tuple, TupleDesc *tupdesc,
+ vehicle_columns_t *vehicle_columns, vrp_vehicles_t *vehicle, int t)
+{
+ Datum binval;
+ bool isnull;
+
+ DBG("inside fetch_vehicle\n");
+
+ //binval = SPI_getbinval(*tuple, *tupdesc, vehicle_columns->id, &isnull);
+ //DBG("Got id\n");
+ //
+ //if (isnull)
+ // elog(ERROR, "id contains a null value");
+ //
+ //vehicle->id = DatumGetInt32(binval);
+
+
+ binval = SPI_getbinval(*tuple, *tupdesc, vehicle_columns->vehicle_id, &isnull);
+ DBG("Got vehicle_id\n");
+
+ if (isnull)
+ elog(ERROR, "vehicle_id contains a null value");
+
+ vehicle->id = DatumGetInt32(binval);
+
+ DBG("vehicle_id = %i\n", vehicle->id);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, vehicle_columns->capacity, &isnull);
+ if (isnull)
+ elog(ERROR, "capacity contains a null value");
+
+ vehicle->capacity = DatumGetInt32(binval);
+
+ DBG("capacity = %f\n", vehicle->capacity);
+
+}
+
+static int conn(int *SPIcode)
+{
+ int res = 0;
+
+ *SPIcode = SPI_connect();
+
+ if (*SPIcode != SPI_OK_CONNECT)
+ {
+ elog(ERROR, "vrp: couldn't open a connection to SPI");
+ res = -1;
+ }
+
+ return res;
+}
+
+static int prepare_query(Portal *SPIportal, char* sql)
+{
+ int res = 0;
+
+ void* SPIplan = SPI_prepare(sql, 0, NULL);
+
+ if (SPIplan == NULL)
+ {
+ elog(ERROR, "vrp: couldn't create query plan via SPI");
+ res = -1;
+ }
+
+ if ((*SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL)
+ {
+ elog(ERROR, "vrp: SPI_cursor_open('%s') returns NULL", sql);
+ res = -1;
+ }
+
+ return res;
+}
+
+static int solve_vrp(char* orders_sql, char* vehicles_sql,
+ char* dist_sql,
+ int depot,
+ vrp_result_element_t** path, int *path_count)
+{
+ int SPIcode;
+
+ Portal SPIportal_o;
+ Portal SPIportal_v;
+ Portal SPIportal_d;
+ // Portal SPIportal_p;
+
+ bool moredata = TRUE;
+ int ntuples;
+
+ int order_num, vehicle_num, dist_num;
+
+ vrp_vehicles_t *vehicles=NULL;
+ vehicle_columns_t vehicle_columns = {.vehicle_id = -1, .capacity = -1};
+
+ vrp_orders_t *orders=NULL;
+ order_columns_t order_columns = {.id = -1, .order_unit = -1, .open_time = -1, .close_time = -1, .service_time = -1, .x = -1, .y = -1};
+
+ vrp_cost_element_t *costs=NULL;
+ distance_columns_t distance_columns = {.src_id = -1, .dest_id = -1, .cost = -1, .distance = -1, .traveltime = -1};
+
+ char *err_msg = NULL;
+ int ret = -1;
+
+ // int z = 0;
+
+ // int tt, cc;
+ // double dx, dy;
+ // float fit=0.0;
+
+ int prep = -1, con = -1;
+
+ //int total_tuples = 0;
+ total_tuples = 0;
+ order_num = 0;
+ vehicle_num = 0;
+
+ DBG("start solve_vrp\n");
+
+ //vrp_orders_t depot_ord = {id:0, order_id:depot, from:depot_point, to:depot_point};
+ //orders = palloc(1 * sizeof(vrp_orders_t));
+ //orders[0] = depot_ord;
+
+ con = conn(&SPIcode);
+
+ if (con < 0)
+ return ret;
+
+
+ // Fetching orders
+
+ DBG("calling prepare_query for orders_sql");
+
+ prep = prepare_query(&SPIportal_o, orders_sql);
+
+ if (prep < 0)
+ return ret;
+
+ DBG("Query: %s\n",orders_sql);
+ DBG("Query executed\n");
+
+ DBG("Orders before: %i\n", order_num);
+
+ while (moredata == TRUE)
+ {
+ SPI_cursor_fetch(SPIportal_o, TRUE, TUPLIMIT);
+
+ DBG("cursor fetched\n");
+
+ if (order_columns.id == -1)
+ {
+ if (fetch_order_columns(SPI_tuptable, &order_columns) == -1)
+ return finish(&SPIcode);
+ }
+
+ ntuples = SPI_processed;
+
+ order_num += ntuples;
+
+ DBG("Tuples: %i\n", order_num);
+
+ if (!orders)
+ orders = palloc(order_num * sizeof(vrp_orders_t));
+ else
+ orders = repalloc(orders, (order_num + 1) * sizeof(vrp_orders_t));
+
+ if (orders == NULL)
+ {
+ elog(ERROR, "Out of memory");
+ return finish(&SPIcode);
+ }
+
+ if (ntuples > 0)
+ {
+ int t;
+ SPITupleTable *tuptable = SPI_tuptable;
+ TupleDesc tupdesc = SPI_tuptable->tupdesc;
+
+ DBG("Got tuple desc\n");
+
+ for (t = 0; t < ntuples; t++)
+ {
+ HeapTuple tuple = tuptable->vals[t];
+ //DBG("Before order fetched [%i]\n", order_num - ntuples + t);
+ fetch_order(&tuple, &tupdesc, &order_columns,
+ &orders[order_num - ntuples + t], t);
+
+ //&orders[t+1], t);
+ DBG("Order fetched\n");
+ }
+
+ SPI_freetuptable(tuptable);
+ }
+ else
+ {
+ moredata = FALSE;
+ }
+ }// end of fetching orders
+ //finish(&SPIcode_o);
+/*
+ int o;
+ for(o=0; o<order_num+1;++o)
+ {
+ elog(NOTICE, "ORDERS[%i] = {id=%i, open=%i, close=%i, service=%i}", o, orders[o].id, orders[o].open_time, orders[o].close_time, orders[o].service_time);
+ }
+*/
+ DBG ("order_num = %i", order_num);
+
+ //qsort (orders, order_num+1, sizeof (vrp_orders_t), order_cmp);
+
+
+ // Fetching vehicles
+
+ moredata = TRUE;
+ prep = prepare_query(&SPIportal_v, vehicles_sql);
+
+ if (prep < 0)
+ return ret;
+
+ DBG("Query: %s\n",vehicles_sql);
+ DBG("Query executed\n");
+
+
+ while (moredata == TRUE)
+ {
+ SPI_cursor_fetch(SPIportal_v, TRUE, TUPLIMIT);
+
+ if (vehicle_columns.vehicle_id == -1)
+ {
+ if (fetch_vehicle_columns(SPI_tuptable, &vehicle_columns) == -1)
+ return finish(&SPIcode);
+ }
+
+
+ ntuples = SPI_processed;
+
+ vehicle_num += ntuples;
+
+ DBG("Tuples: %i\n", vehicle_num);
+
+ if (!vehicles)
+ vehicles = palloc(vehicle_num * sizeof(vrp_vehicles_t));
+ else
+ vehicles = repalloc(vehicles, vehicle_num * sizeof(vrp_vehicles_t));
+
+ if (vehicles == NULL)
+ {
+ elog(ERROR, "Out of memory");
+ return finish(&SPIcode);
+ }
+
+ if (ntuples > 0)
+ {
+ int t;
+ SPITupleTable *tuptable = SPI_tuptable;
+ TupleDesc tupdesc = SPI_tuptable->tupdesc;
+
+ DBG("Got tuple desc\n");
+
+ for (t = 0; t < ntuples; t++)
+ {
+ HeapTuple tuple = tuptable->vals[t];
+ DBG("Before vehicle fetched\n");
+ fetch_vehicle(&tuple, &tupdesc, &vehicle_columns,
+ &vehicles[vehicle_num - ntuples + t], t);
+ DBG("Vehicle fetched\n");
+ }
+
+ SPI_freetuptable(tuptable);
+ }
+ else
+ {
+ moredata = FALSE;
+ }
+ }// end of fetching vehicles
+ //finish(&SPIcode_v);
+
+ //double dist[order_num*2+1][order_num*2+1];
+
+ // Fetching distances
+
+ dist_num = 0;
+ moredata = TRUE;
+ prep = prepare_query(&SPIportal_d, dist_sql);
+
+ if (prep < 0)
+ return ret;
+
+ DBG("Query: %s\n",dist_sql);
+ DBG("Query executed\n");
+
+ while (moredata == TRUE)
+ {
+ SPI_cursor_fetch(SPIportal_d, TRUE, TUPLIMIT);
+
+ if (distance_columns.src_id == -1)
+ {
+ if (fetch_distance_columns(SPI_tuptable, &distance_columns) == -1)
+ return finish(&SPIcode);
+ }
+
+ ntuples = SPI_processed;
+ dist_num += ntuples;
+
+ DBG("Tuples: %i\n", vehicle_num);
+
+ if (!costs)
+ costs = palloc(dist_num * sizeof(vrp_cost_element_t));
+ else
+ costs = repalloc(costs, dist_num * sizeof(vrp_cost_element_t));
+
+ if (costs == NULL)
+ {
+ elog(ERROR, "Out of memory");
+ return finish(&SPIcode);
+ }
+
+ if (ntuples > 0)
+ {
+ int t;
+ SPITupleTable *tuptable = SPI_tuptable;
+ TupleDesc tupdesc = SPI_tuptable->tupdesc;
+
+ DBG("Got tuple desc\n");
+
+ for (t = 0; t < ntuples; t++)
+ {
+ HeapTuple tuple = tuptable->vals[t];
+ DBG("Before distance fetched\n");
+ fetch_distance(&tuple, &tupdesc, &distance_columns,
+ &costs[dist_num - ntuples + t], t);
+ DBG("Distance fetched\n");
+ }
+
+ SPI_freetuptable(tuptable);
+ }
+ else
+ {
+ moredata = FALSE;
+ }
+ }// end of fetching distances
+
+
+ DBG("Calling vrp\n");
+
+ profstop("extract", prof_extract);
+ profstart(prof_vrp);
+
+ DBG("Total orders: %i\n", order_num);
+ DBG("Total vehicles: %i\n", vehicle_num);
+
+
+ //qsort (orders, order_num+1, sizeof (vrp_orders_t), order_cmp_asc);
+
+
+#ifdef DEBUG
+ int o;
+ for(o=0; o<order_num+1;++o)
+ {
+ DBG("ORDERS[%i] = {id=%i, open=%i, close=%i, service=%i}", o, orders[o].id, orders[o].open_time, orders[o].close_time, orders[o].service_time);
+ }
+#endif
+
+
+
+ //itinerary = (vrp_result_element_t *)palloc(sizeof(vrp_result_element_t)*(order_num*2-1)*vehicle_num);
+
+ DBG("Calling vrp solver\n");
+ //elog(NOTICE, "Calling find_vrp_solution: vehicles: %i, orders: %i, dists: %i, depot: %i", vehicle_num, order_num, dist_num, depot);
+
+ ret = find_vrp_solution(vehicles, vehicle_num,
+ orders, order_num,
+ costs, dist_num,
+ depot,
+ path, path_count, &err_msg);
+
+ //ret = -1;
+ total_tuples = *path_count;
+ //elog(NOTICE, "vrp solved! ret: %d, path_count: %d", ret, *path_count);
+ // int pp;
+/*
+ for(pp = 0; pp < *path_count; pp++)
+ {
+ elog(NOTICE, "Row: %d: %d %d %d %d %d", pp, (*path)[pp].order_id, (*path)[pp].order_pos, (*path)[pp].vehicle_id, (*path)[pp].arrival_time, (*path)[pp].depart_time);
+ }
+*/
+ DBG("vrp solved! ret: %d, path_count: %d", ret, path_count);
+ //DBG("Score: %f\n", fit);
+
+ profstop("vrp", prof_vrp);
+ profstart(prof_store);
+
+ DBG("Profile changed and ret is %i", ret);
+
+ if (ret < 0)
+ {
+ //elog(ERROR, "Error computing path: %s", err_msg);
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED), errmsg("Error computing path: %s", err_msg)));
+ }
+
+ //pfree(vehicles);
+ //pfree(orders);
+ return finish(&SPIcode);
+}
+
+PG_FUNCTION_INFO_V1(vrp);
+Datum
+vrp(PG_FUNCTION_ARGS)
+{
+ FuncCallContext *funcctx;
+ int call_cntr;
+ int max_calls;
+ TupleDesc tuple_desc;
+ vrp_result_element_t *path;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL())
+ {
+ MemoryContext oldcontext;
+ //int path_count;
+ // int ret=-1;
+ int path_count = 0;
+
+ // XXX profiling messages are not thread safe
+ profstart(prof_total);
+ profstart(prof_extract);
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+
+ //path = (vrp_result_element_t *)palloc(sizeof(vrp_result_element_t)*(MAX_ORDERS-1)*2*MAX_VEHICLES);
+
+
+ DBG("Calling solve_vrp ...");
+
+ // ret =
+ solve_vrp(//text2char(PG_GETARG_TEXT_P(0)), // points sql
+ text2char(PG_GETARG_TEXT_P(0)), // orders sql
+ text2char(PG_GETARG_TEXT_P(1)), // vehicles sql
+ text2char(PG_GETARG_TEXT_P(2)), // distances query
+ PG_GETARG_INT32(3), // depot id
+ &path, &path_count);
+
+ DBG("Back from solve_vrp, path_count:%d", path_count);
+ //elog(NOTICE, "Back from solve_vrp, path_count:%d", path_count);
+
+ /* total number of tuples to be returned */
+ //DBG("Counting tuples number\n");
+
+ funcctx->max_calls = total_tuples;
+
+ funcctx->user_fctx = path;
+
+ /* Build a tuple descriptor for our result type */
+ 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 = BlessTupleDesc(tuple_desc);
+
+ /*
+ * generate attribute metadata needed later to produce tuples from raw
+ * C strings
+ */
+ //attinmeta = TupleDescGetAttInMetadata(tuple_desc);
+ //funcctx->attinmeta = attinmeta;
+
+ MemoryContextSwitchTo(oldcontext);
+ //elog(NOTICE, "table formed");
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ call_cntr = funcctx->call_cntr;
+ max_calls = funcctx->max_calls;
+ tuple_desc = funcctx->tuple_desc;
+
+ path = (vrp_result_element_t *)funcctx->user_fctx;
+
+ //elog(NOTICE, "Point 1");
+ //DBG("Trying to allocate some memory\n");
+ //DBG("call_cntr = %i, max_calls = %i\n", call_cntr, max_calls);
+
+ if (call_cntr < max_calls) /* do when there is more left to send */
+ {
+ HeapTuple tuple;
+ Datum result;
+ Datum *values;
+ char* nulls;
+
+ values = palloc(5 * sizeof(Datum));
+ nulls = palloc(5 * sizeof(char));
+
+ values[0] = Int32GetDatum(path[call_cntr].order_id); // order id
+ nulls[0] = ' ';
+ values[1] = Int32GetDatum(path[call_cntr].order_pos); // order pos
+ nulls[1] = ' ';
+ values[2] = Int32GetDatum(path[call_cntr].vehicle_id); // vehicle id
+ nulls[2] = ' ';
+ values[3] = Int32GetDatum(path[call_cntr].arrival_time); // arrival time
+ nulls[3] = ' ';
+ //values[4] = TimeTzADTPGetDatum(&path[call_cntr].time);
+ values[4] = Int32GetDatum(path[call_cntr].depart_time); // departure time
+ nulls[4] = ' ';
+
+ // DBG("Heap making\n");
+ //elog(NOTICE,"Result %d %d %d", call_cntr, path[call_cntr].order_id, max_calls);
+ tuple = heap_formtuple(tuple_desc, values, nulls);
+
+ //DBG("Datum making\n");
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ //DBG("Trying to free some memory\n");
+
+ /* clean up */
+ pfree(values);
+ pfree(nulls);
+
+
+ SRF_RETURN_NEXT(funcctx, result);
+ }
+ else /* do when there is no more left */
+ {
+
+ DBG("Ending function\n");
+ profstop("store", prof_store);
+ profstop("total", prof_total);
+ DBG("Profiles stopped\n");
+
+ free(path);
+
+ DBG("Itinerary cleared\n");
+
+ SRF_RETURN_DONE(funcctx);
+ }
+}
diff --git a/src/vrp_basic/src/VRP.h b/src/vrp_basic/src/VRP.h
new file mode 100644
index 0000000..92b5f3c
--- /dev/null
+++ b/src/vrp_basic/src/VRP.h
@@ -0,0 +1,84 @@
+/*PGR
+
+Copyright (c) 2013 Khondoker Md. Razequl Islam
+ziboncsedu at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#ifndef _VRP_H
+#define _VRP_H
+
+#include "postgres.h"
+
+
+typedef struct vrp_vehicles
+{
+ int id;
+ int capacity;
+
+} vrp_vehicles_t;
+
+
+typedef struct vrp_orders
+{
+ int id;
+ int order_unit;
+ int open_time;
+ int close_time;
+ int service_time;
+
+ float8 x;
+ float8 y;
+
+} vrp_orders_t;
+
+typedef struct vrp_cost_element
+{
+ int src_id;
+ int dest_id;
+ int cost;
+ int distance;
+ int traveltime;
+
+}vrp_cost_element_t;
+
+
+typedef struct vrp_result_element
+{
+ int order_id;
+ int order_pos;
+ int vehicle_id;
+ int arrival_time;
+ int depart_time;
+} vrp_result_element_t;
+
+
+#ifdef __cplusplus
+extern "C"
+#endif
+
+int find_vrp_solution(vrp_vehicles_t *vehicles, int vehicle_count,
+ vrp_orders_t *orders, int order_count,
+ vrp_cost_element_t *costmatrix, int cost_count,
+ int depot_id,
+ vrp_result_element_t **result, int *result_count, char **err_msg);
+
+#ifdef __cplusplus
+extern "C"
+#endif
+
+#endif
diff --git a/src/vrp_basic/src/VRP_Solver.cpp b/src/vrp_basic/src/VRP_Solver.cpp
new file mode 100644
index 0000000..6b77352
--- /dev/null
+++ b/src/vrp_basic/src/VRP_Solver.cpp
@@ -0,0 +1,1034 @@
+/*PGR
+
+Copyright (c) 2013 Khondoker Md. Razequl Islam
+ziboncsedu at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include "VRP_Solver.h"
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
+#undef PGR_LOGGER_ON
+#define PGR_LOGGER_LOC
+#define PGR_LOGGER_FILE "/tmp/vrp-debug.log"
+#include "../../common/src/pgr_logger.h"
+
+#define DOUBLE_MAX 1e50
+
+bool operator != (const CVehicleInfo& cur, const CVehicleInfo& that)
+{
+ return(cur.m_iVehicleId != that.m_iVehicleId);
+}
+
+bool operator== (const CTourInfo& cur, const CTourInfo& that)
+{
+ if(cur.m_vehicleInfo != that.m_vehicleInfo)
+ return false;
+ if(cur.m_viOrderIds.size() != that.m_viOrderIds.size())
+ return false;
+ int tot = cur.m_viOrderIds.size();
+ for(int i = 0; i < tot; i++)
+ {
+ if(cur.m_viOrderIds[i] != that.m_viOrderIds[i])
+ return false;
+ }
+ return true;
+}
+
+bool operator == (const CMoveInfo& cur, const CMoveInfo& that)
+{
+ if(!(cur.m_vInitialTour == that.m_vInitialTour))
+ return false;
+ if(!(cur.m_vModifiedTour == that.m_vModifiedTour))
+ return false;
+ return true;
+}
+
+
+
+CVehicleInfo::CVehicleInfo()
+{
+ m_iCurrentLoad = 0;
+}
+CVehicleInfo::~CVehicleInfo()
+{
+}
+
+bool CVehicleInfo::loadUnit(int lUnit)
+{
+ if(m_iCurrentLoad + lUnit > m_iCapacity)
+ return false;
+ m_iCurrentLoad += lUnit;
+ return true;
+}
+
+COrderInfo::COrderInfo()
+{
+}
+COrderInfo::~COrderInfo()
+{
+}
+
+CDepotInfo::CDepotInfo()
+{
+}
+CDepotInfo::~CDepotInfo()
+{
+}
+
+CTourInfo::CTourInfo()
+{
+ m_dTotalCost = 0.0;
+ m_dTotalDistance = 0.0;
+ m_dTotalTraveltime = 0.0;
+}
+CTourInfo::~CTourInfo()
+{
+}
+
+bool CTourInfo::insertOrder(int orderId, int pos)
+{
+ m_viOrderIds.insert(m_viOrderIds.begin() + pos, orderId);
+ return true;
+}
+
+int CTourInfo::getRemainingCapacity()
+{
+ return(m_vehicleInfo.getRemainingCapacity());
+}
+
+bool CTourInfo::removeOrder(int pos)
+{
+ m_viOrderIds.erase(m_viOrderIds.begin() + pos);
+ return true;
+}
+
+void CTourInfo::updateCost(double cost, double distance, double travelTime)
+{
+ m_dTotalCost = cost;
+ m_dTotalDistance = distance;
+ m_dTotalTraveltime = travelTime;
+}
+
+CSolutionInfo::CSolutionInfo()
+{
+}
+CSolutionInfo::~CSolutionInfo()
+{
+}
+
+void CSolutionInfo::replaceTour(CTourInfo curTour)
+{
+ unsigned int i;
+ for(i = 0; i < m_vtourAll.size(); i++)
+ {
+ if(m_vtourAll[i].getVehicleId() == curTour.getVehicleId())
+ {
+ m_vtourAll[i] = curTour;
+ return;
+ }
+ }
+ return;
+}
+
+void CSolutionInfo::replaceTourAt(int index, CTourInfo curTour)
+{
+ if(index < 0 || (unsigned int) index >= m_vtourAll.size())
+ return;
+ m_vtourAll[index] = curTour;
+}
+
+bool CSolutionInfo::init(std::vector<int> vecOrder, int iTotalOrder, std::vector<int> vecVehicle)
+{
+ m_vUnservedOrderId = vecOrder;
+ m_iTotalOrders = iTotalOrder;
+ m_vUnusedVehicles = vecVehicle;
+
+ m_vtourAll.clear();
+ m_iVehicleUsed = 0;
+ m_iOrdersServed = 0;
+ m_iTotalOrders = 0;
+ m_dTotalCost = 0;
+ m_dTotalDistance = 0;
+ m_dTotalTravelTime = 0;
+ return true;
+}
+
+bool CSolutionInfo::addTour(CTourInfo& tour)
+{
+ m_vtourAll.push_back(tour);
+ int vid = tour.getVehicleId();
+ std::vector<int>::iterator it;
+ it = std::find(m_vUnusedVehicles.begin(), m_vUnusedVehicles.end(), vid);
+ if(it != m_vUnusedVehicles.end())
+ {
+ m_vUnusedVehicles.erase(it);
+ }
+ m_iVehicleUsed++;
+ m_dTotalDistance += tour.getDistance();
+ m_dTotalTravelTime += tour.getTravelTime();
+ m_dTotalCost += tour.getCost();
+
+ std::vector<int> vecOrders = tour.getOrderVector();
+
+ m_iOrdersServed += vecOrders.size();
+
+ for(unsigned int i = 0; i < vecOrders.size(); i++)
+ {
+ int oid = vecOrders[i];
+ it = std::find(m_vUnservedOrderId.begin(), m_vUnservedOrderId.end(), oid);
+ if(it != m_vUnservedOrderId.end())
+ {
+ m_vUnservedOrderId.erase(it);
+ }
+ }
+
+ return true;
+}
+
+CMoveInfo::CMoveInfo()
+{
+
+}
+CMoveInfo::~CMoveInfo()
+{
+
+}
+
+void CMoveInfo::setInitialTour(CTourInfo tourData)
+{
+ m_vInitialTour.clear();
+ m_vInitialTour.push_back(tourData);
+}
+
+void CMoveInfo::setInitialTour(CTourInfo tourData1, CTourInfo tourData2)
+{
+ m_vInitialTour.clear();
+ m_vInitialTour.push_back(tourData1);
+ m_vInitialTour.push_back(tourData2);
+}
+
+void CMoveInfo::setModifiedTour(CTourInfo tourData)
+{
+ m_vModifiedTour.clear();
+ m_vModifiedTour.push_back(tourData);
+}
+
+void CMoveInfo::setModifiedTour(CTourInfo tourData1, CTourInfo tourData2)
+{
+ m_vModifiedTour.clear();
+ m_vModifiedTour.push_back(tourData1);
+ m_vModifiedTour.push_back(tourData2);
+}
+
+void CMoveInfo::getInitialTour(CTourInfo &tourData)
+{
+ tourData = m_vInitialTour[0];
+}
+
+void CMoveInfo::getInitialTour(CTourInfo &tourData1, CTourInfo &tourData2)
+{
+ tourData1 = m_vInitialTour[0];
+ tourData2 = m_vInitialTour[1];
+}
+
+bool CMoveInfo::getModifiedTourAt(int index, CTourInfo& tourInfo)
+{
+ if(index < 0 || (unsigned int) index >= m_vModifiedTour.size())
+ return false;
+ tourInfo = m_vModifiedTour[index];
+ return true;
+}
+
+
+
+CVRPSolver::CVRPSolver()
+{
+ // set a seed for the random number generator
+ // so it will generate consistent results for the same input
+ // otherwise we can not test it :(
+ srand(1726354);
+}
+CVRPSolver::~CVRPSolver()
+{
+}
+
+bool CVRPSolver::solveVRP(std::string& strError)
+{
+// if(!m_bIsReadyToSolve)
+// {
+// strError = "Scenario is not ready to solve. Configure all parameter";
+// return false;
+// }
+ PGR_LOG("Inside Solve VRP");
+ std::vector<int> vecOrders, vecVehicles;
+ for(unsigned int i = 0; i < m_vOrderInfos.size(); i++)
+ {
+ vecOrders.push_back(m_vOrderInfos[i].getOrderId());
+ }
+
+ for(unsigned int i = 0; i < m_vVehicleInfos.size(); i++)
+ {
+ vecVehicles.push_back(m_vVehicleInfos[i].getId());
+ }
+
+ m_solutionFinal.init(vecOrders, vecOrders.size(), vecVehicles);
+ PGR_LOG("After init solution");
+ int iAttemtCount = 0;
+ while(iAttemtCount < MAXIMUM_TRY)
+ {
+ bool bUpdateFound = false;
+ CSolutionInfo initialSolution = generateInitialSolution();
+ PGR_LOG("After Generate initial Solution");
+ iAttemtCount++;
+ bUpdateFound = updateFinalSolution(initialSolution);
+ PGR_LOG("After update final Solution");
+ bool bUpdateFound2 = tabuSearch(initialSolution);
+ PGR_LOG("After Tabu Search");
+ if((bUpdateFound == true) || (bUpdateFound2 == true))
+ {
+ iAttemtCount = 0;
+ }
+ }
+ m_bIsSolutionReady = true;
+ return true;
+
+}
+
+CSolutionInfo CVRPSolver::generateInitialSolution()
+{
+ CSolutionInfo initialSolution;
+ PGR_LOG("Inside gen ini sol");
+ std::vector<int> vecOrders, vecVehicles;
+ for(unsigned int i = 0; i < m_vOrderInfos.size(); i++)
+ {
+ vecOrders.push_back(m_vOrderInfos[i].getOrderId());
+ }
+
+ for(unsigned int i = 0; i < m_vVehicleInfos.size(); i++)
+ {
+ vecVehicles.push_back(m_vVehicleInfos[i].getId());
+ }
+
+ initialSolution.init(vecOrders, vecOrders.size(), vecVehicles);
+
+ int iUnusedVehicles = initialSolution.getUnusedVehicleCount();
+ int iUnservedOrders = initialSolution.getUnservedOrderCount();//m_viUnservedOrderIndex.size();
+ PGR_LOG("before while");
+ while( iUnusedVehicles && iUnservedOrders )
+ {
+ CTourInfo curTour;
+
+ int vehicleIndex = rand() % iUnusedVehicles--;
+ int vehicleInd = m_mapVehicleIdToIndex[initialSolution.getUnusedVehicleAt(vehicleIndex)];
+ curTour.setVehicleInfo(m_vVehicleInfos[vehicleInd]);//m_viUnusedVehicleIndex[vehicleIndex]
+ initialSolution.removeVehicle(vehicleIndex);
+
+ curTour.setStartDepot(m_vDepotInfos[0].getDepotId());
+ curTour.setEndDepot(m_vDepotInfos[0].getDepotId());
+
+ //use a random seed to start to tour. (we can use better approach in future)
+
+ bool insertAvailable = true;
+
+ while( insertAvailable )
+ {
+ insertAvailable = false;
+ std::pair<int,int> PotentialInsert; // first = insert_index, second = removed_order_index;
+ std::pair<int,double> bestInsert = std::make_pair(-1,DOUBLE_MAX);//first = order_insert_index, second = cost;
+
+ for(int i = 0;i<iUnservedOrders;++i)
+ {
+ int orderInd = m_mapOrderIdToIndex[initialSolution.getUnservedOrderAt(i)];
+ COrderInfo curOrder = m_vOrderInfos[orderInd];
+ std::pair<int,double> curInsert = getPotentialInsert(curTour, curOrder);
+
+ if( curInsert.second < bestInsert.second )
+ {
+ insertAvailable = true;
+ bestInsert = curInsert;
+ PotentialInsert = std::make_pair(curInsert.first,i);
+ }
+ }
+ if( insertAvailable )
+ {
+ if(insertOrder(curTour, initialSolution.getUnservedOrderAt(PotentialInsert.second), PotentialInsert.first))
+ {
+ iUnservedOrders--;
+ initialSolution.removeOrder(PotentialInsert.second);
+ }
+ }
+ }
+
+ initialSolution.addTour(curTour);
+ }
+
+ return initialSolution;
+}
+
+bool CVRPSolver::updateFinalSolution(CSolutionInfo& curSolution)
+{
+ bool callUpdate = false;
+ if ( curSolution.getOrderServed() > m_solutionFinal.getOrderServed() )
+ {
+ callUpdate = true;
+ }
+ else if ( curSolution.getOrderServed() == m_solutionFinal.getOrderServed() )
+ {
+ if ( curSolution.getTotalCost() < m_solutionFinal.getTotalCost() )
+ {
+ callUpdate = true;
+ }
+ else if (curSolution.getTotalCost() == m_solutionFinal.getTotalCost() )
+ {
+ if ( curSolution.getTotalTravelTime() < m_solutionFinal.getTotalTravelTime() )
+ {
+ callUpdate = true;
+ }
+ else if ( curSolution.getTotalTravelTime() == m_solutionFinal.getTotalTravelTime() )
+ {
+ if ( curSolution.getTotalDistance() < m_solutionFinal.getTotalDistance() )
+ {
+ callUpdate = true;
+ }
+ }
+ }
+ }
+ if (callUpdate)
+ {
+ //m_iStepsSinceLastSolution = 0;
+ m_solutionFinal = curSolution;
+
+ //clear map and delete objects
+ //m_mpTabuCount.clear();
+ //for (std::map< CVRPTWMove*,int >::iterator it = m_mpMoveFrequency.begin();it!=m_mpMoveFrequency.end();++it)
+ //{
+ // delete (*it).first;
+ //}
+ //m_mpMoveFrequency.clear();
+ return true;
+ }
+ return false;
+}
+
+std::pair<int,double> CVRPSolver::getPotentialInsert(CTourInfo& curTour, COrderInfo& curOrder)
+{
+ std::pair<int,double> bestInsert = std::make_pair(-1,DOUBLE_MAX);
+ if( curOrder.getOrderUnit() > curTour.getRemainingCapacity() )
+ {
+ return bestInsert;
+ }
+ //check if ith position insert is fisible.
+ std::vector<int> vecOrderId = curTour.getOrderVector();
+ for(unsigned int i = 0; i <= vecOrderId.size();++i)
+ {
+ CostPack costToOrder, costFromOrder;
+
+ if(!i)
+ {
+ costToOrder = getDepotToOrderCost( curTour.getStartDepot(), curOrder.getOrderId());
+ }
+ else costToOrder = getOrderToOrderCost( vecOrderId[i-1], curOrder.getOrderId());
+
+ double dArrivalTime = costToOrder.traveltime + curTour.getStartTime(i);
+
+ if( dArrivalTime > curOrder.getCloseTime() )
+ {
+ continue;
+ }
+
+ if (i == vecOrderId.size())
+ {
+ costFromOrder = getOrderToDepotCost( curOrder.getOrderId(), curTour.getEndDepot() );
+ }
+ else costFromOrder = getOrderToOrderCost( curOrder.getOrderId(), vecOrderId[i] );
+
+ dArrivalTime += curOrder.getServiceTime() + costFromOrder.traveltime;
+
+ if( i < vecOrderId.size() && dArrivalTime > m_vOrderInfos[m_mapOrderIdToIndex[vecOrderId[i]]].getCloseTime())
+ {
+ continue;
+ }
+
+ CostPack totalCost = getCostForInsert(curTour, curOrder, i);
+
+
+ if( totalCost.cost < bestInsert.second )
+ {
+ bestInsert = std::make_pair(i,totalCost.cost);
+ }
+ }
+ return bestInsert;
+}
+
+bool CVRPSolver::tabuSearch(CSolutionInfo& curSolution)
+{
+ m_bFoundOptimal = false;
+ updateFinalSolution(curSolution);
+
+ int numberOfSearch = 0;
+ m_iGeneratedSolutionCount = 0;
+ m_iStepsSinceLastSolution = 0;
+
+ while( numberOfSearch < TOTAL_NUMBER_OF_SEARCH )
+ {
+ //applyBestMoveInCurrentSolution(curSolution, identifyPotentialMove(curSolution) );
+ insertUnservedOrders(curSolution);
+ //attemptFeasibleNodeExchange(curSolution);
+ attempVehicleExchange(curSolution);
+ ++numberOfSearch;
+ }
+ return false;
+}
+
+void CVRPSolver::applyBestMoveInCurrentSolution(CSolutionInfo& curSolution, CMoveInfo& bestMove)
+{
+ ++m_iGeneratedSolutionCount;
+ ++m_iStepsSinceLastSolution;
+
+ updateTabuCount(bestMove);
+
+ int totalTour = bestMove.getModifiedTourCount();
+ for(int i = 0;i<totalTour;++i)
+ {
+ CTourInfo tourInfo;
+ bool bIsValid = bestMove.getModifiedTourAt(i, tourInfo);
+
+ if(bIsValid)
+ curSolution.replaceTour(tourInfo);
+ }
+ updateFinalSolution(curSolution);
+
+}
+
+void CVRPSolver::insertUnservedOrders(CSolutionInfo& curSolution)
+{
+ ++m_iGeneratedSolutionCount;
+ ++m_iStepsSinceLastSolution;
+ bool insertAvailable = true;
+ CMoveInfo curMove;
+ int totalUnservedOrder = m_vOrderInfos.size() - curSolution.getOrderServed();
+
+ while( insertAvailable && totalUnservedOrder > 0 )
+ {
+ int insertTourId = -1;
+ insertAvailable = false;
+ int totalTour = curSolution.getTourInfoVector().size();
+ std::pair<int,int> PotentialInsert; // first = insert_index, second = removed_customer_index;
+ std::pair<int,double> bestInsert = std::make_pair(-1,DOUBLE_MAX);//first = customer_insert_index, second = cost;
+
+ for(int j = 0;j<totalTour;++j)
+ {
+ CTourInfo curTour = curSolution.getTour(j);
+ curMove.setInitialTour(curTour);
+
+ for(int i = 0;i<totalUnservedOrder;++i)
+ {
+ int ordIndex = m_mapOrderIdToIndex[curSolution.getUnservedOrderAt(i)];
+ COrderInfo curOrder = m_vOrderInfos[ordIndex];
+ std::pair<int,double> curInsert = getPotentialInsert(curTour, curOrder);
+
+ insertOrder(curTour, i,curInsert.first);
+ curMove.setModifiedTour(curTour);
+ curMove.getInitialTour(curTour);
+
+ //check if current move is tabu.
+ if( isTabuMove(curMove) )
+ {
+ continue;
+ }
+
+ if( curInsert.second < bestInsert.second )
+ {
+ insertTourId = j;
+ insertAvailable = true;
+ bestInsert = curInsert;
+ PotentialInsert = std::make_pair(curInsert.first,i);
+ }
+ }
+ }
+ if( insertAvailable )
+ {
+ totalUnservedOrder--;
+ curMove.setInitialTour(curSolution.getTour(insertTourId));
+
+ addOrderAtTour(curSolution, insertTourId,
+ PotentialInsert.first,
+ PotentialInsert.second);
+
+ curMove.setModifiedTour(curSolution.getTour(insertTourId));
+ this->updateTabuCount(curMove);
+ this->updateFinalSolution(curSolution);//this->evaluateCurrentSolution();
+ }
+ }
+
+}
+
+bool CVRPSolver::addDepot(CDepotInfo depotInfo)
+{
+ int id = depotInfo.getDepotId();
+ if(m_mapDepotIdToIndex.find(id) != m_mapDepotIdToIndex.end())
+ return false;
+ m_mapDepotIdToIndex.insert(std::make_pair(id, m_vDepotInfos.size()));
+ m_vDepotInfos.push_back(depotInfo);
+
+ return true;
+}
+
+bool CVRPSolver::addOrder(COrderInfo orderInfo)
+{
+ int id = orderInfo.getOrderId();
+ if(m_mapOrderIdToIndex.find(id) != m_mapOrderIdToIndex.end())
+ {
+ return false;
+ }
+ int index = m_vOrderInfos.size();
+ m_mapOrderIdToIndex.insert(std::make_pair(id, index));
+ m_vOrderInfos.push_back(orderInfo);
+ m_viUnservedOrderIndex.push_back(index);
+ return true;
+}
+
+bool CVRPSolver::addVehicle(CVehicleInfo vehicleInfo)
+{
+ int id = vehicleInfo.getId();
+ if(m_mapVehicleIdToIndex.find(id) != m_mapVehicleIdToIndex.end())
+ {
+ return false;
+ }
+ int index = m_vVehicleInfos.size();
+ m_mapVehicleIdToIndex.insert(std::make_pair(id, index));
+ m_vVehicleInfos.push_back(vehicleInfo);
+ m_viUnusedVehicleIndex.push_back(index);
+ return true;
+}
+
+bool CVRPSolver::addDepotToOrderCost(int depotId, int orderId, CostPack cost)
+{
+ PII depo_order = std::make_pair(depotId, orderId);
+ if(m_mapDepotToOrderrCost.find(depo_order) != m_mapDepotToOrderrCost.end())
+ {
+ return false;
+ }
+ m_mapDepotToOrderrCost.insert(make_pair(depo_order, cost));
+ return true;
+}
+
+bool CVRPSolver::addOrderToDepotCost(int depotId, int orderId, CostPack cost)
+{
+ PII depo_order = std::make_pair(orderId, depotId);
+ if(m_mapOrderToDepotCost.find(depo_order) != m_mapOrderToDepotCost.end())
+ {
+ return false;
+ }
+ m_mapOrderToDepotCost.insert(std::make_pair(depo_order, cost));
+ return true;
+}
+
+bool CVRPSolver::addOrderToOrderCost(int firstOrder, int secondOrder, CostPack cost)
+{
+ PII order_order = std::make_pair(firstOrder, secondOrder);
+ if(m_mapOrderToOrderCost.find(order_order) != m_mapOrderToOrderCost.end())
+ {
+ return false;
+ }
+ m_mapOrderToOrderCost.insert(std::make_pair(order_order, cost));
+ return true;
+}
+
+bool CVRPSolver::getSolution(CSolutionInfo& solution, std::string& strError)
+{
+ if(m_bIsSolutionReady == true)
+ {
+ solution = m_solutionFinal;
+ return true;
+ }
+ else
+ {
+ bool ret = solveVRP(strError);
+ if(ret == true)
+ {
+ solution = m_solutionFinal;
+ return true;
+ }
+ return false;
+ }
+}
+
+CostPack CVRPSolver::getDepotToOrderCost(int depotId, int orderId)
+{
+ PII depo_order = std::make_pair(depotId, orderId);
+
+ if(m_mapDepotToOrderrCost.find(depo_order) != m_mapDepotToOrderrCost.end())
+ {
+ return(m_mapDepotToOrderrCost[depo_order]);
+ }
+ CostPack ret;
+ ret.cost = ret.distance = ret.traveltime = 1e15;
+ return ret;
+}
+
+CostPack CVRPSolver::getOrderToOrderCost(int orderId1, int orderId2)
+{
+ PII order_order = std::make_pair(orderId1, orderId2);
+
+ if(m_mapOrderToOrderCost.find(order_order) != m_mapOrderToOrderCost.end())
+ {
+ return(m_mapOrderToOrderCost[order_order]);
+ }
+ CostPack ret;
+ ret.cost = ret.distance = ret.traveltime = 1e15;
+ return ret;
+}
+
+
+CostPack CVRPSolver::getOrderToDepotCost(int depotId, int orderId)
+{
+ PII depo_order = std::make_pair(orderId, depotId);
+
+ if(m_mapOrderToDepotCost.find(depo_order) != m_mapOrderToDepotCost.end())
+ {
+ return(m_mapOrderToDepotCost[depo_order]);
+ }
+ CostPack ret;
+ ret.cost = ret.distance = ret.traveltime = 1e15;
+ return ret;
+}
+
+bool CVRPSolver::insertOrder(CTourInfo& tourInfo, int orderId, int pos)
+{
+ if(pos < 0 || (unsigned int) pos > tourInfo.getOrderVector().size())
+ return false;
+
+ int orderIndex = m_mapOrderIdToIndex[orderId];
+ if(!tourInfo.getVehicleInfo().loadUnit(m_vOrderInfos[orderIndex].getOrderUnit()))
+ return false;
+ tourInfo.insertOrder(orderId, pos);
+
+ if(!updateTourCosts(tourInfo))
+ {
+ tourInfo.removeOrder(pos);
+ return false;
+ }
+
+ return true;
+}
+
+bool CVRPSolver::updateTourCosts(CTourInfo& tourInfo)
+{
+ std::vector<int> vecOrderId = tourInfo.getOrderVector();
+ std::vector<int> vecStartTimes;
+
+ double dCost, dDistance, dTravelTime;
+ dCost = dDistance = dTravelTime = 0.0;
+
+ CostPack cPack = getDepotToOrderCost(tourInfo.getStartDepot(), vecOrderId[0]);
+
+ dCost += cPack.cost;
+ dDistance += cPack.distance;
+
+ int ind = m_mapOrderIdToIndex[vecOrderId[0]];
+ vecStartTimes.push_back(0);
+
+ if(dTravelTime + cPack.traveltime > m_vOrderInfos[ind].getCloseTime())
+ return false;
+
+ dTravelTime = max(dTravelTime + cPack.traveltime + m_vOrderInfos[ind].getServiceTime(),
+ m_vOrderInfos[ind].getOpenTime() + m_vOrderInfos[ind].getServiceTime());
+ vecStartTimes.push_back(ceil(dTravelTime));
+
+ unsigned int i;
+ for(i = 1; i < vecOrderId.size(); i++)
+ {
+ cPack = getOrderToOrderCost(vecOrderId[i - 1], vecOrderId[i]);
+ dCost += cPack.cost;
+ dDistance += cPack.distance;
+
+ ind = m_mapOrderIdToIndex[vecOrderId[i]];
+
+ if(dTravelTime + cPack.traveltime > m_vOrderInfos[ind].getCloseTime())
+ return false;
+
+ dTravelTime = max(dTravelTime + cPack.traveltime + m_vOrderInfos[ind].getServiceTime(),
+ m_vOrderInfos[ind].getOpenTime() + m_vOrderInfos[ind].getServiceTime());
+
+ vecStartTimes.push_back(ceil(dTravelTime));
+
+ }
+
+ cPack = getOrderToDepotCost(vecOrderId[i - 1], tourInfo.getEndDepot());
+ dCost += cPack.cost;
+ dDistance += cPack.distance;
+
+ dTravelTime += cPack.traveltime;
+
+ vecStartTimes.push_back(ceil(dTravelTime));
+ ind = m_mapDepotIdToIndex[tourInfo.getEndDepot()];
+ if(dTravelTime > m_vDepotInfos[ind].getCloseTime())
+ return false;
+
+ tourInfo.updateCost(dCost, dDistance, dTravelTime);
+
+ tourInfo.setStartTime(vecStartTimes);
+
+ return true;
+}
+
+bool CVRPSolver::addOrderAtTour(CSolutionInfo &solutionInfo, int tourIndex, int insertIndex, int orderIndex)
+{
+ return(insertOrder(solutionInfo.getTour(tourIndex), m_vOrderInfos[orderIndex].getOrderId(), insertIndex));
+}
+
+CostPack CVRPSolver::getCostForInsert(CTourInfo& curTour, COrderInfo& curOrder, int pos)
+{
+ std::vector<int> vecOrderId = curTour.getOrderVector();
+
+ vecOrderId.insert(vecOrderId.begin() + pos, curOrder.getOrderId());
+ double dCost, dDistance, dTravelTime;
+ dCost = dDistance = dTravelTime = 0.0;
+ CostPack costRet;
+
+ costRet.cost = INF;
+ costRet.distance = INF;
+ costRet.traveltime = INF;
+
+ CostPack cPack = getDepotToOrderCost(curTour.getStartDepot(), vecOrderId[0]);
+
+ dCost += cPack.cost;
+ dDistance += cPack.distance;
+
+ int ind = m_mapOrderIdToIndex[vecOrderId[0]];
+
+ if(dTravelTime + cPack.traveltime > m_vOrderInfos[ind].getCloseTime())
+ return costRet;
+
+ dTravelTime = max(dTravelTime + cPack.traveltime + m_vOrderInfos[ind].getServiceTime(),
+ m_vOrderInfos[ind].getOpenTime() + m_vOrderInfos[ind].getServiceTime());
+
+ unsigned int i;
+ for(i = 1; i < vecOrderId.size(); i++)
+ {
+ cPack = getOrderToOrderCost(vecOrderId[i - 1], vecOrderId[i]);
+ dCost += cPack.cost;
+ dDistance += cPack.distance;
+
+ ind = m_mapOrderIdToIndex[vecOrderId[i]];
+
+ if(dTravelTime + cPack.traveltime > m_vOrderInfos[ind].getCloseTime())
+ return costRet;
+
+ dTravelTime = max(dTravelTime + cPack.traveltime + m_vOrderInfos[ind].getServiceTime(),
+ m_vOrderInfos[ind].getOpenTime() + m_vOrderInfos[ind].getServiceTime());
+
+ }
+
+ cPack = getOrderToDepotCost(vecOrderId[i - 1], curTour.getEndDepot());
+ dCost += cPack.cost;
+ dDistance += cPack.distance;
+
+ dTravelTime += cPack.traveltime;
+
+ ind = m_mapDepotIdToIndex[curTour.getEndDepot()];
+ if(dTravelTime > m_vDepotInfos[ind].getCloseTime())
+ return costRet;
+
+ costRet.cost = dCost - curTour.getCost();
+ costRet.distance = dDistance - curTour.getDistance();
+ costRet.traveltime = dTravelTime - curTour.getTravelTime();
+
+ return costRet;
+}
+
+void CVRPSolver::attempVehicleExchange(CSolutionInfo& solutionInfo)
+{
+ ++m_iGeneratedSolutionCount;
+ ++m_iStepsSinceLastSolution;
+ CMoveInfo curMove;
+ CMoveInfo bestMove;
+
+ int bestFreeCapacity = 0;
+ std::pair<int,int> bestSwapIndex;
+ int totalTour = solutionInfo.getTourCount();
+
+ for (int i = 0;i<totalTour;++i)
+ {
+ CTourInfo firstTour = solutionInfo.getTour(i);
+ int firstTourLoad = firstTour.getVehicleInfo().getCurrentLoad();
+ int firstVehicleCapacity = firstTour.getVehicleInfo().getCapacity();
+
+ for (int j = i+1;j<totalTour;++j)
+ {
+ CTourInfo secondTour = solutionInfo.getTour(j);
+ curMove.setInitialTour(firstTour,secondTour);
+
+ int FirstTourRemainingCapacity = firstVehicleCapacity - secondTour.getVehicleInfo().getCurrentLoad();
+
+ int SecondTourRemainingCapacity = secondTour.getVehicleInfo().getCapacity() - firstTourLoad;
+
+ // int prevFreeCapacity = max( secondTour.getRemainingCapacity(), firstTour.getRemainingCapacity() );
+
+ int curFreeCapacity = max(FirstTourRemainingCapacity,SecondTourRemainingCapacity);
+
+ if ( (FirstTourRemainingCapacity > 0) && (SecondTourRemainingCapacity > 0) &&
+ // curFreeCapacity > curFreeCapacity autological compare evaluates to false (error on MAC)
+ (curFreeCapacity > bestFreeCapacity) )
+ {
+
+ CVehicleInfo tempVehicle = m_vVehicleInfos[firstTour.getVehicleId()];
+ firstTour.setVehicleInfo(m_vVehicleInfos[secondTour.getVehicleId()] );
+ secondTour.setVehicleInfo( tempVehicle );
+
+ curMove.setModifiedTour(firstTour, secondTour);
+
+ if (!isTabuMove(curMove))
+ {
+ bestMove = curMove;
+ bestFreeCapacity = curFreeCapacity;
+ bestSwapIndex = std::make_pair(i,j);
+ }
+
+ curMove.getInitialTour(firstTour,secondTour);
+ }
+ }
+ }
+ if (bestFreeCapacity > 0)
+ {
+ CTourInfo tempTour;
+ bestMove.getModifiedTourAt(0, tempTour);
+ solutionInfo.replaceTourAt(bestSwapIndex.first, tempTour);
+ bestMove.getModifiedTourAt(1, tempTour);
+ solutionInfo.replaceTourAt(bestSwapIndex.second, tempTour);
+ updateTabuCount(bestMove);
+ updateFinalSolution(solutionInfo);
+ }
+
+}
+/*
+void CVRPSolver::attemptFeasibleNodeExchange(CSolutionInfo& solutionInfo)
+{
+ ++m_iGeneratedSolutionCount;
+ ++m_iStepsSinceLastSolution;
+ CMoveInfo bestMove, curMove;
+
+ int totalTour = solutionInfo.getTourCount();
+
+ for (int i = 0;i<totalTour;++i)
+ {
+ CTourInfo curTour = solutionInfo.getTour(i);
+ std::vector<int> vecOrderId = curTour.getOrderVector();
+ curMove.setInitialTour(curTour);
+ int totalCustomer = curTour.getServedOrderCount();
+ std::pair<int,int> bestSwapIndex;
+ double lowestCost = DOUBLE_MAX;
+
+ for (int j = 0;j<totalCustomer;++j)
+ {
+ for (int k = j+1;k<totalCustomer;++k)
+ {
+ COrderInfo firstCustomer = m_vOrderInfos[m_mapOrderIdToIndex[vecOrderId[j]]];
+ COrderInfo secondCustomer = m_vOrderInfos[m_mapOrderIdToIndex[vecOrderId[k]]];
+
+ if ( curTour->isFeasibleReplace(j,pSecondCustomer) && pCurTour->isFeasibleReplace(k,pFirstCustomer) )
+ {
+ pCurTour->removeCustomer(j,false);
+ pCurTour->addCustomer(pSecondCustomer,j);
+
+ pCurTour->removeCustomer(k,false);
+ pCurTour->addCustomer(pFirstCustomer,k);
+
+ pCurMove->setModifiedTour(pCurTour);
+ if (isTabuMove(pCurMove))
+ {
+ pCurMove->getInitialTour(pCurTour);
+ continue;
+ }
+
+ double curTourCost = pCurTour->getTourData()->calcCost(pCurTour->getAssignedVehicle());
+ if ( curTourCost < lowestCost )
+ {
+ *pBestMove = *pCurMove;
+ lowestCost = curTourCost;
+ bestSwapIndex = std::make_pair(j,k);
+ }
+ pCurMove->getInitialTour(pCurTour);
+ }
+ }
+ }
+
+ if (lowestCost!=DOUBLE_MAX)
+ {
+ m_pCurrentSolution->replaceTourAt(i,pBestMove->getModifiedTourAt(0));
+ this->updateTabuCount(pBestMove);
+ this->evaluateCurrentSolution();
+ }
+ }
+ delete pCurMove;
+ delete pBestMove;
+}
+*/
+
+void CVRPSolver::updateTabuCount(CMoveInfo& bestMove)
+{
+ m_veMoves.push_back(bestMove);
+ /*
+ bestMove.reverseMove();
+ CMoveInfo curMove;
+
+ std::map< CMoveInfo,int >::iterator mpIt = m_mapMoveFrequency.find(bestMove);
+
+ if (mpIt == m_mapMoveFrequency.end())
+ {
+ curMove = bestMove;
+ }
+ else curMove = (*mpIt).first;
+
+ m_mapMoveFrequency[curMove]++;
+
+ if( m_mapMoveFrequency[curMove] >= MAXIMUM_MOVE_FREQUENCY )
+ {
+ CMoveInfo tmpMove;
+ std::set<CMoveInfo>::iterator sIt = m_sTabuList.find(curMove);
+
+ CMoveInfo tmpMove2;
+ if ( sIt == m_sTabuList.end() )
+ {
+ tmpMove2 = curMove;
+ }
+ else tmpMove2 = (*sIt);
+ m_sTabuList.insert(tmpMove2);
+ }
+ m_mapTabuCount[curMove] = std::make_pair(m_iGeneratedSolutionCount,m_iStepsSinceLastSolution);
+ bestMove.reverseMove();
+ */
+}
+
+bool CVRPSolver::isTabuMove(CMoveInfo& curMove)
+{
+ int i, tot = m_veMoves.size();
+ for(i = 0; i < tot; i++)
+ {
+ if(curMove == m_veMoves[i])
+ return true;
+ }
+ return false;
+}
+
+
diff --git a/src/vrp_basic/src/VRP_Solver.h b/src/vrp_basic/src/VRP_Solver.h
new file mode 100644
index 0000000..ce558d5
--- /dev/null
+++ b/src/vrp_basic/src/VRP_Solver.h
@@ -0,0 +1,426 @@
+/*PGR
+
+Copyright (c) 2013 Khondoker Md. Razequl Islam
+ziboncsedu at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#ifndef VRPSOLVER_H
+#define VRPSOLVER_H
+
+#include <vector>
+#include <map>
+#include <queue>
+#include <string>
+#include <stdlib.h>
+#include <iostream>
+#include <algorithm>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <set>
+
+#define MAXIMUM_TRY 15
+#define TOTAL_NUMBER_OF_SEARCH 15
+#define MAXIMUM_MOVE_FREQUENCY 15
+
+#define INF (1e15)
+
+typedef std::pair<int, int> PII;
+
+#define max(a,b) ((a)>(b))?(a):(b)
+
+// Structure for Point, Geo coordinates can be represented with it
+typedef struct
+{
+ double X, Y;
+}Point;
+
+// Structure to keep cost, distance and traveltime. If distance/ traveltime is missing, there may be a negative flag
+typedef struct
+{
+ double cost, distance, traveltime;
+}CostPack;
+
+
+// Class for holding vehicle information which consist of capacity, and cost_per_km
+// For first version we will use homogeneous cost
+class CVehicleInfo
+{
+public:
+ CVehicleInfo();
+ ~CVehicleInfo();
+
+ bool init();
+
+ bool loadUnit(int lUnit);
+ bool unloadUnit(int lUnit);
+ int getRemainingCapacity(){return (m_iCapacity - m_iCurrentLoad);}
+
+ int getCurrentLoad(){return m_iCurrentLoad;}
+
+ int getCapacity(){return m_iCapacity;}
+ void setCapacity(int capacity){m_iCapacity = capacity;}
+
+ int getId(){return (this->m_iVehicleId);}
+ void setId(int id){m_iVehicleId = id;}
+
+ double getCostPerKM(){return m_dCostPerKM;}
+ void setCostPerKM(double cost){m_dCostPerKM = cost;}
+
+ friend bool operator != (const CVehicleInfo& cur, const CVehicleInfo& that);
+
+
+ //CVehicleInfo( CVehicleInfo const& );
+ //CVehicleInfo& operator = (const CVehicleInfo& vehicleInfo);
+
+private:
+ int m_iCapacity;
+ int m_iCurrentLoad;
+ int m_iVehicleId;
+ double m_dCostPerKM;
+
+};
+
+
+
+// Class to represent Orders. Each order is consist of open_time, close_time and sevice_time, its location and number of units ordered.
+class COrderInfo
+{
+public:
+ COrderInfo();
+ ~COrderInfo();
+
+ int getOpenTime(){return m_iOrderOpenTime;}
+ void setOpenTime(int openTime){m_iOrderOpenTime = openTime;}
+
+ int getCloseTime(){return m_iOrderCloseTime;}
+ void setCloseTime(int closeTime){m_iOrderCloseTime = closeTime;}
+
+ int getServiceTime(){return m_iOrderServiceTime;}
+ void setServiceTime(int serviceTime){m_iOrderServiceTime = serviceTime;}
+
+ int getOrderUnit(){return m_iOrderUnitCount;}
+ void setOrderUnit(int orderUnit){m_iOrderUnitCount = orderUnit;}
+
+ Point getOrderLocation(){return m_ptOrderLocation;}
+ void setOrderLocation(Point location){m_ptOrderLocation = location;}
+
+ int getOrderId(){return m_iOrderId; }
+ void setOrderId(int orderId){m_iOrderId = orderId;}
+
+
+ //COrderInfo( COrderInfo const& );
+ //COrderInfo& operator = (const COrderInfo& solution);
+
+private:
+ int m_iOrderOpenTime;
+ int m_iOrderCloseTime;
+ int m_iOrderServiceTime;
+ int m_iOrderUnitCount;
+ int m_iOrderId;
+
+ Point m_ptOrderLocation;
+};
+
+
+// Class to represent Depot information. Each depot will have it's Open_Time and Close_Time. The Depot that will open earliest will have open time 0
+// and all other time will be normalized with respect to it. For the first version there will be only one depot
+class CDepotInfo
+{
+public:
+ CDepotInfo();
+ ~CDepotInfo();
+
+ int getOpenTime(){return m_iDepotOpenTime;}
+ void setOpenTime(int openTime){m_iDepotOpenTime = openTime;}
+
+ int getCloseTime(){return m_iDepotCloseTime;}
+ void setCloseTime(int closeTime){m_iDepotCloseTime = closeTime;}
+
+ int getDepotId(){return m_iDepotId;}
+ void setDepotId(int id){m_iDepotId = id;}
+
+ Point getDepotLocation(){return m_ptDepotLocation;}
+ void setDepotLocation(Point location){m_ptDepotLocation = location;}
+
+ //CDepotInfo( CDepotInfo const& );
+ //CDepotInfo& operator = (const CDepotInfo& solution);
+
+private:
+ int m_iDepotOpenTime;
+ int m_iDepotCloseTime;
+
+ int m_iDepotId;
+
+ Point m_ptDepotLocation;
+};
+
+// Class to represent information of a Tour. A Tour starts from a depot and ends in a depot. On the way it serves several orders.
+// Each Tour has a vehicle ID and the list of Orders it serves in appropriate order. It also has the total Distance, Cost and Time assciated.
+class CTourInfo
+{
+public:
+ CTourInfo();
+ ~CTourInfo();
+
+ void init();
+
+ int getRemainingCapacity();
+
+ int getVehicleId(){return m_vehicleInfo.getId();}
+
+ CVehicleInfo& getVehicleInfo(){return m_vehicleInfo;}
+ void setVehicleInfo(CVehicleInfo vehicleInfo){m_vehicleInfo = vehicleInfo;}
+
+ int getStartDepot(){return m_iStartDepotId;}
+ void setStartDepot(int depotId){m_iStartDepotId = depotId;}
+
+ int getEndDepot(){return m_iEndDepotId;}
+ void setEndDepot(int depotId){m_iEndDepotId = depotId;}
+
+ int getServedOrderCount(){return m_viOrderIds.size();}
+
+ void updateCost(double cost, double distance, double travelTime);
+
+ void setStartTime(std::vector<int> vStartTime){m_viStartTime = vStartTime;}
+
+
+ bool insertOrder(int orderId, int pos);
+ bool removeOrder(int pos);
+
+
+ double getDistance(){return m_dTotalDistance;}
+
+ double getCost(){return m_dTotalCost;}
+
+ double getTravelTime(){return m_dTotalTraveltime;}
+
+ std::vector<int> getOrderVector(){return m_viOrderIds;}
+
+ int getStartTime(int pos){if( (unsigned int) pos >= m_viStartTime.size()) return 0;
+ else return m_viStartTime[pos];}
+
+ friend bool operator== (const CTourInfo& cur, const CTourInfo& that);
+
+
+ //bool operator != (const CTourInfo& that)
+ //{
+ // return(!(*this == that));
+ //}
+
+ //CTourInfo( CTourInfo const& );
+ //CTourInfo& operator = (const CTourInfo& solution);
+
+
+private:
+ CVehicleInfo m_vehicleInfo;
+ int m_iStartDepotId;
+ int m_iEndDepotId;
+ int m_iOrdersServed;
+ std::vector<int> m_viOrderIds;
+ std::vector<int> m_viStartTime;
+ double m_dTotalCost;
+ double m_dTotalDistance;
+ double m_dTotalTraveltime;
+};
+
+
+
+// This class will represent a solution of a VRP problem. A solution will be consist of multiple tour.
+// It also contains the number of vehicle used, number of orders served and total cost, distance and traveltime.
+class CSolutionInfo
+{
+public:
+ CSolutionInfo();
+ ~CSolutionInfo();
+
+ int getVehicleUsed(){return m_iVehicleUsed;}
+ int getOrderServed(){return m_iOrdersServed;}
+ //int getVehicleUsed(){return m_iVehicleUsed;}
+
+ bool addTour(CTourInfo& tour);
+ CTourInfo& getTour(int pos){return m_vtourAll[pos];}
+
+ int getTourCount(){return (m_vtourAll.size());}
+
+ int getUnservedOrderCount(){return m_vUnservedOrderId.size();}
+ int getUnusedVehicleCount(){return m_vUnusedVehicles.size();}
+
+ int getUnusedVehicleAt(int pos){return m_vUnusedVehicles[pos];}
+
+ void removeVehicle(int pos){m_vUnusedVehicles.erase(m_vUnusedVehicles.begin() + pos);}
+ void removeOrder(int pos){m_vUnservedOrderId.erase(m_vUnservedOrderId.begin() + pos);}
+
+ double getTotalCost(){return m_dTotalCost;}
+ double getTotalDistance(){return m_dTotalDistance;}
+ double getTotalTravelTime(){return m_dTotalTravelTime;}
+ int getUnservedOrderAt(int pos){return m_vUnservedOrderId[pos];}
+ //void addOrderAtTour(int tourIndex, int insertIndex, int orderIndex);
+
+ void replaceTourAt(int index, CTourInfo curTour);
+ void replaceTour(CTourInfo curTour);
+
+ bool init(std::vector<int> vecOrder, int iTotalOrder, std::vector<int> vecVehicle);
+
+ std::vector<CTourInfo> getTourInfoVector(){return m_vtourAll;}
+
+ //CTourInfo( CTourInfo const& );
+ //CTourInfo& operator = (const CTourInfo& solution);
+
+private:
+ std::vector<CTourInfo> m_vtourAll;
+ std::vector<int> m_vUnservedOrderId;
+ std::vector<int> m_vUnusedVehicles;
+ int m_iVehicleUsed;
+ int m_iOrdersServed;
+ int m_iTotalOrders;
+ double m_dTotalCost;
+ double m_dTotalDistance;
+ double m_dTotalTravelTime;
+};
+
+class CMoveInfo
+{
+public:
+
+ CMoveInfo();
+ ~CMoveInfo();
+
+ bool isBetter( CMoveInfo *pVRPMove );
+
+ void reverseMove();
+ void setInitialTour(CTourInfo pTourData);
+ void setInitialTour(CTourInfo pTourData1, CTourInfo pTourData2);
+ void setModifiedTour(CTourInfo pTourData);
+ void setModifiedTour(CTourInfo pTourData1, CTourInfo pTourData2);
+
+ bool getModifiedTourAt(int index, CTourInfo& tourInfo);
+ int getModifiedTourCount() const { return m_vModifiedTour.size();}
+ double getModifiedTourCost() const;
+ void getInitialTour(CTourInfo &TourData);
+ void getInitialTour(CTourInfo &TourData1, CTourInfo &TourData2);
+
+ friend bool operator == (const CMoveInfo& cur, const CMoveInfo& that);
+
+
+ //bool operator != (const CMoveInfo& that)
+ //{
+ // return(!(*this == that));
+ //}
+
+ //CMoveInfo( CMoveInfo const& );
+ //CMoveInfo& operator = (const CMoveInfo& solution);
+
+private:
+
+ void clearInitialTour();
+ void clearModifiedTour();
+
+ std::vector<CTourInfo> m_vInitialTour;
+ std::vector<CTourInfo> m_vModifiedTour;
+};
+
+
+
+
+// This is the main class that will solve the VRP problem. It will use the previous classes to represent the problem and the solution.
+// It will also have pre generated point to point distance/ cost/ traveltime information in maps.
+class CVRPSolver
+{
+public:
+ CVRPSolver();
+ ~CVRPSolver();
+
+ bool init();
+
+ bool addDepot(CDepotInfo depotInfo);
+ bool addOrder(COrderInfo orderInfo);
+ bool addVehicle(CVehicleInfo vehicleInfo);
+
+ CostPack getOrderToOrderCost(int firstOrder, int secondOrder);
+ CostPack getDepotToOrderCost(int depotId, int orderId);
+ CostPack getOrderToDepotCost(int depotId, int orderId);
+
+ bool addOrderToOrderCost(int firstOrder, int secondOrder, CostPack cost);
+ bool addDepotToOrderCost(int depotId, int orderId, CostPack cost);
+ bool addOrderToDepotCost(int depotId, int orderId, CostPack cost);
+
+ void removeVehicle(int vehicleIndex)
+ {m_viUnusedVehicleIndex.erase(m_viUnusedVehicleIndex.begin() + vehicleIndex, m_viUnusedVehicleIndex.begin() + vehicleIndex+1);}
+
+ void removeOrder(int orderIndex)
+ {m_viUnservedOrderIndex.erase(m_viUnservedOrderIndex.begin() + orderIndex, m_viUnservedOrderIndex.begin() + orderIndex + 1);}
+
+ bool solveVRP(std::string& strError);
+
+ bool getSolution(CSolutionInfo& solution, std::string& strError);
+ CSolutionInfo generateInitialSolution();
+ bool updateFinalSolution(CSolutionInfo& solutionInfo);
+ std::pair<int,double> getPotentialInsert(CTourInfo& curTour, COrderInfo& curOrder);
+ CostPack getCostForInsert(CTourInfo& curTour, COrderInfo& curOrder, int pos);
+ bool tabuSearch(CSolutionInfo& solutionInfo);
+ int getServiceTime(int order_id){return (m_vOrderInfos[m_mapOrderIdToIndex[order_id]].getServiceTime());}
+
+ bool insertOrder(CTourInfo& tourInfo, int orderId, int pos);
+ void applyBestMoveInCurrentSolution(CSolutionInfo& solutionInfo, CMoveInfo& bestMove );
+ void insertUnservedOrders(CSolutionInfo& solutionInfo);
+ //void attemptFeasibleNodeExchange(CSolutionInfo& solutionInfo);
+ void attempVehicleExchange(CSolutionInfo& solutionInfo);
+ //CMoveInfo identifyPotentialMove();
+ void updateTabuCount(CMoveInfo& bestMove);
+
+ bool isTabuMove(CMoveInfo& curMove);
+ bool updateTourCosts(CTourInfo& tourInfo);
+ bool addOrderAtTour(CSolutionInfo& solutionInfo, int tourIndex, int insertIndex, int orderIndex);
+
+
+private:
+ bool m_bIsReadyToSolve;
+ std::vector<CVehicleInfo> m_vVehicleInfos;
+ std::vector<COrderInfo> m_vOrderInfos;
+ std::vector<CDepotInfo> m_vDepotInfos;
+
+ std::map<int, int> m_mapOrderIdToIndex;
+ std::map<int, int> m_mapVehicleIdToIndex;
+ std::map<int, int> m_mapDepotIdToIndex;
+
+ std::map<std::pair<int, int>, CostPack> m_mapOrderToOrderCost;
+ std::map<std::pair<int, int>, CostPack> m_mapDepotToOrderrCost;
+ std::map<std::pair<int, int>, CostPack> m_mapOrderToDepotCost;
+
+ /*
+ std::map<CMoveInfo, int> m_mapMoveFrequency;
+ std::map<CMoveInfo, std::pair<int, int> > m_mapTabuCount;
+ std::set<CMoveInfo> m_sTabuList;
+ */
+
+ std::vector<CMoveInfo> m_veMoves;
+
+ bool m_bIsSolutionReady;
+ CSolutionInfo m_solutionFinal;
+
+private:
+ std::vector<int> m_viUnservedOrderIndex;
+ std::vector<int> m_viUnusedVehicleIndex;
+ int m_iGeneratedSolutionCount;
+ int m_iStepsSinceLastSolution;
+ bool m_bFoundOptimal;
+
+};
+
+#endif
diff --git a/src/vrp_basic/src/VRP_core.cpp b/src/vrp_basic/src/VRP_core.cpp
new file mode 100644
index 0000000..1248c56
--- /dev/null
+++ b/src/vrp_basic/src/VRP_core.cpp
@@ -0,0 +1,240 @@
+/*PGR
+
+Copyright (c) 2013 Khondoker Md. Razequl Islam
+ziboncsedu at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#include "VRP.h"
+#include "VRP_Solver.h"
+#include <exception>
+
+#undef PGR_LOGGER_ON
+#define PGR_LOGGER_LOC
+#define PGR_LOGGER_FILE "/tmp/vrp-debug.log"
+#include "../../common/src/pgr_logger.h"
+
+CVRPSolver solver;
+
+void loadOrders(vrp_orders_t *orders, int order_count, int depotId)
+{
+ int i;
+ PGR_LOGF("%s: %d\n", "Depot ID", id)
+ for(i = 0; i < order_count; i++)
+ {
+ int id = orders[i].id;
+ PGR_LOGF("%s: %d\n", "Order ID", id)
+ if (id == depotId)
+ {
+ PGR_LOG("Got depot");
+ // This order represents Deopot
+ CDepotInfo depot;
+
+ depot.setDepotId(id);
+
+ Point pt;
+
+ pt.X = orders[i].x;
+ pt.Y = orders[i].y;
+
+ depot.setDepotLocation(pt);
+
+ int openTime = orders[i].open_time;
+ depot.setOpenTime(openTime);
+
+ int closeTime = orders[i].close_time;
+ depot.setCloseTime(closeTime);
+
+ solver.addDepot(depot);
+
+ }
+ else
+ {
+ // This is an order
+ COrderInfo order;
+
+ order.setOrderId(id);
+
+ Point pt;
+
+ pt.X = orders[i].x;
+ pt.Y = orders[i].y;
+
+ order.setOrderLocation(pt);
+
+ int demand = orders[i].order_unit;
+ order.setOrderUnit(demand);
+
+ int openTime = orders[i].open_time;
+ order.setOpenTime(openTime);
+
+ int closeTime = orders[i].close_time;
+ order.setCloseTime(closeTime);
+
+ int serviceTime = orders[i].service_time;
+ order.setServiceTime(serviceTime);
+
+ solver.addOrder(order);
+ }
+ }
+
+}
+
+void loadVehicles(vrp_vehicles_t *vehicles, int vehicle_count)
+{
+ int i;
+ for(i = 0; i < vehicle_count; i++)
+ {
+ CVehicleInfo vehicle;
+
+ int id = vehicles[i].id;
+ vehicle.setId(id);
+
+ int capcity = vehicles[i].capacity;
+ vehicle.setCapacity(capcity);
+
+ vehicle.setCostPerKM(1);
+
+ solver.addVehicle(vehicle);
+ }
+
+}
+
+void loadDistanceMatrix(vrp_cost_element_t *costmatrix, int cost_count, int depotId)
+{
+ int i;
+ for(i = 0; i < cost_count; i++)
+ {
+ int fromId = costmatrix[i].src_id;
+ int toId = costmatrix[i].dest_id;
+ CostPack cpack;
+ cpack.cost = costmatrix[i].cost;
+ cpack.distance = costmatrix[i].distance;
+ cpack.traveltime = costmatrix[i].traveltime;
+
+ if(fromId == depotId)
+ solver.addDepotToOrderCost(fromId, toId, cpack);
+ else if(toId == depotId)
+ solver.addOrderToDepotCost(fromId, toId, cpack);
+ else
+ solver.addOrderToOrderCost(fromId, toId, cpack);
+ }
+
+}
+
+
+int find_vrp_solution(vrp_vehicles_t *vehicles, int vehicle_count,
+ vrp_orders_t *orders, int order_count,
+ vrp_cost_element_t *costmatrix, int cost_count,
+ int depot_id,
+ vrp_result_element_t **results, int *result_count, char **err_msg)
+{
+ int res;
+
+ std::string strError;
+ try {
+ PGR_LOG("Before load order");
+ loadOrders(orders, order_count, depot_id);
+ PGR_LOG("After load order");
+ loadVehicles(vehicles, vehicle_count);
+ PGR_LOG("After load vehicles");
+ loadDistanceMatrix(costmatrix, cost_count, depot_id);
+ PGR_LOG("After load distance matrix");
+ res = solver.solveVRP(strError);
+ PGR_LOG("After VRP Solve");
+
+ }
+ catch(std::exception& e) {
+ *err_msg = (char *) e.what();
+ return -1;
+ }
+ catch(...) {
+ *err_msg = (char *) "Caught unknown exception!";
+ return -1;
+ }
+
+
+ if (res < 0)
+ return res;
+ else
+ {
+ try {
+ CSolutionInfo solution;
+ CTourInfo ctour;
+ // bool bOK =
+ solver.getSolution(solution, strError);
+ int totalRoute = solution.getTourInfoVector().size();
+ int totRows = 0;
+ int i;
+ for(i = 0; i < totalRoute; i++)
+ {
+ totRows += (solution.getTour(i).getServedOrderCount() + 2);
+ }
+ *results = (vrp_result_element_t *) malloc(totRows * sizeof(vrp_result_element_t));
+ *result_count = totRows;
+ int cnt = 0;
+ for(int i = 0; i < totalRoute; i++)
+ {
+ ctour = solution.getTour(i);
+ std::vector<int> vecOrder = ctour.getOrderVector();
+ int totalOrder = vecOrder.size();
+
+ // For start depot
+ (*results)[cnt].order_id = ctour.getStartDepot();
+ (*results)[cnt].order_pos = 0;
+ (*results)[cnt].vehicle_id = ctour.getVehicleId();
+ (*results)[cnt].arrival_time = -1;
+ (*results)[cnt].depart_time = ctour.getStartTime(0);
+ cnt++;
+
+ // For each order
+ for(int j = 0; j < totalOrder; j++)
+ {
+ (*results)[cnt].order_id = vecOrder[j];
+ (*results)[cnt].order_pos = j + 1;
+ (*results)[cnt].vehicle_id = ctour.getVehicleId();
+ (*results)[cnt].depart_time = ctour.getStartTime(j + 1);
+ (*results)[cnt].arrival_time = ctour.getStartTime(j + 1) - solver.getServiceTime(vecOrder[j]);
+ cnt++;
+ }
+
+ // For return depot
+ (*results)[cnt].order_id = ctour.getEndDepot();
+ (*results)[cnt].order_pos = totalOrder + 1;
+ (*results)[cnt].vehicle_id = ctour.getVehicleId();
+ (*results)[cnt].arrival_time = ctour.getStartTime(totalOrder + 1);
+ (*results)[cnt].depart_time = -1;
+ cnt++;
+ }
+ }
+ catch(std::exception& e) {
+ *err_msg = (char *) e.what();
+ return -1;
+ }
+ catch(...) {
+ *err_msg = (char *) "Caught unknown exception!";
+ return -1;
+ }
+ }
+ return EXIT_SUCCESS;
+}
+
diff --git a/src/vrp_basic/src/Vehicles.txt b/src/vrp_basic/src/Vehicles.txt
new file mode 100644
index 0000000..04aa1c2
--- /dev/null
+++ b/src/vrp_basic/src/Vehicles.txt
@@ -0,0 +1,21 @@
+V_d Capacity
+1 200
+2 200
+3 200
+4 200
+5 200
+6 200
+7 200
+8 200
+9 200
+10 200
+11 200
+12 200
+13 200
+14 200
+15 200
+16 200
+17 200
+18 200
+19 200
+20 200
diff --git a/src/common/src/CMakeLists.txt b/src/vrp_basic/test/CMakeLists.txt
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/vrp_basic/test/CMakeLists.txt
diff --git a/src/vrp_basic/test/Distance.txt b/src/vrp_basic/test/Distance.txt
new file mode 100644
index 0000000..a8ce2cd
--- /dev/null
+++ b/src/vrp_basic/test/Distance.txt
@@ -0,0 +1,10100 @@
+1 2 38.078866
+1 3 30.805844
+1 4 39.357337
+1 5 36.055513
+1 6 40.311289
+1 7 33.301652
+1 8 35.355339
+1 9 39.051248
+1 10 33.541020
+1 11 31.622777
+1 12 33.526109
+1 13 32.388269
+1 14 38.078866
+1 15 35.355339
+1 16 39.293765
+1 17 41.231056
+1 18 40.311289
+1 19 45.177428
+1 20 40.049969
+1 21 35.057096
+1 22 45.000000
+1 23 35.000000
+1 24 45.044423
+1 25 35.057096
+1 26 45.276926
+1 27 58.523500
+1 28 57.008771
+1 29 55.713553
+1 30 52.201533
+1 31 52.000000
+1 32 50.289164
+1 33 51.078371
+1 34 51.478151
+1 35 47.434165
+1 36 44.204072
+1 37 43.011626
+1 38 40.607881
+1 39 37.202150
+1 40 36.055513
+1 41 40.311289
+1 42 30.805844
+1 43 33.541020
+1 44 38.078866
+1 45 35.341194
+1 46 37.735925
+1 47 37.202150
+1 48 38.327536
+1 49 45.044423
+1 50 38.052595
+1 51 35.341194
+1 52 33.541020
+1 53 25.000000
+1 54 20.000000
+1 55 18.027756
+1 56 14.142136
+1 57 18.027756
+1 58 26.925824
+1 59 47.169906
+1 60 42.426407
+1 61 26.925824
+1 62 15.811388
+1 63 29.154759
+1 64 39.051248
+1 65 20.615528
+1 66 11.180340
+1 67 13.038405
+1 68 25.298221
+1 69 10.000000
+1 70 9.219544
+1 71 19.646883
+1 72 25.495098
+1 73 27.459060
+1 74 39.293765
+1 75 36.055513
+1 76 57.008771
+1 77 42.941821
+1 78 49.979996
+1 79 32.557641
+1 80 38.470768
+1 81 7.615773
+1 82 12.041595
+1 83 14.764823
+1 84 19.235384
+1 85 27.018512
+1 86 35.468296
+1 87 32.202484
+1 88 38.209946
+1 89 17.888544
+1 90 52.478567
+1 91 4.242641
+1 92 12.041595
+1 93 14.764823
+1 94 21.095023
+1 95 17.117243
+1 96 20.615528
+1 97 15.524175
+1 98 48.166378
+1 99 14.142136
+1 100 20.518285
+1 101 19.235384
+2 1 38.078866
+2 3 10.440307
+2 4 3.000000
+2 5 7.071068
+2 6 5.000000
+2 7 12.206556
+2 8 14.142136
+2 9 11.180340
+2 10 52.201533
+2 11 47.434165
+2 12 48.104054
+2 13 43.462628
+2 14 53.851648
+2 15 44.721360
+2 16 50.537115
+2 17 51.478151
+2 18 47.169906
+2 19 82.225300
+2 20 76.902536
+2 21 72.034714
+2 22 81.394103
+2 23 71.589105
+2 24 81.049368
+2 25 71.196910
+2 26 80.622577
+2 27 89.022469
+2 28 86.023253
+2 29 86.683332
+2 30 82.006097
+2 31 83.630138
+2 32 80.430094
+2 33 82.879430
+2 34 84.852814
+2 35 78.102497
+2 36 42.000000
+2 37 40.000000
+2 38 40.112342
+2 39 37.336309
+2 40 35.355339
+2 41 35.000000
+2 42 34.481879
+2 43 30.413813
+2 44 30.000000
+2 45 30.149627
+2 46 5.830952
+2 47 8.602325
+2 48 46.141088
+2 49 81.786307
+2 50 74.953319
+2 51 68.622154
+2 52 71.589105
+2 53 55.000000
+2 54 35.355339
+2 55 39.051248
+2 56 25.495098
+2 57 55.901699
+2 58 60.207973
+2 59 75.663730
+2 60 66.708320
+2 61 26.925824
+2 62 28.284271
+2 63 64.031242
+2 64 76.321688
+2 65 58.523500
+2 66 46.097722
+2 67 50.596443
+2 68 58.051701
+2 69 29.154759
+2 70 33.541020
+2 71 18.867962
+2 72 50.000000
+2 73 42.941821
+2 74 33.970576
+2 75 65.192024
+2 76 82.462113
+2 77 80.956779
+2 78 82.024387
+2 79 33.615473
+2 80 25.495098
+2 81 43.908997
+2 82 36.124784
+2 83 42.047592
+2 84 55.317267
+2 85 64.498062
+2 86 72.718636
+2 87 61.131007
+2 88 62.369865
+2 89 27.018512
+2 90 90.354856
+2 91 39.849718
+2 92 49.244289
+2 93 50.477718
+2 94 48.836462
+2 95 48.918299
+2 96 57.140179
+2 97 43.139309
+2 98 70.213959
+2 99 33.015148
+2 100 50.009999
+2 101 18.973666
+3 1 30.805844
+3 2 10.440307
+3 4 10.000000
+3 5 5.385165
+3 6 10.198039
+3 7 4.000000
+3 8 7.000000
+3 9 8.602325
+3 10 41.761226
+3 11 37.000000
+3 12 37.696154
+3 13 33.105891
+3 14 43.462628
+3 15 34.481879
+3 16 40.311289
+3 17 41.340053
+3 18 37.202150
+3 19 73.375745
+3 20 68.007353
+3 21 63.245553
+3 22 72.277244
+3 23 62.641839
+3 24 71.805292
+3 25 62.096699
+3 26 71.196910
+3 27 85.755466
+3 28 83.240615
+3 29 83.216585
+3 30 78.892332
+3 31 79.881162
+3 32 77.175126
+3 33 79.056942
+3 34 80.430094
+3 35 74.625733
+3 36 46.097722
+3 37 44.147480
+3 38 43.566042
+3 39 40.311289
+3 40 38.327536
+3 41 39.293765
+3 42 36.000000
+3 43 33.376639
+3 44 34.481879
+3 45 33.734256
+3 46 7.280110
+3 47 6.403124
+3 48 36.055513
+3 49 72.801099
+3 50 66.098411
+3 51 64.031242
+3 52 64.140471
+3 53 45.099889
+3 54 25.079872
+3 55 36.249138
+3 56 17.000000
+3 57 48.826222
+3 58 50.635956
+3 59 65.375837
+3 60 56.293872
+3 61 16.552945
+3 62 25.079872
+3 63 58.728187
+3 64 69.814039
+3 65 50.537115
+3 66 37.336309
+3 67 42.485292
+3 68 53.413481
+3 69 23.430749
+3 70 24.698178
+3 71 14.317821
+3 72 47.423623
+3 73 42.201896
+3 74 25.000000
+3 75 55.036352
+3 76 72.034714
+3 77 73.573093
+3 78 72.006944
+3 79 23.600847
+3 80 17.464249
+3 81 37.536649
+3 82 31.906112
+3 83 32.388269
+3 84 46.486557
+3 85 57.801384
+3 86 66.219333
+3 87 51.009803
+3 88 51.971146
+3 89 17.117243
+3 90 83.216585
+3 91 31.764760
+3 92 42.638011
+3 93 44.553339
+3 94 45.276926
+3 95 44.204072
+3 96 50.990195
+3 97 39.115214
+3 98 59.774577
+3 99 23.345235
+3 100 40.199502
+3 101 12.041595
+4 1 39.357337
+4 2 3.000000
+4 3 10.000000
+4 5 5.385165
+4 6 2.000000
+4 7 10.770330
+4 8 12.206556
+4 9 8.602325
+4 10 51.419841
+4 11 46.572524
+4 12 47.127487
+4 13 42.379240
+4 14 52.810984
+4 15 43.462628
+4 16 49.244289
+4 17 50.089919
+4 18 45.650849
+4 19 82.969874
+4 20 77.620873
+4 21 72.801099
+4 22 82.000000
+4 23 72.277244
+4 24 81.584312
+4 25 71.805292
+4 26 81.049368
+4 27 91.400219
+4 28 88.481637
+4 29 89.022469
+4 30 84.403791
+4 31 85.912746
+4 32 82.800966
+4 33 85.146932
+4 34 87.000000
+4 35 80.430094
+4 36 45.000000
+4 37 43.000000
+4 38 43.104524
+4 39 40.311289
+4 40 38.327536
+4 41 38.000000
+4 42 37.363083
+4 43 33.376639
+4 44 33.000000
+4 45 33.136083
+4 46 3.605551
+4 47 6.403124
+4 48 44.721360
+4 49 82.462113
+4 50 75.690158
+4 51 70.710678
+4 52 72.897188
+4 53 55.081757
+4 54 35.057096
+4 55 41.400483
+4 56 26.248809
+4 57 57.306195
+4 58 60.530984
+4 59 75.325958
+4 60 66.098411
+4 61 25.961510
+4 62 30.479501
+4 63 65.946948
+4 64 77.935871
+4 65 59.615434
+4 66 46.840154
+4 67 51.623638
+4 68 60.108236
+4 69 30.805844
+4 70 34.205263
+4 71 20.615528
+4 72 52.430907
+4 73 45.617979
+4 74 32.015621
+4 75 65.030762
+4 76 81.786307
+4 77 82.298238
+4 78 82.006097
+4 79 32.202484
+4 80 23.345235
+4 81 45.486262
+4 82 38.183766
+4 83 42.296572
+4 84 56.044625
+4 85 66.037868
+4 86 74.330344
+4 87 61.008196
+4 88 61.814238
+4 89 27.073973
+4 90 91.787799
+4 91 40.853396
+4 92 50.774009
+4 93 52.201533
+4 94 51.088159
+4 95 50.931326
+4 96 58.821765
+4 97 45.276926
+4 98 69.375788
+4 99 33.241540
+4 100 50.159745
+4 101 20.124612
+5 1 36.055513
+5 2 7.071068
+5 3 5.385165
+5 4 5.385165
+5 6 5.000000
+5 7 5.385165
+5 8 7.071068
+5 9 5.000000
+5 10 46.097722
+5 11 41.231056
+5 12 41.761226
+5 13 37.000000
+5 14 47.434165
+5 15 38.078866
+5 16 43.863424
+5 17 44.721360
+5 18 40.311289
+5 19 78.746428
+5 20 73.375745
+5 21 68.622154
+5 22 77.620873
+5 23 68.007353
+5 24 77.129761
+5 25 67.446275
+5 26 76.485293
+5 27 90.138782
+5 28 87.464278
+5 29 87.658428
+5 30 83.216585
+5 31 84.403791
+5 32 81.541401
+5 33 83.600239
+5 34 85.146932
+5 35 79.056942
+5 36 47.265209
+5 37 45.276926
+5 38 45.044423
+5 39 42.000000
+5 40 40.000000
+5 41 40.311289
+5 42 38.327536
+5 43 35.000000
+5 44 35.355339
+5 45 35.057096
+5 46 2.000000
+5 47 2.000000
+5 48 39.357337
+5 49 78.160092
+5 50 71.470274
+5 51 68.767725
+5 52 69.462220
+5 53 50.249378
+5 54 30.000000
+5 55 40.311289
+5 56 22.360680
+5 57 54.083269
+5 58 55.901699
+5 59 70.178344
+5 60 60.827625
+5 61 20.615528
+5 62 29.154759
+5 63 63.639610
+5 64 75.000000
+5 65 55.901699
+5 66 42.720019
+5 67 47.853944
+5 68 58.137767
+5 69 28.284271
+5 70 30.083218
+5 71 18.601075
+5 72 51.478151
+5 73 45.541190
+5 74 26.907248
+5 75 60.000000
+5 76 76.485293
+5 77 78.892332
+5 78 77.058419
+5 79 26.832816
+5 80 18.439089
+5 81 42.638011
+5 82 36.400549
+5 83 37.656341
+5 84 51.865210
+5 85 63.007936
+5 86 71.400280
+5 87 56.008928
+5 88 56.568542
+5 89 22.360680
+5 90 88.509886
+5 91 37.121422
+5 92 47.801674
+5 93 49.578221
+5 94 49.648766
+5 95 48.918299
+5 96 56.080300
+5 97 43.600459
+5 98 64.031242
+5 99 28.635642
+5 100 45.398238
+5 101 17.029386
+6 1 40.311289
+6 2 5.000000
+6 3 10.198039
+6 4 2.000000
+6 5 5.000000
+6 7 10.198039
+6 8 11.180340
+6 9 7.071068
+6 10 50.990195
+6 11 46.097722
+6 12 46.572524
+6 13 41.761226
+6 14 52.201533
+6 15 42.720019
+6 16 48.466483
+6 17 49.244289
+6 18 44.721360
+6 19 83.522452
+6 20 78.160092
+6 21 73.375745
+6 22 82.462113
+6 23 72.801099
+6 24 82.000000
+6 25 72.277244
+6 26 81.394103
+6 27 93.005376
+6 28 90.138782
+6 29 90.603532
+6 30 86.023253
+6 31 87.458562
+6 32 84.403791
+6 33 86.683332
+6 34 88.459030
+6 35 82.006097
+6 36 47.000000
+6 37 45.000000
+6 38 45.099889
+6 39 42.296572
+6 40 40.311289
+6 41 40.000000
+6 42 39.293765
+6 43 35.355339
+6 44 35.000000
+6 45 35.128336
+6 46 3.000000
+6 47 5.385165
+6 48 43.863424
+6 49 82.969874
+6 50 76.243032
+6 51 72.138755
+6 52 73.824115
+6 53 55.226805
+6 54 35.000000
+6 55 43.011626
+6 56 26.925824
+6 57 58.309519
+6 58 60.827625
+6 59 75.166482
+6 60 65.764732
+6 61 25.495098
+6 62 32.015621
+6 63 67.268120
+6 64 79.056942
+6 65 60.415230
+6 66 47.434165
+6 67 52.392748
+6 68 61.522354
+6 69 32.015621
+6 70 34.785054
+6 71 21.931712
+6 72 54.083269
+6 73 47.423623
+6 74 30.805844
+6 75 65.000000
+6 76 81.394103
+6 77 83.240615
+6 78 82.054860
+6 79 31.384710
+6 80 22.022716
+6 81 46.615448
+6 82 39.623226
+6 83 42.579338
+6 84 56.612719
+6 85 67.119297
+6 86 75.451971
+6 87 61.008196
+6 88 61.522354
+6 89 27.294688
+6 90 92.784697
+6 91 41.629317
+6 92 51.865210
+6 93 53.413481
+6 94 52.630789
+6 95 52.325902
+6 96 60.000000
+6 97 46.754679
+6 98 68.883960
+6 99 33.541020
+6 100 50.358713
+6 101 21.095023
+7 1 33.301652
+7 2 12.206556
+7 3 4.000000
+7 4 10.770330
+7 5 5.385165
+7 6 10.198039
+7 8 3.000000
+7 9 5.830952
+7 10 40.792156
+7 11 35.902646
+7 12 36.400549
+7 13 31.622777
+7 14 42.059482
+7 15 32.695565
+7 16 38.483763
+7 17 39.357337
+7 18 34.985711
+7 19 74.672619
+7 20 69.289249
+7 21 64.621978
+7 22 73.375745
+7 23 63.906181
+7 24 72.801099
+7 25 63.245553
+7 26 72.034714
+7 27 89.185201
+7 28 86.769810
+7 29 86.608314
+7 30 82.365041
+7 31 83.216585
+7 32 80.622577
+7 33 82.377181
+7 34 83.600239
+7 35 78.032045
+7 36 50.009999
+7 37 48.052055
+7 38 47.518417
+7 39 44.283180
+7 40 42.296572
+7 41 43.174066
+7 42 40.000000
+7 43 37.336309
+7 44 38.327536
+7 45 37.656341
+7 46 7.280110
+7 47 5.000000
+7 48 34.000000
+7 49 74.000000
+7 50 67.416615
+7 51 67.201190
+7 52 66.287254
+7 53 45.541190
+7 54 25.079872
+7 55 39.924930
+7 56 19.209373
+7 57 51.224994
+7 58 51.419841
+7 59 65.069194
+7 60 55.578773
+7 61 15.297059
+7 62 28.792360
+7 63 61.717096
+7 64 72.346389
+7 65 52.478567
+7 66 38.910153
+7 67 44.418465
+7 68 56.612719
+7 69 26.627054
+7 70 26.419690
+7 71 18.027756
+7 72 51.078371
+7 73 46.097722
+7 74 21.931712
+7 75 55.036352
+7 76 71.196910
+7 77 75.716577
+7 78 72.173402
+7 79 21.470911
+7 80 13.892444
+7 81 40.311289
+7 82 35.355339
+7 83 33.241540
+7 84 47.927028
+7 85 60.307545
+7 86 68.767725
+7 87 51.088159
+7 88 51.351728
+7 89 18.027756
+7 90 85.445889
+7 91 33.837849
+7 92 45.276926
+7 93 47.423623
+7 94 48.764741
+7 95 47.434165
+7 96 53.740115
+7 97 42.544095
+7 98 58.694122
+7 99 24.351591
+7 100 40.792156
+7 101 15.264338
+8 1 35.355339
+8 2 14.142136
+8 3 7.000000
+8 4 12.206556
+8 5 7.071068
+8 6 11.180340
+8 7 3.000000
+8 9 5.000000
+8 10 40.311289
+8 11 35.355339
+8 12 35.693137
+8 13 30.805844
+8 14 41.231056
+8 15 31.622777
+8 16 37.336309
+8 17 38.078866
+8 18 33.541020
+8 19 75.769387
+8 20 70.384657
+8 21 65.795137
+8 22 74.330344
+8 23 65.000000
+8 24 73.681748
+8 25 64.257295
+8 26 72.801099
+8 27 91.787799
+8 28 89.442719
+8 29 89.185201
+8 30 85.000000
+8 31 85.755466
+8 32 83.240615
+8 33 84.905830
+8 34 86.023253
+8 35 80.622577
+8 36 52.952809
+8 37 50.990195
+8 38 50.487622
+8 39 47.265209
+8 40 45.276926
+8 41 46.097722
+8 42 43.000000
+8 43 40.311289
+8 44 41.231056
+8 45 40.607881
+8 46 8.602325
+8 47 5.830952
+8 48 32.695565
+8 49 75.026662
+8 50 68.541958
+8 51 69.634761
+8 52 68.007353
+8 53 46.097722
+8 54 25.495098
+8 55 42.720019
+8 56 21.213203
+8 57 53.150729
+8 58 52.201533
+8 59 65.000000
+8 60 55.226805
+8 61 15.000000
+8 62 31.622777
+8 63 64.031242
+8 64 74.330344
+8 65 54.083269
+8 66 40.311289
+8 67 46.043458
+8 68 59.076222
+8 69 29.154759
+8 70 28.017851
+8 71 20.880613
+8 72 53.851648
+8 73 49.030603
+8 74 19.849433
+8 75 55.226805
+8 76 70.710678
+8 77 77.420927
+8 78 72.443081
+8 79 20.248457
+8 80 11.401754
+8 81 42.520583
+8 82 38.013156
+8 83 34.176015
+8 84 49.193496
+8 85 62.289646
+8 86 70.767224
+8 87 51.351728
+8 88 51.088159
+8 89 19.235384
+8 90 87.200917
+8 91 35.608988
+8 92 47.381431
+8 93 49.678969
+8 94 51.429563
+8 95 49.929951
+8 96 55.901699
+8 97 45.177428
+8 98 58.051701
+8 99 25.495098
+8 100 41.484937
+8 101 17.888544
+9 1 39.051248
+9 2 11.180340
+9 3 8.602325
+9 4 8.602325
+9 5 5.000000
+9 6 7.071068
+9 7 5.830952
+9 8 5.000000
+9 10 45.276926
+9 11 40.311289
+9 12 40.607881
+9 13 35.693137
+9 14 46.097722
+9 15 36.400549
+9 16 42.059482
+9 17 42.720019
+9 18 38.078866
+9 19 80.411442
+9 20 75.026662
+9 21 70.384657
+9 22 79.056942
+9 23 69.641941
+9 24 78.447435
+9 25 68.949257
+9 26 77.620873
+9 27 94.339811
+9 28 91.787799
+9 29 91.809586
+9 30 87.464278
+9 31 88.481637
+9 32 85.755466
+9 33 87.658428
+9 34 89.022469
+9 35 83.216585
+9 36 52.239832
+9 37 50.249378
+9 38 50.039984
+9 39 47.000000
+9 40 45.000000
+9 41 45.276926
+9 42 43.289722
+9 43 40.000000
+9 44 40.311289
+9 45 40.049969
+9 46 5.385165
+9 47 3.000000
+9 48 37.336309
+9 49 79.711982
+9 50 73.164199
+9 51 72.622311
+9 52 72.111026
+9 53 50.990195
+9 54 30.413813
+9 55 44.721360
+9 56 25.000000
+9 57 57.008771
+9 58 57.008771
+9 59 70.000000
+9 60 60.207973
+9 61 20.000000
+9 62 33.541020
+9 63 67.268120
+9 64 78.102497
+9 65 58.309519
+9 66 44.721360
+9 67 50.249378
+9 68 62.008064
+9 69 32.015621
+9 70 32.249031
+9 71 22.825424
+9 72 55.901699
+9 73 50.289164
+9 74 23.853721
+9 75 60.207973
+9 76 75.663730
+9 77 81.541401
+9 78 77.414469
+9 79 25.000000
+9 80 15.000000
+9 81 45.967380
+9 82 40.496913
+9 83 38.897301
+9 84 53.712196
+9 85 66.068147
+9 86 74.518454
+9 87 56.320511
+9 88 56.080300
+9 89 23.769729
+9 90 91.263355
+9 91 39.661064
+9 92 50.990195
+9 93 53.037722
+9 94 53.851648
+9 95 52.801515
+9 96 59.413803
+9 97 47.707442
+9 98 62.968246
+9 99 30.083218
+9 100 46.324939
+9 101 20.615528
+10 1 33.541020
+10 2 52.201533
+10 3 41.761226
+10 4 51.419841
+10 5 46.097722
+10 6 50.990195
+10 7 40.792156
+10 8 40.311289
+10 9 45.276926
+10 11 5.000000
+10 12 5.385165
+10 13 10.198039
+10 14 5.000000
+10 15 11.180340
+10 16 9.433981
+10 17 11.180340
+10 18 14.142136
+10 19 45.343136
+10 20 40.607881
+10 21 37.735925
+10 22 42.426407
+10 23 36.055513
+10 24 41.036569
+10 25 34.409301
+10 26 39.051248
+10 27 85.146932
+10 28 85.000000
+10 29 82.152298
+10 30 80.000000
+10 31 78.160092
+10 32 78.000000
+10 33 77.162167
+10 34 75.663730
+10 35 75.000000
+10 36 75.822160
+10 37 74.330344
+10 38 72.346389
+10 39 68.767725
+10 40 67.268120
+10 41 70.710678
+10 42 62.481997
+10 43 63.639610
+10 44 67.268120
+10 45 65.069194
+10 46 48.052055
+10 47 45.705580
+10 48 12.806248
+10 49 43.863424
+10 50 39.408121
+10 51 62.000000
+10 52 47.434165
+10 53 15.811388
+10 54 18.027756
+10 55 51.478151
+10 56 32.015621
+10 57 40.000000
+10 58 22.360680
+10 59 25.495098
+10 60 15.000000
+10 61 25.495098
+10 62 46.097722
+10 63 55.000000
+10 64 57.008771
+10 65 35.355339
+10 66 25.495098
+10 67 31.064449
+10 68 54.451814
+10 69 39.051248
+10 70 27.018512
+10 71 42.201896
+10 72 58.523500
+10 73 60.901560
+10 74 26.248809
+10 75 18.027756
+10 76 30.413813
+10 77 55.036352
+10 78 34.539832
+10 79 21.095023
+10 80 33.241540
+10 81 38.897301
+10 82 45.276926
+10 83 18.788294
+10 84 27.294688
+10 85 47.381431
+10 86 54.341513
+10 87 15.556349
+10 88 11.180340
+10 89 26.925824
+10 90 64.412732
+10 91 29.546573
+10 92 39.623226
+10 93 43.737855
+10 94 53.758720
+10 95 48.764741
+10 96 46.043458
+10 97 48.846699
+10 98 18.027756
+10 99 23.345235
+10 100 16.000000
+10 101 38.275318
+11 1 31.622777
+11 2 47.434165
+11 3 37.000000
+11 4 46.572524
+11 5 41.231056
+11 6 46.097722
+11 7 35.902646
+11 8 35.355339
+11 9 40.311289
+11 10 5.000000
+11 12 2.000000
+11 13 5.385165
+11 14 7.071068
+11 15 7.071068
+11 16 8.000000
+11 17 10.000000
+11 18 11.180340
+11 19 48.795492
+11 20 43.863424
+11 21 40.607881
+11 22 46.097722
+11 23 39.051248
+11 24 44.821870
+11 25 37.536649
+11 26 43.011626
+11 27 85.586214
+11 28 85.146932
+11 29 82.607506
+11 30 80.156098
+11 31 78.638413
+11 32 78.160092
+11 33 77.646635
+11 34 76.485293
+11 35 75.166482
+11 36 72.622311
+11 37 71.063352
+11 38 69.202601
+11 39 65.604878
+11 40 64.031242
+11 41 67.268120
+11 42 59.405387
+11 43 60.207973
+11 44 63.639610
+11 45 61.554854
+11 46 43.174066
+11 47 40.792156
+11 48 9.433981
+11 49 47.423623
+11 50 42.520583
+11 51 62.201286
+11 52 49.244289
+11 53 18.027756
+11 54 14.142136
+11 55 49.244289
+11 56 28.284271
+11 57 40.311289
+11 58 25.000000
+11 59 30.413813
+11 60 20.000000
+11 61 20.615528
+11 62 43.011626
+11 63 55.226805
+11 64 58.523500
+11 65 36.400549
+11 66 25.000000
+11 67 31.144823
+11 68 54.037024
+11 69 36.055513
+11 70 24.186773
+11 71 38.288379
+11 72 57.008771
+11 73 58.600341
+11 74 21.540659
+11 75 22.360680
+11 76 35.355339
+11 77 57.306195
+11 78 39.217343
+11 79 16.124515
+11 80 28.284271
+11 81 37.656341
+11 82 42.953463
+11 83 17.262677
+11 84 28.460499
+11 85 48.270074
+11 86 55.659680
+11 87 19.416488
+11 88 16.124515
+11 89 22.803509
+11 90 66.887966
+11 91 27.892651
+11 92 39.051248
+11 93 43.104524
+11 94 52.392748
+11 95 47.675990
+11 96 46.097722
+11 97 47.127487
+11 98 22.803509
+11 99 20.000000
+11 100 16.763055
+11 101 34.205263
+12 1 33.526109
+12 2 48.104054
+12 3 37.696154
+12 4 47.127487
+12 5 41.761226
+12 6 46.572524
+12 7 36.400549
+12 8 35.693137
+12 9 40.607881
+12 10 5.385165
+12 11 2.000000
+12 13 5.000000
+12 14 5.830952
+12 15 5.830952
+12 16 6.000000
+12 17 8.000000
+12 18 9.433981
+12 19 50.209561
+12 20 45.343136
+12 21 42.201896
+12 22 47.423623
+12 23 40.607881
+12 24 46.097722
+12 25 39.051248
+12 26 44.204072
+12 27 87.572827
+12 28 87.143560
+12 29 84.593144
+12 30 82.152298
+12 31 80.622577
+12 32 80.156098
+12 33 79.630396
+12 34 78.447435
+12 35 77.162167
+12 36 74.202426
+12 37 72.622311
+12 38 70.802542
+12 39 67.201190
+12 40 65.604878
+12 41 68.767725
+12 42 61.032778
+12 43 61.717096
+12 44 65.069194
+12 45 63.031738
+12 46 43.680659
+12 47 41.231056
+12 48 7.810250
+12 49 48.795492
+12 50 44.045431
+12 51 64.195015
+12 52 51.078371
+12 53 19.723083
+12 54 15.620499
+12 55 51.078371
+12 56 29.732137
+12 57 42.296572
+12 58 26.627054
+12 59 30.805844
+12 60 20.099751
+12 61 21.189620
+12 62 44.654227
+12 63 57.218878
+12 64 60.406953
+12 65 38.327536
+12 66 27.000000
+12 67 33.136083
+12 68 56.035703
+12 69 37.735925
+12 70 25.942244
+12 71 39.623226
+12 72 58.940648
+12 73 60.415230
+12 74 20.880613
+12 75 23.323808
+12 76 35.128336
+12 77 59.059292
+12 78 39.924930
+12 79 16.000000
+12 80 28.071338
+12 81 39.623226
+12 82 44.777226
+12 83 19.235384
+12 84 30.364453
+12 85 50.219518
+12 86 57.567352
+12 87 20.615528
+12 88 16.492423
+12 89 24.083189
+12 90 68.600292
+12 91 29.832868
+12 92 41.048752
+12 93 45.099889
+12 94 54.341513
+12 95 49.648766
+12 96 48.093659
+12 97 49.040799
+12 98 22.360680
+12 99 21.633308
+12 100 18.681542
+12 101 35.468296
+13 1 32.388269
+13 2 43.462628
+13 3 33.105891
+13 4 42.379240
+13 5 37.000000
+13 6 41.761226
+13 7 31.622777
+13 8 30.805844
+13 9 35.693137
+13 10 10.198039
+13 11 5.385165
+13 12 5.000000
+13 14 10.440307
+13 15 3.000000
+13 16 7.810250
+13 17 9.433981
+13 18 8.000000
+13 19 53.814496
+13 20 48.795492
+13 21 45.343136
+13 22 51.224994
+13 23 43.863424
+13 24 50.000000
+13 25 42.426407
+13 26 48.259714
+13 27 88.283634
+13 28 87.572827
+13 29 85.328776
+13 30 82.607506
+13 31 81.394103
+13 32 80.622577
+13 33 80.411442
+13 34 79.555012
+13 35 77.646635
+13 36 71.281134
+13 37 69.634761
+13 38 67.955868
+13 39 64.350602
+13 40 62.681736
+13 41 65.604878
+13 42 58.309519
+13 43 58.600341
+13 44 61.717096
+13 45 59.816386
+13 46 38.897301
+13 47 36.400549
+13 48 6.000000
+13 49 52.497619
+13 50 47.381431
+13 51 64.776539
+13 52 53.235327
+13 53 22.671568
+13 54 13.000000
+13 55 49.335586
+13 56 26.627054
+13 57 43.174066
+13 58 29.732137
+13 59 35.693137
+13 60 25.079872
+13 61 16.552945
+13 62 42.059482
+13 63 57.870545
+13 64 62.241465
+13 65 39.924930
+13 66 27.459060
+13 67 33.955854
+13 68 56.080300
+13 69 35.341194
+13 70 24.041631
+13 71 36.124784
+13 72 57.870545
+13 73 58.523500
+13 74 16.155494
+13 75 27.730849
+13 76 40.112342
+13 77 61.587336
+13 78 44.598206
+13 79 11.000000
+13 80 23.086793
+13 81 39.051248
+13 82 43.011626
+13 83 19.104973
+13 84 32.202484
+13 85 51.546096
+13 86 59.236813
+13 87 24.698178
+13 88 21.377558
+13 89 20.615528
+13 90 71.281134
+13 91 29.068884
+13 92 41.109610
+13 93 45.044423
+13 94 53.460266
+13 95 49.091751
+13 96 48.662100
+13 97 47.853944
+13 98 27.294688
+13 99 19.313208
+13 100 20.591260
+13 101 31.827661
+14 1 38.078866
+14 2 53.851648
+14 3 43.462628
+14 4 52.810984
+14 5 47.434165
+14 6 52.201533
+14 7 42.059482
+14 8 41.231056
+14 9 46.097722
+14 10 5.000000
+14 11 7.071068
+14 12 5.830952
+14 13 10.440307
+14 15 10.000000
+14 16 5.830952
+14 17 7.071068
+14 18 11.180340
+14 19 49.203658
+14 20 44.654227
+14 21 42.059482
+14 22 46.097722
+14 23 40.311289
+14 24 44.598206
+14 25 38.587563
+14 26 42.426407
+14 27 90.138782
+14 28 90.000000
+14 29 87.143560
+14 30 85.000000
+14 31 83.150466
+14 32 83.000000
+14 33 82.152298
+14 34 80.622577
+14 35 80.000000
+14 36 79.649231
+14 37 78.102497
+14 38 76.216796
+14 39 72.622311
+14 40 71.063352
+14 41 74.330344
+14 42 66.400301
+14 43 67.268120
+14 44 70.710678
+14 45 68.622154
+14 46 49.335586
+14 47 46.840154
+14 48 10.440307
+14 49 47.634021
+14 50 43.566042
+14 51 67.000000
+14 52 52.201533
+14 53 20.615528
+14 54 21.213203
+14 55 55.901699
+14 56 35.355339
+14 57 45.000000
+14 58 26.925824
+14 59 26.925824
+14 60 15.811388
+14 61 26.925824
+14 62 50.000000
+14 63 60.000000
+14 64 61.846584
+14 65 40.311289
+14 66 30.413813
+14 67 36.055513
+14 68 59.413803
+14 69 43.011626
+14 70 31.064449
+14 71 45.343136
+14 72 63.245553
+14 73 65.299311
+14 74 25.179357
+14 75 21.213203
+14 76 30.000000
+14 77 59.615434
+14 78 36.715120
+14 79 21.213203
+14 80 33.015148
+14 81 43.680659
+14 82 49.648766
+14 83 23.409400
+14 84 32.249031
+14 85 52.345009
+14 86 59.228372
+14 87 19.416488
+14 88 13.038405
+14 89 29.832868
+14 90 68.876701
+14 91 34.176015
+14 92 44.553339
+14 93 48.662100
+14 94 58.523500
+14 95 53.600373
+14 96 51.039201
+14 97 53.488316
+14 98 17.029386
+14 99 27.018512
+14 100 21.000000
+14 101 41.231056
+15 1 35.355339
+15 2 44.721360
+15 3 34.481879
+15 4 43.462628
+15 5 38.078866
+15 6 42.720019
+15 7 32.695565
+15 8 31.622777
+15 9 36.400549
+15 10 11.180340
+15 11 7.071068
+15 12 5.830952
+15 13 3.000000
+15 14 10.000000
+15 16 5.830952
+15 17 7.071068
+15 18 5.000000
+15 19 55.865911
+15 20 50.931326
+15 21 47.634021
+15 22 53.150729
+15 23 46.097722
+15 24 51.855569
+15 25 44.598206
+15 26 50.000000
+15 27 91.241438
+15 28 90.553851
+15 29 88.283634
+15 30 85.586214
+15 31 84.344532
+15 32 83.600239
+15 33 83.360662
+15 34 82.462113
+15 35 80.622577
+15 36 73.783467
+15 37 72.111026
+15 38 70.491134
+15 39 66.887966
+15 40 65.192024
+15 41 68.007353
+15 42 60.901560
+15 43 61.032778
+15 44 64.031242
+15 45 62.201286
+15 46 39.924930
+15 47 37.336309
+15 48 3.000000
+15 49 54.488531
+15 50 49.578221
+15 51 67.742158
+15 52 55.901699
+15 53 25.000000
+15 54 15.811388
+15 55 52.201533
+15 56 29.154759
+15 57 46.097722
+15 58 32.015621
+15 59 36.400549
+15 60 25.495098
+15 61 18.027756
+15 62 44.721360
+15 63 60.827625
+15 64 65.000000
+15 65 42.720019
+15 66 30.413813
+15 67 36.878178
+15 68 59.076222
+15 69 38.078866
+15 70 26.925824
+15 71 38.418745
+15 72 60.827625
+15 73 61.351447
+15 74 15.297059
+15 75 29.154759
+15 76 40.000000
+15 77 64.140471
+15 78 45.694639
+15 79 11.401754
+15 80 23.021729
+15 81 42.047592
+15 82 45.880279
+15 83 22.090722
+15 84 34.928498
+15 85 54.405882
+15 86 62.032250
+15 87 26.400758
+15 88 22.135944
+15 89 23.021729
+15 90 73.783467
+15 91 32.062439
+15 92 44.102154
+15 93 48.041649
+15 94 56.435804
+15 95 52.086467
+15 96 51.623638
+15 97 50.803543
+15 98 27.018512
+15 99 22.135944
+15 100 23.259407
+15 101 34.058773
+16 1 39.293765
+16 2 50.537115
+16 3 40.311289
+16 4 49.244289
+16 5 43.863424
+16 6 48.466483
+16 7 38.483763
+16 8 37.336309
+16 9 42.059482
+16 10 9.433981
+16 11 8.000000
+16 12 6.000000
+16 13 7.810250
+16 14 5.830952
+16 15 5.830952
+16 17 2.000000
+16 18 5.385165
+16 19 54.671748
+16 20 50.000000
+16 21 47.169906
+16 22 51.662365
+16 23 45.486262
+16 24 50.209561
+16 25 43.829214
+16 26 48.104054
+16 27 93.536089
+16 28 93.134312
+16 29 90.553851
+16 30 88.141931
+16 31 86.579443
+16 32 86.145226
+16 33 85.586214
+16 34 84.344532
+16 35 83.150466
+16 36 79.056942
+16 37 77.420927
+16 38 75.716577
+16 39 72.111026
+16 40 70.455660
+16 41 73.409809
+16 42 66.037868
+16 43 66.400301
+16 44 69.526973
+16 45 67.623960
+16 46 45.694639
+16 47 43.081318
+16 48 5.000000
+16 49 53.150729
+16 50 48.826222
+16 51 70.178344
+16 52 56.648036
+16 53 25.079872
+16 54 20.591260
+16 55 56.648036
+16 56 34.409301
+16 57 48.259714
+16 58 31.764760
+16 59 32.695565
+16 60 21.540659
+16 61 23.853721
+16 62 49.739320
+16 63 63.198101
+16 64 66.098411
+16 65 44.147480
+16 66 33.000000
+16 67 39.115214
+16 68 62.032250
+16 69 42.941821
+16 70 31.384710
+16 71 43.931765
+16 72 64.761099
+16 73 65.924199
+16 74 20.000000
+16 75 26.907248
+16 76 35.128336
+16 77 64.404969
+16 78 42.544095
+16 79 17.088007
+16 80 28.284271
+16 81 45.541190
+16 82 50.328918
+16 83 25.179357
+16 84 36.138622
+16 85 56.089215
+16 86 63.324561
+16 87 24.839485
+16 88 18.867962
+16 89 28.425341
+16 90 73.824115
+16 91 35.693137
+16 92 47.042534
+16 93 51.088159
+16 94 60.207973
+16 95 55.578773
+16 96 54.083269
+16 97 54.817880
+16 98 22.090722
+16 99 26.832816
+16 100 24.515301
+16 101 39.623226
+17 1 41.231056
+17 2 51.478151
+17 3 41.340053
+17 4 50.089919
+17 5 44.721360
+17 6 49.244289
+17 7 39.357337
+17 8 38.078866
+17 9 42.720019
+17 10 11.180340
+17 11 10.000000
+17 12 8.000000
+17 13 9.433981
+17 14 7.071068
+17 15 7.071068
+17 16 2.000000
+17 18 5.000000
+17 19 56.222771
+17 20 51.613952
+17 21 48.877398
+17 22 53.150729
+17 23 47.169906
+17 24 51.662365
+17 25 45.486262
+17 26 49.497475
+17 27 95.524866
+17 28 95.131488
+17 29 92.541882
+17 30 90.138782
+17 31 88.566359
+17 32 88.141931
+17 33 87.572827
+17 34 86.313383
+17 35 85.146932
+17 36 80.709355
+17 37 79.056942
+17 38 77.388630
+17 39 73.783467
+17 40 72.111026
+17 41 75.000000
+17 42 67.742158
+17 43 68.007353
+17 44 71.063352
+17 45 69.202601
+17 46 46.518813
+17 47 43.863424
+17 48 5.385165
+17 49 54.671748
+17 50 50.477718
+17 51 72.173402
+17 52 58.523500
+17 53 26.925824
+17 54 22.360680
+17 55 58.523500
+17 56 36.055513
+17 57 50.249378
+17 58 33.541020
+17 59 33.541020
+17 60 22.360680
+17 61 25.000000
+17 62 51.478151
+17 63 65.192024
+17 64 68.007353
+17 65 46.097722
+17 66 35.000000
+17 67 41.109610
+17 68 64.031242
+17 69 44.721360
+17 70 33.241540
+17 71 45.453273
+17 72 66.708320
+17 73 67.779053
+17 74 20.099751
+17 75 28.284271
+17 76 35.355339
+17 77 66.211781
+17 78 43.566042
+17 79 17.888544
+17 80 28.635642
+17 81 47.518417
+17 82 52.201533
+17 83 27.166155
+17 84 38.078866
+17 85 58.051701
+17 86 65.253352
+17 87 26.400758
+17 88 20.000000
+17 89 30.000000
+17 90 75.591005
+17 91 37.656341
+17 92 49.040799
+17 93 53.084838
+17 94 62.169124
+17 95 57.558666
+17 96 56.080300
+17 97 56.753854
+17 98 22.360680
+17 99 28.635642
+17 100 26.476405
+17 101 41.109610
+18 1 40.311289
+18 2 47.169906
+18 3 37.202150
+18 4 45.650849
+18 5 40.311289
+18 6 44.721360
+18 7 34.985711
+18 8 33.541020
+18 9 38.078866
+18 10 14.142136
+18 11 11.180340
+18 12 9.433981
+18 13 8.000000
+18 14 11.180340
+18 15 5.000000
+18 16 5.385165
+18 17 5.000000
+18 19 59.464275
+18 20 54.671748
+18 21 51.613952
+18 22 56.568542
+18 23 50.000000
+18 24 55.172457
+18 25 48.414874
+18 26 53.150729
+18 27 96.176920
+18 28 95.524866
+18 29 93.214806
+18 30 90.553851
+18 31 89.269256
+18 32 88.566359
+18 33 88.283634
+18 34 87.321246
+18 35 85.586214
+18 36 78.032045
+18 37 76.321688
+18 38 74.793048
+18 39 71.196910
+18 40 69.462220
+18 41 72.111026
+18 42 65.299311
+18 43 65.192024
+18 44 68.007353
+18 45 66.287254
+18 46 42.059482
+18 47 39.357337
+18 48 2.000000
+18 49 58.000000
+18 50 53.413481
+18 51 72.691127
+18 52 60.415230
+18 53 29.154759
+18 54 20.615528
+18 55 57.008771
+18 56 33.541020
+18 57 50.990195
+18 58 36.055513
+18 59 38.078866
+18 60 26.925824
+18 61 21.213203
+18 62 49.244289
+18 63 65.764732
+18 64 69.641941
+18 65 47.434165
+18 66 35.355339
+18 67 41.773197
+18 68 64.070274
+18 69 42.720019
+18 70 31.780497
+18 71 42.438190
+18 72 65.764732
+18 73 66.098411
+18 74 15.132746
+18 75 32.015621
+18 76 40.311289
+18 77 68.476273
+18 78 47.885280
+18 79 13.601471
+18 80 23.769729
+18 81 47.042534
+18 82 50.695167
+18 83 27.073973
+18 84 39.560081
+18 85 59.203040
+18 86 66.730802
+18 87 29.698485
+18 88 24.186773
+18 89 27.294688
+18 90 78.032045
+18 91 37.054015
+18 92 49.091751
+18 93 53.037722
+18 94 61.400326
+18 95 57.078893
+18 96 56.568542
+18 97 55.731499
+18 98 27.294688
+18 99 26.925824
+18 100 27.856777
+18 101 38.013156
+19 1 45.177428
+19 2 82.225300
+19 3 73.375745
+19 4 82.969874
+19 5 78.746428
+19 6 83.522452
+19 7 74.672619
+19 8 75.769387
+19 9 80.411442
+19 10 45.343136
+19 11 48.795492
+19 12 50.209561
+19 13 53.814496
+19 14 49.203658
+19 15 55.865911
+19 16 54.671748
+19 17 56.222771
+19 18 59.464275
+19 20 5.385165
+19 21 10.198039
+19 22 4.000000
+19 23 10.770330
+19 24 6.000000
+19 25 11.661904
+19 26 9.000000
+19 27 56.797887
+19 28 59.169249
+19 29 54.120237
+19 30 54.918121
+19 31 50.606324
+19 32 53.254108
+19 33 49.739320
+19 34 45.617979
+19 35 50.803543
+19 36 83.240615
+19 37 82.710338
+19 38 79.812280
+19 39 77.129761
+19 40 76.687678
+19 41 81.584312
+19 42 71.386273
+19 43 75.802375
+19 44 80.752709
+19 45 77.781746
+19 46 80.653580
+19 47 79.378838
+19 48 58.000000
+19 49 2.000000
+19 50 7.280110
+19 51 41.036569
+19 52 18.601075
+19 53 31.400637
+19 54 51.000000
+19 55 56.089215
+19 56 56.753854
+19 57 30.594117
+19 58 24.413111
+19 59 29.427878
+19 60 37.161808
+19 61 62.177166
+19 62 60.008333
+19 63 36.619667
+19 64 25.806976
+19 65 25.019992
+19 66 36.138622
+19 67 32.140317
+19 68 42.059482
+19 69 55.145263
+19 70 48.764741
+19 71 64.629715
+19 72 54.230987
+19 73 62.936476
+19 74 69.202601
+19 75 28.301943
+19 76 39.000000
+19 77 17.464249
+19 78 21.095023
+19 79 62.425956
+19 80 73.573093
+19 81 42.107007
+19 82 53.235327
+19 83 41.629317
+19 84 26.925824
+19 85 27.294688
+19 86 26.172505
+19 87 29.832868
+19 88 37.215588
+19 89 56.648036
+19 90 23.000000
+19 91 42.579338
+19 92 37.336309
+19 93 39.051248
+19 94 49.979996
+19 95 44.922155
+19 96 34.176015
+19 97 50.219518
+19 98 42.059482
+19 99 50.328918
+19 100 34.985711
+19 101 63.348244
+20 1 40.049969
+20 2 76.902536
+20 3 68.007353
+20 4 77.620873
+20 5 73.375745
+20 6 78.160092
+20 7 69.289249
+20 8 70.384657
+20 9 75.026662
+20 10 40.607881
+20 11 43.863424
+20 12 45.343136
+20 13 48.795492
+20 14 44.654227
+20 15 50.931326
+20 16 50.000000
+20 17 51.613952
+20 18 54.671748
+20 19 5.385165
+20 21 5.000000
+20 22 5.385165
+20 23 5.385165
+20 24 6.403124
+20 25 6.403124
+20 26 8.602325
+20 27 56.648036
+20 28 58.600341
+20 29 53.851648
+20 30 54.120237
+20 31 50.159745
+20 32 52.354560
+20 33 49.244289
+20 34 45.541190
+20 35 49.739320
+20 36 79.056942
+20 37 78.447435
+20 38 75.584390
+20 39 72.801099
+20 40 72.277244
+20 41 77.129761
+20 42 66.940272
+20 43 71.196910
+20 44 76.118329
+20 45 73.164199
+20 46 75.286121
+20 47 74.000000
+20 48 53.150729
+20 49 5.000000
+20 50 2.000000
+20 51 39.051248
+20 52 16.401219
+20 53 26.248809
+20 54 45.650849
+20 55 51.662365
+20 56 51.419841
+20 57 26.248809
+20 58 19.209373
+20 59 27.000000
+20 60 33.526109
+20 61 56.824291
+20 62 55.081757
+20 63 33.970576
+20 64 25.079872
+20 65 20.223748
+20 66 30.805844
+20 67 27.018512
+20 68 38.832976
+20 69 50.039984
+20 70 43.416587
+20 71 59.413803
+20 72 50.537115
+20 73 58.872744
+20 74 64.031242
+20 75 24.166092
+20 76 37.336309
+20 77 18.110770
+20 78 20.248457
+20 79 57.201399
+20 80 68.264193
+20 81 37.336309
+20 82 48.507731
+20 83 36.249138
+20 84 21.587033
+20 85 24.207437
+20 86 24.698178
+20 87 25.238859
+20 88 33.105891
+20 89 51.264022
+20 90 25.495098
+20 91 37.336309
+20 92 32.756679
+20 93 34.785054
+20 94 46.097722
+20 95 40.853396
+20 96 30.413813
+20 97 45.880279
+20 98 38.832976
+20 99 44.944410
+20 100 29.681644
+20 101 58.051701
+21 1 35.057096
+21 2 72.034714
+21 3 63.245553
+21 4 72.801099
+21 5 68.622154
+21 6 73.375745
+21 7 64.621978
+21 8 65.795137
+21 9 70.384657
+21 10 37.735925
+21 11 40.607881
+21 12 42.201896
+21 13 45.343136
+21 14 42.059482
+21 15 47.634021
+21 16 47.169906
+21 17 48.877398
+21 18 51.613952
+21 19 10.198039
+21 20 5.000000
+21 22 10.198039
+21 23 2.000000
+21 24 10.770330
+21 25 4.000000
+21 26 12.206556
+21 27 55.081757
+21 28 56.648036
+21 29 52.201533
+21 30 52.000000
+21 31 48.383882
+21 32 50.159745
+21 33 47.434165
+21 34 44.147480
+21 35 47.423623
+21 36 74.330344
+21 37 73.681748
+21 38 70.837843
+21 39 68.007353
+21 40 67.446275
+21 41 72.277244
+21 42 62.096699
+21 43 66.287254
+21 44 71.196910
+21 45 68.249542
+21 46 70.519501
+21 47 69.289249
+21 48 50.000000
+21 49 10.000000
+21 50 3.000000
+21 51 36.055513
+21 52 13.928388
+21 53 22.671568
+21 54 41.340053
+21 55 46.840154
+21 56 46.572524
+21 57 21.540659
+21 58 15.620499
+21 59 27.459060
+21 60 32.388269
+21 61 52.478567
+21 62 50.089919
+21 63 30.479501
+21 64 23.537205
+21 65 15.297059
+21 66 25.961510
+21 67 22.022716
+21 68 34.828150
+21 69 45.044423
+21 70 38.600518
+21 71 54.451814
+21 72 46.141088
+21 73 54.230987
+21 74 60.207973
+21 75 22.561028
+21 76 38.327536
+21 77 18.248288
+21 78 22.472205
+21 79 53.263496
+21 80 64.070274
+21 81 32.388269
+21 82 43.566042
+21 83 31.764760
+21 84 16.763055
+21 85 20.518285
+21 86 22.472205
+21 87 22.847319
+21 88 31.320920
+21 89 46.615448
+21 90 26.925824
+21 91 32.388269
+21 92 27.892651
+21 93 30.083218
+21 94 41.593269
+21 95 36.249138
+21 96 26.076810
+21 97 41.109610
+21 98 38.118237
+21 99 40.311289
+21 100 25.612497
+21 101 53.150729
+22 1 45.000000
+22 2 81.394103
+22 3 72.277244
+22 4 82.000000
+22 5 77.620873
+22 6 82.462113
+22 7 73.375745
+22 8 74.330344
+22 9 79.056942
+22 10 42.426407
+22 11 46.097722
+22 12 47.423623
+22 13 51.224994
+22 14 46.097722
+22 15 53.150729
+22 16 51.662365
+22 17 53.150729
+22 18 56.568542
+22 19 4.000000
+22 20 5.385165
+22 21 10.198039
+22 23 10.000000
+22 24 2.000000
+22 25 10.198039
+22 26 5.000000
+22 27 60.415230
+22 28 62.649820
+22 29 57.697487
+22 30 58.309519
+22 31 54.120237
+22 32 56.603887
+22 33 53.235327
+22 34 49.244289
+22 35 54.083269
+22 36 84.433406
+22 37 83.815273
+22 38 80.956779
+22 39 78.160092
+22 40 77.620873
+22 41 82.462113
+22 42 72.277244
+22 43 76.485293
+22 44 81.394103
+22 45 78.447435
+22 46 79.555012
+22 47 78.160092
+22 48 55.172457
+22 49 2.000000
+22 50 7.280110
+22 51 43.863424
+22 52 21.213203
+22 53 29.154759
+22 54 49.244289
+22 55 57.008771
+22 56 55.901699
+22 57 31.622777
+22 58 22.360680
+22 59 25.495098
+22 60 33.541020
+22 61 60.415230
+22 62 60.207973
+22 63 39.051248
+22 64 29.154759
+22 65 25.495098
+22 66 35.355339
+22 67 32.015621
+22 68 44.102154
+22 69 55.000000
+22 70 47.853944
+22 71 64.195015
+22 72 55.901699
+22 73 64.257295
+22 74 66.850580
+22 75 25.000000
+22 76 35.000000
+22 77 21.189620
+22 78 17.117243
+22 79 60.207973
+22 80 71.589105
+22 81 42.579338
+22 82 53.758720
+22 83 40.162171
+22 84 26.172505
+22 85 29.410882
+22 86 29.206164
+22 87 26.870058
+22 88 33.837849
+22 89 55.362442
+22 90 27.000000
+22 91 42.107007
+22 92 38.078866
+22 93 40.162171
+22 94 51.478151
+22 95 46.238512
+22 96 35.777088
+22 97 51.244512
+22 98 38.275318
+22 99 49.040799
+22 100 33.105891
+22 101 62.649820
+23 1 35.000000
+23 2 71.589105
+23 3 62.641839
+23 4 72.277244
+23 5 68.007353
+23 6 72.801099
+23 7 63.906181
+23 8 65.000000
+23 9 69.641941
+23 10 36.055513
+23 11 39.051248
+23 12 40.607881
+23 13 43.863424
+23 14 40.311289
+23 15 46.097722
+23 16 45.486262
+23 17 47.169906
+23 18 50.000000
+23 19 10.770330
+23 20 5.385165
+23 21 2.000000
+23 22 10.000000
+23 24 10.198039
+23 25 2.000000
+23 26 11.180340
+23 27 57.008771
+23 28 58.523500
+23 29 54.120237
+23 30 53.851648
+23 31 50.289164
+23 32 52.000000
+23 33 49.335586
+23 34 46.097722
+23 35 49.244289
+23 36 75.026662
+23 37 74.330344
+23 38 71.512237
+23 39 68.622154
+23 40 68.007353
+23 41 72.801099
+23 42 62.641839
+23 43 66.708320
+23 44 71.589105
+23 45 68.658576
+23 46 69.921384
+23 47 68.622154
+23 48 48.414874
+23 49 10.198039
+23 50 3.605551
+23 51 37.735925
+23 52 15.811388
+23 53 21.213203
+23 54 40.311289
+23 55 47.434165
+23 56 46.097722
+23 57 22.360680
+23 58 14.142136
+23 59 25.495098
+23 60 30.413813
+23 61 51.478151
+23 62 50.249378
+23 63 32.015621
+23 64 25.495098
+23 65 15.811388
+23 66 25.495098
+23 67 22.022716
+23 68 36.124784
+23 69 45.000000
+23 70 38.078866
+23 71 54.230987
+23 72 47.169906
+23 73 55.036352
+23 74 58.898217
+23 75 20.615528
+23 76 36.400549
+23 77 20.223748
+23 78 20.808652
+23 79 52.009614
+23 80 62.968246
+23 81 32.756679
+23 82 43.931765
+23 83 30.870698
+23 84 16.278821
+23 85 22.022716
+23 86 24.351591
+23 87 21.023796
+23 88 29.410882
+23 89 45.880279
+23 90 28.792360
+23 91 32.140317
+23 92 28.460499
+23 93 30.870698
+23 94 42.544095
+23 95 37.121422
+23 96 27.202941
+23 97 41.785165
+23 98 36.124784
+23 99 39.560081
+23 100 24.413111
+23 101 52.773099
+24 1 45.044423
+24 2 81.049368
+24 3 71.805292
+24 4 81.584312
+24 5 77.129761
+24 6 82.000000
+24 7 72.801099
+24 8 73.681748
+24 9 78.447435
+24 10 41.036569
+24 11 44.821870
+24 12 46.097722
+24 13 50.000000
+24 14 44.598206
+24 15 51.855569
+24 16 50.209561
+24 17 51.662365
+24 18 55.172457
+24 19 6.000000
+24 20 6.403124
+24 21 10.770330
+24 22 2.000000
+24 23 10.198039
+24 25 10.000000
+24 26 3.000000
+24 27 62.241465
+24 28 64.412732
+24 29 59.506302
+24 30 60.033324
+24 31 55.901699
+24 32 58.309519
+24 33 55.009090
+24 34 51.078371
+24 35 55.758407
+24 36 85.094066
+24 37 84.433406
+24 38 81.596569
+24 39 78.746428
+24 40 78.160092
+24 41 82.969874
+24 42 72.801099
+24 43 76.902536
+24 44 81.786307
+24 45 78.854296
+24 46 79.075913
+24 47 77.620873
+24 48 53.814496
+24 49 4.000000
+24 50 8.062258
+24 51 45.343136
+24 52 22.671568
+24 53 28.178006
+24 54 48.466483
+24 55 57.567352
+24 56 55.578773
+24 57 32.310989
+24 58 21.540659
+24 59 23.537205
+24 60 31.764760
+24 61 59.615434
+24 62 60.406953
+24 63 40.360872
+24 64 30.886890
+24 65 25.961510
+24 66 35.128336
+24 67 32.140317
+24 68 45.221676
+24 69 55.036352
+24 70 47.518417
+24 71 64.070274
+24 72 56.824291
+24 73 65.000000
+24 74 65.734314
+24 75 23.430749
+24 76 33.000000
+24 77 23.086793
+24 78 15.132746
+24 79 59.169249
+24 80 70.661163
+24 81 42.953463
+24 82 54.129474
+24 83 39.560081
+24 84 26.019224
+24 85 30.610456
+24 86 30.805844
+24 87 25.495098
+24 88 32.202484
+24 89 54.817880
+24 90 29.000000
+24 91 42.011903
+24 92 38.600518
+24 93 40.853396
+24 94 52.325902
+24 95 47.010637
+24 96 36.715120
+24 97 51.865210
+24 98 36.400549
+24 99 48.507731
+24 100 32.310989
+24 101 62.393910
+25 1 35.057096
+25 2 71.196910
+25 3 62.096699
+25 4 71.805292
+25 5 67.446275
+25 6 72.277244
+25 7 63.245553
+25 8 64.257295
+25 9 68.949257
+25 10 34.409301
+25 11 37.536649
+25 12 39.051248
+25 13 42.426407
+25 14 38.587563
+25 15 44.598206
+25 16 43.829214
+25 17 45.486262
+25 18 48.414874
+25 19 11.661904
+25 20 6.403124
+25 21 4.000000
+25 22 10.198039
+25 23 2.000000
+25 24 10.000000
+25 26 10.440307
+25 27 58.940648
+25 28 60.406953
+25 29 56.044625
+25 30 55.713553
+25 31 52.201533
+25 32 53.851648
+25 33 51.244512
+25 34 48.052055
+25 35 51.078371
+25 36 75.769387
+25 37 75.026662
+25 38 72.235725
+25 39 69.289249
+25 40 68.622154
+25 41 73.375745
+25 42 63.245553
+25 43 67.186308
+25 44 72.034714
+25 45 69.123079
+25 46 69.375788
+25 47 68.007353
+25 48 46.861498
+25 49 10.770330
+25 50 5.000000
+25 51 39.446166
+25 52 17.720045
+25 53 19.849433
+25 54 39.357337
+25 55 48.104054
+25 56 45.705580
+25 57 23.323808
+25 58 12.806248
+25 59 23.537205
+25 60 28.442925
+25 61 50.537115
+25 62 50.487622
+25 63 33.600595
+25 64 27.459060
+25 65 16.552945
+25 66 25.179357
+25 67 22.203603
+25 68 37.483330
+25 69 45.044423
+25 70 37.656341
+25 71 54.083269
+25 72 48.259714
+25 73 55.901699
+25 74 57.628118
+25 75 18.681542
+25 76 34.481879
+25 77 22.203603
+25 78 19.209373
+25 79 50.803543
+25 80 61.911227
+25 81 33.241540
+25 82 44.384682
+25 83 30.083218
+25 84 16.031220
+25 85 23.600847
+25 86 26.248809
+25 87 19.235384
+25 88 27.513633
+25 89 45.221676
+25 90 30.675723
+25 91 32.015621
+25 92 29.154759
+25 93 31.764760
+25 94 43.566042
+25 95 38.078866
+25 96 28.425341
+25 97 42.544095
+25 98 34.132096
+25 99 38.897301
+25 100 23.323808
+25 101 52.469038
+26 1 45.276926
+26 2 80.622577
+26 3 71.196910
+26 4 81.049368
+26 5 76.485293
+26 6 81.394103
+26 7 72.034714
+26 8 72.801099
+26 9 77.620873
+26 10 39.051248
+26 11 43.011626
+26 12 44.204072
+26 13 48.259714
+26 14 42.426407
+26 15 50.000000
+26 16 48.104054
+26 17 49.497475
+26 18 53.150729
+26 19 9.000000
+26 20 8.602325
+26 21 12.206556
+26 22 5.000000
+26 23 11.180340
+26 24 3.000000
+26 25 10.440307
+26 27 65.000000
+26 28 67.082039
+26 29 62.241465
+26 30 62.649820
+26 31 58.600341
+26 32 60.901560
+26 33 57.697487
+26 34 53.851648
+26 35 58.309519
+26 36 86.162637
+26 37 85.440037
+26 38 82.637764
+26 39 79.711982
+26 40 79.056942
+26 41 83.815273
+26 42 73.681748
+26 43 77.620873
+26 44 82.462113
+26 45 79.555012
+26 46 78.447435
+26 47 76.902536
+26 48 51.855569
+26 49 7.000000
+26 50 9.899495
+26 51 47.634021
+26 52 25.000000
+26 53 26.925824
+26 54 47.434165
+26 55 58.523500
+26 56 55.226805
+26 57 33.541020
+26 58 20.615528
+26 59 20.615528
+26 60 29.154759
+26 61 58.523500
+26 62 60.827625
+26 63 42.426407
+26 64 33.541020
+26 65 26.925824
+26 66 35.000000
+26 67 32.557641
+26 68 47.010637
+26 69 55.226805
+26 70 47.169906
+26 71 64.000000
+26 72 58.309519
+26 73 66.211781
+26 74 64.140471
+26 75 21.213203
+26 76 30.000000
+26 77 25.961510
+26 78 12.165525
+26 79 57.706152
+26 80 69.354164
+26 81 43.680659
+26 82 54.817880
+26 83 38.832976
+26 84 26.076810
+26 85 32.557641
+26 86 33.286634
+26 87 23.600847
+26 88 29.832868
+26 89 54.129474
+26 90 32.000000
+26 91 42.047592
+26 92 39.560081
+26 93 42.047592
+26 94 53.712196
+26 95 48.301139
+26 96 38.275318
+26 97 52.924474
+26 98 33.615473
+26 99 47.853944
+26 100 31.320920
+26 101 62.128898
+27 1 58.523500
+27 2 89.022469
+27 3 85.755466
+27 4 91.400219
+27 5 90.138782
+27 6 93.005376
+27 7 89.185201
+27 8 91.787799
+27 9 94.339811
+27 10 85.146932
+27 11 85.586214
+27 12 87.572827
+27 13 88.283634
+27 14 90.138782
+27 15 91.241438
+27 16 93.536089
+27 17 95.524866
+27 18 96.176920
+27 19 56.797887
+27 20 56.648036
+27 21 55.081757
+27 22 60.415230
+27 23 57.008771
+27 24 62.241465
+27 25 58.940648
+27 26 65.000000
+27 28 5.000000
+27 29 3.000000
+27 30 7.071068
+27 31 7.000000
+27 32 8.602325
+27 33 8.000000
+27 34 11.180340
+27 35 11.180340
+27 36 61.717096
+27 37 62.649820
+27 38 60.033324
+27 39 59.908263
+27 40 61.032778
+27 41 65.192024
+27 42 58.258047
+27 43 64.031242
+27 44 68.007353
+27 45 65.604878
+27 46 91.263355
+27 47 91.809586
+27 48 94.201911
+27 49 58.600341
+27 50 55.973208
+27 51 23.537205
+27 52 41.231056
+27 53 70.000000
+27 54 77.620873
+27 55 50.000000
+27 56 71.589105
+27 57 45.276926
+27 58 65.192024
+27 59 82.462113
+27 60 85.586214
+27 61 85.440037
+27 62 61.032778
+27 63 30.413813
+27 64 31.622777
+27 65 50.000000
+27 66 60.827625
+27 67 54.451814
+27 68 33.241540
+27 69 62.649820
+27 70 67.675697
+27 71 71.561163
+27 72 39.051248
+27 73 47.423623
+27 74 97.718985
+27 75 75.663730
+27 76 93.407708
+27 77 39.357337
+27 78 76.896034
+27 79 90.801982
+27 80 96.772930
+27 81 50.921508
+27 82 53.851648
+27 83 69.231496
+27 84 58.008620
+27 85 38.013156
+27 86 32.756679
+27 87 74.242845
+27 88 83.216585
+27 89 76.321688
+27 90 37.536649
+27 91 60.440053
+27 92 47.539457
+27 93 43.965896
+27 94 40.496913
+27 95 42.047592
+27 96 39.623226
+27 97 46.647615
+27 98 91.787799
+27 99 72.422372
+27 100 69.180922
+27 101 73.925638
+28 1 57.008771
+28 2 86.023253
+28 3 83.240615
+28 4 88.481637
+28 5 87.464278
+28 6 90.138782
+28 7 86.769810
+28 8 89.442719
+28 9 91.787799
+28 10 85.000000
+28 11 85.146932
+28 12 87.143560
+28 13 87.572827
+28 14 90.000000
+28 15 90.553851
+28 16 93.134312
+28 17 95.131488
+28 18 95.524866
+28 19 59.169249
+28 20 58.600341
+28 21 56.648036
+28 22 62.649820
+28 23 58.523500
+28 24 64.412732
+28 25 60.406953
+28 26 67.082039
+28 27 5.000000
+28 29 5.830952
+28 30 5.000000
+28 31 8.602325
+28 32 7.000000
+28 33 9.433981
+28 34 14.142136
+28 35 10.000000
+28 36 57.306195
+28 37 58.309519
+28 38 55.758407
+28 39 55.803226
+28 40 57.008771
+28 41 61.032778
+28 42 54.488531
+28 43 60.207973
+28 44 64.031242
+28 45 61.717096
+28 46 88.509886
+28 47 89.185201
+28 48 93.536089
+28 49 60.901560
+28 50 57.775427
+28 51 23.000000
+28 52 42.720019
+28 53 70.178344
+28 54 76.485293
+28 55 47.169906
+28 56 69.641941
+28 57 45.000000
+28 58 65.764732
+28 59 83.815273
+28 60 86.313383
+28 61 83.815273
+28 62 58.309519
+28 63 30.000000
+28 64 33.541020
+28 65 50.249378
+28 66 60.207973
+28 67 54.037024
+28 68 31.780497
+28 69 60.415230
+28 70 66.219333
+28 71 68.963759
+28 72 36.055513
+28 73 43.863424
+28 74 96.301610
+28 75 76.485293
+28 76 94.868330
+28 77 41.880783
+28 78 78.790862
+28 79 89.498603
+28 80 94.921020
+28 81 49.477268
+28 82 51.429563
+28 83 68.468971
+28 84 58.137767
+28 85 38.470768
+28 86 34.176015
+28 87 74.813100
+28 88 83.725743
+28 89 74.632433
+28 90 41.036569
+28 91 59.228372
+28 92 46.529560
+28 93 42.755117
+28 94 38.013156
+28 95 40.162171
+28 96 39.051248
+28 97 44.283180
+28 98 92.574294
+28 99 71.063352
+28 100 69.000000
+28 101 71.554175
+29 1 55.713553
+29 2 86.683332
+29 3 83.216585
+29 4 89.022469
+29 5 87.658428
+29 6 90.603532
+29 7 86.608314
+29 8 89.185201
+29 9 91.809586
+29 10 82.152298
+29 11 82.607506
+29 12 84.593144
+29 13 85.328776
+29 14 87.143560
+29 15 88.283634
+29 16 90.553851
+29 17 92.541882
+29 18 93.214806
+29 19 54.120237
+29 20 53.851648
+29 21 52.201533
+29 22 57.697487
+29 23 54.120237
+29 24 59.506302
+29 25 56.044625
+29 26 62.241465
+29 27 3.000000
+29 28 5.830952
+29 30 5.385165
+29 31 4.000000
+29 32 6.403124
+29 33 5.000000
+29 34 8.602325
+29 35 8.602325
+29 36 60.415230
+29 37 61.269895
+29 38 58.591808
+29 39 58.309519
+29 40 59.363288
+29 41 63.631753
+29 42 56.400355
+29 43 62.201286
+29 44 66.287254
+29 45 63.820060
+29 46 88.814413
+29 47 89.308454
+29 48 91.241438
+29 49 55.901699
+29 50 53.141321
+29 51 20.615528
+29 52 38.327536
+29 53 67.000000
+29 54 74.726167
+29 55 47.634021
+29 56 68.876701
+29 57 42.296572
+29 58 62.201286
+29 59 79.555012
+29 60 82.607506
+29 61 82.637764
+29 62 58.600341
+29 63 27.459060
+29 64 28.792360
+29 65 47.000000
+29 66 57.870545
+29 67 51.478151
+29 68 30.463092
+29 69 60.033324
+29 70 64.845971
+29 71 69.065187
+29 72 36.796739
+29 73 45.453273
+29 74 94.868330
+29 75 72.691127
+29 76 90.520716
+29 77 36.715120
+29 78 74.094534
+29 79 87.931792
+29 80 94.021274
+29 81 48.104054
+29 82 51.312766
+29 83 66.287254
+29 84 55.009090
+29 85 35.014283
+29 86 29.832868
+29 87 71.253070
+29 88 80.224684
+29 89 73.539105
+29 90 35.355339
+29 91 57.567352
+29 92 44.643029
+29 93 41.109610
+29 94 38.013156
+29 95 39.357337
+29 96 36.674242
+29 97 44.102154
+29 98 88.814413
+29 99 69.570109
+29 100 66.189123
+29 101 71.344236
+30 1 52.201533
+30 2 82.006097
+30 3 78.892332
+30 4 84.403791
+30 5 83.216585
+30 6 86.023253
+30 7 82.365041
+30 8 85.000000
+30 9 87.464278
+30 10 80.000000
+30 11 80.156098
+30 12 82.152298
+30 13 82.607506
+30 14 85.000000
+30 15 85.586214
+30 16 88.141931
+30 17 90.138782
+30 18 90.553851
+30 19 54.918121
+30 20 54.120237
+30 21 52.000000
+30 22 58.309519
+30 23 53.851648
+30 24 60.033324
+30 25 55.713553
+30 26 62.649820
+30 27 7.071068
+30 28 5.000000
+30 29 5.385165
+30 31 5.385165
+30 32 2.000000
+30 33 5.830952
+30 34 11.180340
+30 35 5.000000
+30 36 55.036352
+30 37 55.901699
+30 38 53.235327
+30 39 53.000000
+30 40 54.083269
+30 41 58.309519
+30 42 51.224994
+30 43 57.008771
+30 44 61.032778
+30 45 58.600341
+30 46 84.314886
+30 47 84.905830
+30 48 88.566359
+30 49 56.603887
+30 50 53.225934
+30 51 18.000000
+30 52 38.078866
+30 53 65.192024
+30 54 71.589105
+30 55 43.011626
+30 56 65.000000
+30 57 40.000000
+30 58 60.827625
+30 59 79.056942
+30 60 81.394103
+30 61 79.056942
+30 62 54.083269
+30 63 25.000000
+30 64 29.154759
+30 65 45.276926
+30 66 55.226805
+30 67 49.040799
+30 68 26.925824
+30 69 55.901699
+30 70 61.400326
+30 71 64.660653
+30 72 32.015621
+30 73 40.360872
+30 74 91.482239
+30 75 71.589105
+30 76 90.138782
+30 77 37.802116
+30 78 74.249579
+30 79 84.646323
+30 80 90.249654
+30 81 44.643029
+30 82 47.010637
+30 83 63.505905
+30 84 53.150729
+30 85 33.541020
+30 86 29.546573
+30 87 69.871310
+30 88 78.771822
+30 89 69.892775
+30 90 37.802116
+30 91 54.341513
+30 92 41.593269
+30 93 37.854986
+30 94 33.615473
+30 95 35.468296
+30 96 34.058773
+30 97 39.824616
+30 98 87.664132
+30 99 66.219333
+30 100 64.000000
+30 101 67.119297
+31 1 52.000000
+31 2 83.630138
+31 3 79.881162
+31 4 85.912746
+31 5 84.403791
+31 6 87.458562
+31 7 83.216585
+31 8 85.755466
+31 9 88.481637
+31 10 78.160092
+31 11 78.638413
+31 12 80.622577
+31 13 81.394103
+31 14 83.150466
+31 15 84.344532
+31 16 86.579443
+31 17 88.566359
+31 18 89.269256
+31 19 50.606324
+31 20 50.159745
+31 21 48.383882
+31 22 54.120237
+31 23 50.289164
+31 24 55.901699
+31 25 52.201533
+31 26 58.600341
+31 27 7.000000
+31 28 8.602325
+31 29 4.000000
+31 30 5.385165
+31 32 5.000000
+31 33 1.000000
+31 34 5.830952
+31 35 5.830952
+31 36 58.872744
+31 37 59.615434
+31 38 56.859476
+31 39 56.356011
+31 40 57.306195
+31 41 61.717096
+31 42 54.083269
+31 43 59.908263
+31 44 64.140471
+31 45 61.587336
+31 46 85.603738
+31 47 86.023253
+31 48 87.298339
+31 49 52.354560
+31 50 49.396356
+31 51 16.763055
+31 52 34.481879
+31 53 63.000000
+31 54 70.880181
+31 55 44.598206
+31 56 65.299311
+31 57 38.327536
+31 58 58.215118
+31 59 75.690158
+31 60 78.638413
+31 61 78.924014
+31 62 55.443665
+31 63 23.537205
+31 64 25.079872
+31 65 43.000000
+31 66 53.935146
+31 67 47.518417
+31 68 26.832816
+31 69 56.603887
+31 70 61.098281
+31 71 65.802736
+31 72 33.970576
+31 73 43.011626
+31 74 91.082380
+31 75 68.731361
+31 76 86.683332
+31 77 33.286634
+31 78 70.384657
+31 79 84.118963
+31 80 90.376988
+31 81 44.384682
+31 82 48.010416
+31 83 62.369865
+31 84 51.009803
+31 85 31.016125
+31 86 25.961510
+31 87 67.268120
+31 88 76.236474
+31 89 69.856997
+31 90 32.649655
+31 91 53.758720
+31 92 40.804412
+31 93 37.336309
+31 94 34.828150
+31 95 35.846897
+31 96 32.756679
+31 97 40.804412
+31 98 84.852814
+31 99 65.787537
+31 100 62.201286
+31 101 67.955868
+32 1 50.289164
+32 2 80.430094
+32 3 77.175126
+32 4 82.800966
+32 5 81.541401
+32 6 84.403791
+32 7 80.622577
+32 8 83.240615
+32 9 85.755466
+32 10 78.000000
+32 11 78.160092
+32 12 80.156098
+32 13 80.622577
+32 14 83.000000
+32 15 83.600239
+32 16 86.145226
+32 17 88.141931
+32 18 88.566359
+32 19 53.254108
+32 20 52.354560
+32 21 50.159745
+32 22 56.603887
+32 23 52.000000
+32 24 58.309519
+32 25 53.851648
+32 26 60.901560
+32 27 8.602325
+32 28 7.000000
+32 29 6.403124
+32 30 2.000000
+32 31 5.000000
+32 33 5.099020
+32 34 10.440307
+32 35 3.000000
+32 36 54.230987
+32 37 55.036352
+32 38 52.325902
+32 39 51.971146
+32 40 53.000000
+32 41 57.306195
+32 42 50.000000
+32 43 55.803226
+32 44 59.908263
+32 45 57.428216
+32 46 82.661962
+32 47 83.216585
+32 48 86.579443
+32 49 54.918121
+32 50 51.429563
+32 51 16.000000
+32 52 36.249138
+32 53 63.198101
+32 54 69.634761
+32 55 41.400483
+32 56 63.158531
+32 57 38.000000
+32 58 58.855756
+32 59 77.162167
+32 60 79.429214
+32 61 77.162167
+32 62 52.430907
+32 63 23.000000
+32 64 27.459060
+32 65 43.289722
+32 66 53.235327
+32 67 47.042534
+32 68 25.000000
+32 69 54.120237
+32 70 59.481089
+32 71 62.968246
+32 72 30.479501
+32 73 39.051248
+32 74 89.560036
+32 75 69.634761
+32 76 88.255311
+32 77 36.235342
+32 78 72.449983
+32 79 82.710338
+32 80 88.391176
+32 81 42.720019
+32 82 45.276926
+32 83 61.522354
+32 84 51.156622
+32 85 31.575307
+32 86 27.730849
+32 87 67.896981
+32 88 76.791927
+32 89 68.007353
+32 90 36.619667
+32 91 52.392748
+32 92 39.623226
+32 93 35.902646
+32 94 31.906112
+32 95 33.615473
+32 96 32.062439
+32 97 38.078866
+32 98 85.702975
+32 99 64.288413
+32 100 62.000000
+32 101 65.368188
+33 1 51.078371
+33 2 82.879430
+33 3 79.056942
+33 4 85.146932
+33 5 83.600239
+33 6 86.683332
+33 7 82.377181
+33 8 84.905830
+33 9 87.658428
+33 10 77.162167
+33 11 77.646635
+33 12 79.630396
+33 13 80.411442
+33 14 82.152298
+33 15 83.360662
+33 16 85.586214
+33 17 87.572827
+33 18 88.283634
+33 19 49.739320
+33 20 49.244289
+33 21 47.434165
+33 22 53.235327
+33 23 49.335586
+33 24 55.009090
+33 25 51.244512
+33 26 57.697487
+33 27 8.000000
+33 28 9.433981
+33 29 5.000000
+33 30 5.830952
+33 31 1.000000
+33 32 5.099020
+33 34 5.385165
+33 35 5.385165
+33 36 58.523500
+33 37 59.236813
+33 38 56.462377
+33 39 55.901699
+33 40 56.824291
+33 41 61.269895
+33 42 53.535035
+33 43 59.363288
+33 44 63.631753
+33 45 61.057350
+33 46 84.811556
+33 47 85.211502
+33 48 86.313383
+33 49 51.478151
+33 50 48.466483
+33 51 15.811388
+33 52 33.526109
+33 53 62.000000
+33 54 69.921384
+33 55 43.863424
+33 56 64.412732
+33 57 37.336309
+33 58 57.218878
+33 59 74.726167
+33 60 77.646635
+33 61 78.000000
+33 62 54.671748
+33 63 22.561028
+33 64 24.166092
+33 65 42.000000
+33 66 52.952809
+33 67 46.529560
+33 68 25.942244
+33 69 55.758407
+33 70 60.166436
+33 71 65.000000
+33 72 33.301652
+33 73 42.438190
+33 74 90.138782
+33 75 67.742158
+33 76 85.726309
+33 77 32.449961
+33 78 69.462220
+33 79 83.168504
+33 80 89.470666
+33 81 43.462628
+33 82 47.201695
+33 83 61.392182
+33 84 50.009999
+33 85 30.016662
+33 86 25.000000
+33 87 66.272166
+33 88 75.239617
+33 89 68.942005
+33 90 32.015621
+33 91 52.810984
+33 92 39.849718
+33 93 36.400549
+33 94 34.058773
+33 95 34.985711
+33 96 31.780497
+33 97 40.000000
+33 98 83.862983
+33 99 64.845971
+33 100 61.204575
+33 101 67.119297
+34 1 51.478151
+34 2 84.852814
+34 3 80.430094
+34 4 87.000000
+34 5 85.146932
+34 6 88.459030
+34 7 83.600239
+34 8 86.023253
+34 9 89.022469
+34 10 75.663730
+34 11 76.485293
+34 12 78.447435
+34 13 79.555012
+34 14 80.622577
+34 15 82.462113
+34 16 84.344532
+34 17 86.313383
+34 18 87.321246
+34 19 45.617979
+34 20 45.541190
+34 21 44.147480
+34 22 49.244289
+34 23 46.097722
+34 24 51.078371
+34 25 48.052055
+34 26 53.851648
+34 27 11.180340
+34 28 14.142136
+34 29 8.602325
+34 30 11.180340
+34 31 5.830952
+34 32 10.440307
+34 33 5.385165
+34 35 10.000000
+34 36 62.641839
+34 37 63.245553
+34 38 60.406953
+34 39 59.615434
+34 40 60.415230
+34 41 65.000000
+34 42 56.824291
+34 43 62.649820
+34 44 67.082039
+34 45 64.412732
+34 46 86.452299
+34 47 86.683332
+34 48 85.375641
+34 49 47.423623
+34 50 44.922155
+34 51 16.401219
+34 52 30.413813
+34 53 60.207973
+34 54 69.641941
+34 55 46.097722
+34 56 65.192024
+34 57 36.400549
+34 58 55.000000
+34 59 71.589105
+34 60 75.166482
+34 61 78.262379
+34 62 56.568542
+34 63 22.360680
+34 64 20.615528
+34 65 40.311289
+34 66 52.201533
+34 67 45.607017
+34 68 27.018512
+34 69 57.008771
+34 70 60.373835
+34 71 66.603303
+34 72 36.055513
+34 73 45.650849
+34 74 90.077744
+34 75 65.192024
+34 76 82.462113
+34 77 28.178006
+34 78 65.787537
+34 79 83.006024
+34 80 89.944427
+34 81 43.908997
+34 82 48.836462
+34 83 60.728906
+34 84 48.373546
+34 85 28.284271
+34 86 22.090722
+34 87 64.007812
+34 88 73.006849
+34 89 69.354164
+34 90 26.907248
+34 91 52.801515
+34 92 39.812058
+34 93 36.715120
+34 94 36.124784
+34 95 36.235342
+34 96 31.384710
+34 97 41.725292
+34 98 81.301906
+34 99 64.884513
+34 100 59.841457
+34 101 68.410526
+35 1 47.434165
+35 2 78.102497
+35 3 74.625733
+35 4 80.430094
+35 5 79.056942
+35 6 82.006097
+35 7 78.032045
+35 8 80.622577
+35 9 83.216585
+35 10 75.000000
+35 11 75.166482
+35 12 77.162167
+35 13 77.646635
+35 14 80.000000
+35 15 80.622577
+35 16 83.150466
+35 17 85.146932
+35 18 85.586214
+35 19 50.803543
+35 20 49.739320
+35 21 47.423623
+35 22 54.083269
+35 23 49.244289
+35 24 55.758407
+35 25 51.078371
+35 26 58.309519
+35 27 11.180340
+35 28 10.000000
+35 29 8.602325
+35 30 5.000000
+35 31 5.830952
+35 32 3.000000
+35 33 5.385165
+35 34 10.000000
+35 36 53.141321
+35 37 53.851648
+35 38 51.078371
+35 39 50.537115
+35 40 51.478151
+35 41 55.901699
+35 42 48.259714
+35 43 54.083269
+35 44 58.309519
+35 45 55.758407
+35 46 80.212219
+35 47 80.709355
+35 48 83.600239
+35 49 52.430907
+35 50 48.764741
+35 51 13.000000
+35 52 33.541020
+35 53 60.207973
+35 54 66.708320
+35 55 39.051248
+35 56 60.415230
+35 57 35.000000
+35 58 55.901699
+35 59 74.330344
+35 60 76.485293
+35 61 74.330344
+35 62 50.000000
+35 63 20.000000
+35 64 25.000000
+35 65 40.311289
+35 66 50.249378
+35 67 44.045431
+35 68 22.135944
+35 69 51.478151
+35 70 56.612719
+35 71 60.464866
+35 72 28.284271
+35 73 37.202150
+35 74 86.683332
+35 75 66.708320
+35 76 85.440037
+35 77 33.970576
+35 78 69.771054
+35 79 79.812280
+35 80 85.615419
+35 81 39.849718
+35 82 42.720019
+35 83 58.549125
+35 84 48.166378
+35 85 28.635642
+35 86 25.059928
+35 87 64.938432
+35 88 73.824115
+35 89 65.192024
+35 90 34.985711
+35 91 49.477268
+35 92 36.674242
+35 93 32.984845
+35 94 29.410882
+35 95 30.870698
+35 96 29.068884
+35 97 35.510562
+35 98 82.764727
+35 99 61.400326
+35 100 59.000000
+35 101 62.769419
+36 1 44.204072
+36 2 42.000000
+36 3 46.097722
+36 4 45.000000
+36 5 47.265209
+36 6 47.000000
+36 7 50.009999
+36 8 52.952809
+36 9 52.239832
+36 10 75.822160
+36 11 72.622311
+36 12 74.202426
+36 13 71.281134
+36 14 79.649231
+36 15 73.783467
+36 16 79.056942
+36 17 80.709355
+36 18 78.032045
+36 19 83.240615
+36 20 79.056942
+36 21 74.330344
+36 22 84.433406
+36 23 75.026662
+36 24 85.094066
+36 25 75.769387
+36 26 86.162637
+36 27 61.717096
+36 28 57.306195
+36 29 60.415230
+36 30 55.036352
+36 31 58.872744
+36 32 54.230987
+36 33 58.523500
+36 34 62.641839
+36 35 53.141321
+36 37 2.000000
+36 38 3.605551
+36 39 7.071068
+36 40 8.602325
+36 41 7.000000
+36 42 13.453624
+36 43 13.000000
+36 44 12.000000
+36 45 12.369317
+36 46 47.095647
+36 47 49.254441
+36 48 76.321688
+36 49 83.815273
+36 50 77.162167
+36 51 50.249378
+36 52 66.098411
+36 53 69.202601
+36 54 58.600341
+36 55 27.730849
+36 56 44.654227
+36 57 52.810984
+36 58 70.491134
+36 59 91.263355
+36 60 86.452299
+36 61 57.697487
+36 62 29.732137
+36 63 50.039984
+36 64 65.030762
+36 65 59.236813
+36 66 55.217751
+36 67 54.589376
+36 68 43.104524
+36 69 36.796739
+36 70 48.836462
+36 71 35.777088
+36 72 30.066593
+36 73 20.396078
+36 74 69.641941
+36 75 80.212219
+36 76 101.212647
+36 77 73.334848
+36 78 93.059121
+36 79 65.741920
+36 80 63.324561
+36 81 42.941821
+36 82 32.449961
+36 83 58.000000
+36 84 61.773781
+36 85 56.885851
+36 86 62.128898
+36 87 76.400262
+36 88 82.134037
+36 89 50.774009
+36 90 80.000000
+36 91 48.414874
+36 92 46.615448
+36 93 44.271887
+36 94 33.541020
+36 95 38.327536
+36 96 49.244289
+36 97 33.241540
+36 98 91.967386
+36 99 52.630789
+36 100 64.660653
+36 101 40.249224
+37 1 43.011626
+37 2 40.000000
+37 3 44.147480
+37 4 43.000000
+37 5 45.276926
+37 6 45.000000
+37 7 48.052055
+37 8 50.990195
+37 9 50.249378
+37 10 74.330344
+37 11 71.063352
+37 12 72.622311
+37 13 69.634761
+37 14 78.102497
+37 15 72.111026
+37 16 77.420927
+37 17 79.056942
+37 18 76.321688
+37 19 82.710338
+37 20 78.447435
+37 21 73.681748
+37 22 83.815273
+37 23 74.330344
+37 24 84.433406
+37 25 75.026662
+37 26 85.440037
+37 27 62.649820
+37 28 58.309519
+37 29 61.269895
+37 30 55.901699
+37 31 59.615434
+37 32 55.036352
+37 33 59.236813
+37 34 63.245553
+37 35 53.851648
+37 36 2.000000
+37 38 3.000000
+37 39 5.830952
+37 40 7.071068
+37 41 5.000000
+37 42 12.206556
+37 43 11.180340
+37 44 10.000000
+37 45 10.440307
+37 46 45.099889
+37 47 47.265209
+37 48 74.625733
+37 49 83.240615
+37 50 76.537572
+37 51 50.487622
+37 52 65.764732
+37 53 68.007353
+37 54 57.008771
+37 55 26.925824
+37 56 43.011626
+37 57 52.201533
+37 58 69.462220
+37 59 90.138782
+37 60 85.146932
+37 61 55.901699
+37 62 28.284271
+37 63 50.000000
+37 64 65.000000
+37 65 58.523500
+37 66 54.083269
+37 67 53.665631
+37 68 43.011626
+37 69 35.355339
+37 70 47.381431
+37 71 34.000000
+37 72 30.000000
+37 73 20.099751
+37 74 67.779053
+37 75 79.056942
+37 76 100.000000
+37 77 73.171033
+37 78 92.130342
+37 79 63.953108
+37 80 61.400326
+37 81 42.047592
+37 82 31.384710
+37 83 56.639209
+37 84 60.827625
+37 85 56.568542
+37 86 62.032250
+37 87 75.213031
+37 88 80.808415
+37 89 49.091751
+37 90 80.024996
+37 91 47.201695
+37 92 45.880279
+37 93 43.680659
+37 94 33.241540
+37 95 37.854986
+37 96 48.836462
+37 97 32.572995
+37 98 90.609050
+37 99 51.088159
+37 100 63.411355
+37 101 38.470768
+38 1 40.607881
+38 2 40.112342
+38 3 43.566042
+38 4 43.104524
+38 5 45.044423
+38 6 45.099889
+38 7 47.518417
+38 8 50.487622
+38 9 50.039984
+38 10 72.346389
+38 11 69.202601
+38 12 70.802542
+38 13 67.955868
+38 14 76.216796
+38 15 70.491134
+38 16 75.716577
+38 17 77.388630
+38 18 74.793048
+38 19 79.812280
+38 20 75.584390
+38 21 70.837843
+38 22 80.956779
+38 23 71.512237
+38 24 81.596569
+38 25 72.235725
+38 26 82.637764
+38 27 60.033324
+38 28 55.758407
+38 29 58.591808
+38 30 53.235327
+38 31 56.859476
+38 32 52.325902
+38 33 56.462377
+38 34 60.406953
+38 35 51.078371
+38 36 3.605551
+38 37 3.000000
+38 39 3.605551
+38 40 5.385165
+38 41 5.830952
+38 42 9.899495
+38 43 10.198039
+38 44 10.440307
+38 45 10.000000
+38 46 45.000000
+38 47 47.042534
+38 48 73.061618
+38 49 80.361682
+38 50 73.681748
+38 51 47.518417
+38 52 62.801274
+38 53 65.604878
+38 54 55.217751
+38 55 24.166092
+38 56 41.340053
+38 57 49.335586
+38 58 66.887966
+38 59 87.658428
+38 60 82.879430
+38 61 54.626001
+38 62 26.248809
+38 63 47.000000
+38 64 62.000000
+38 65 55.713553
+38 66 51.613952
+38 67 51.000000
+38 68 40.012498
+38 69 33.301652
+38 70 45.343136
+38 71 32.695565
+38 72 27.000000
+38 73 17.117243
+38 74 66.730802
+38 75 76.609399
+38 76 97.616597
+38 77 70.178344
+38 78 89.470666
+38 79 62.649820
+38 80 60.638272
+38 81 39.357337
+38 82 28.844410
+38 83 54.451814
+38 84 58.180753
+38 85 53.600373
+38 86 59.033889
+38 87 72.801099
+38 88 78.568442
+38 89 47.507894
+38 90 77.025970
+38 91 44.821870
+38 92 43.081318
+38 93 40.804412
+38 94 30.265492
+38 95 34.928498
+38 96 45.891176
+38 97 29.732137
+38 98 88.413800
+38 99 49.203658
+38 100 61.073726
+38 101 37.161808
+39 1 37.202150
+39 2 37.336309
+39 3 40.311289
+39 4 40.311289
+39 5 42.000000
+39 6 42.296572
+39 7 44.283180
+39 8 47.265209
+39 9 47.000000
+39 10 68.767725
+39 11 65.604878
+39 12 67.201190
+39 13 64.350602
+39 14 72.622311
+39 15 66.887966
+39 16 72.111026
+39 17 73.783467
+39 18 71.196910
+39 19 77.129761
+39 20 72.801099
+39 21 68.007353
+39 22 78.160092
+39 23 68.622154
+39 24 78.746428
+39 25 69.289249
+39 26 79.711982
+39 27 59.908263
+39 28 55.803226
+39 29 58.309519
+39 30 53.000000
+39 31 56.356011
+39 32 51.971146
+39 33 55.901699
+39 34 59.615434
+39 35 50.537115
+39 36 7.071068
+39 37 5.830952
+39 38 3.605551
+39 40 2.000000
+39 41 5.385165
+39 42 6.403124
+39 43 7.000000
+39 44 8.602325
+39 45 7.280110
+39 46 42.047592
+39 47 44.000000
+39 48 69.462220
+39 49 77.620873
+39 50 70.880181
+39 51 46.097722
+39 52 60.406953
+39 53 62.201286
+39 54 51.613952
+39 55 21.189620
+39 56 37.735925
+39 57 46.572524
+39 58 63.631753
+39 59 84.314886
+39 60 79.397733
+39 61 51.078371
+39 62 22.671568
+39 63 45.099889
+39 64 60.074953
+39 65 52.810984
+39 66 48.259714
+39 67 47.853944
+39 68 38.052595
+39 69 29.732137
+39 70 41.773197
+39 71 29.154759
+39 72 25.179357
+39 73 15.033296
+39 74 63.245553
+39 75 73.239334
+39 76 94.201911
+39 77 68.029405
+39 78 86.313383
+39 79 59.093147
+39 80 57.271284
+39 81 36.249138
+39 82 25.553865
+39 83 50.931326
+39 84 55.009090
+39 85 51.244512
+39 86 57.008771
+39 87 69.404611
+39 88 75.073298
+39 89 43.908997
+39 90 75.166482
+39 91 41.400483
+39 92 40.162171
+39 93 38.078866
+39 94 28.017851
+39 95 32.388269
+39 96 43.416587
+39 97 26.925824
+39 98 84.899941
+39 99 45.607017
+39 100 57.628118
+39 101 33.615473
+40 1 36.055513
+40 2 35.355339
+40 3 38.327536
+40 4 38.327536
+40 5 40.000000
+40 6 40.311289
+40 7 42.296572
+40 8 45.276926
+40 9 45.000000
+40 10 67.268120
+40 11 64.031242
+40 12 65.604878
+40 13 62.681736
+40 14 71.063352
+40 15 65.192024
+40 16 70.455660
+40 17 72.111026
+40 18 69.462220
+40 19 76.687678
+40 20 72.277244
+40 21 67.446275
+40 22 77.620873
+40 23 68.007353
+40 24 78.160092
+40 25 68.622154
+40 26 79.056942
+40 27 61.032778
+40 28 57.008771
+40 29 59.363288
+40 30 54.083269
+40 31 57.306195
+40 32 53.000000
+40 33 56.824291
+40 34 60.415230
+40 35 51.478151
+40 36 8.602325
+40 37 7.071068
+40 38 5.385165
+40 39 2.000000
+40 41 5.000000
+40 42 5.385165
+40 43 5.000000
+40 44 7.071068
+40 45 5.385165
+40 46 40.049969
+40 47 42.000000
+40 48 67.742158
+40 49 77.129761
+40 50 70.342022
+40 51 46.572524
+40 52 60.207973
+40 53 61.032778
+40 54 50.000000
+40 55 20.615528
+40 56 36.055513
+40 57 46.097722
+40 58 62.649820
+40 59 83.216585
+40 60 78.102497
+40 61 49.244289
+40 62 21.213203
+40 63 45.276926
+40 64 60.207973
+40 65 52.201533
+40 66 47.169906
+40 67 47.010637
+40 68 38.209946
+40 69 28.284271
+40 70 40.311289
+40 71 27.313001
+40 72 25.495098
+40 73 15.297059
+40 74 61.351447
+40 75 72.111026
+40 76 93.005376
+40 77 68.000000
+40 78 85.428333
+40 79 57.271284
+40 80 55.317267
+40 81 35.468296
+40 82 24.596748
+40 83 49.578221
+40 84 54.129474
+40 85 51.088159
+40 86 57.078893
+40 87 68.242216
+40 88 73.756356
+40 89 42.190046
+40 90 75.325958
+40 91 40.224371
+40 92 39.560081
+40 93 37.656341
+40 94 28.017851
+40 95 32.140317
+40 96 43.185646
+40 97 26.476405
+40 98 83.546394
+40 99 44.045431
+40 100 56.400355
+40 101 31.780497
+41 1 40.311289
+41 2 35.000000
+41 3 39.293765
+41 4 38.000000
+41 5 40.311289
+41 6 40.000000
+41 7 43.174066
+41 8 46.097722
+41 9 45.276926
+41 10 70.710678
+41 11 67.268120
+41 12 68.767725
+41 13 65.604878
+41 14 74.330344
+41 15 68.007353
+41 16 73.409809
+41 17 75.000000
+41 18 72.111026
+41 19 81.584312
+41 20 77.129761
+41 21 72.277244
+41 22 82.462113
+41 23 72.801099
+41 24 82.969874
+41 25 73.375745
+41 26 83.815273
+41 27 65.192024
+41 28 61.032778
+41 29 63.631753
+41 30 58.309519
+41 31 61.717096
+41 32 57.306195
+41 33 61.269895
+41 34 65.000000
+41 35 55.901699
+41 36 7.000000
+41 37 5.000000
+41 38 5.830952
+41 39 5.385165
+41 40 5.000000
+41 42 10.198039
+41 43 7.071068
+41 44 5.000000
+41 45 5.830952
+41 46 40.112342
+41 47 42.296572
+41 48 70.455660
+41 49 82.000000
+41 50 75.186435
+41 51 51.419841
+41 52 65.192024
+41 53 65.192024
+41 54 53.150729
+41 55 25.495098
+41 56 39.051248
+41 57 50.990195
+41 58 67.082039
+41 59 87.464278
+41 60 82.006097
+41 61 51.478151
+41 62 25.000000
+41 63 50.249378
+41 64 65.192024
+41 65 57.008771
+41 66 51.478151
+41 67 51.623638
+41 68 43.185646
+41 69 32.015621
+41 70 43.931765
+41 71 29.681644
+41 72 30.413813
+41 73 20.223748
+41 74 63.158531
+41 75 76.321688
+41 76 97.082439
+41 77 73.000000
+41 78 89.961103
+41 79 59.539903
+41 80 56.612719
+41 81 40.162171
+41 82 29.154759
+41 83 53.413481
+41 84 58.694122
+41 85 56.080300
+41 86 62.072538
+41 87 72.401657
+41 88 77.620873
+41 89 45.000000
+41 90 80.305666
+41 91 44.418465
+41 92 44.384682
+41 93 42.579338
+41 94 33.015148
+41 95 37.121422
+41 96 48.166378
+41 97 31.400637
+41 98 87.321246
+41 99 47.381431
+41 100 60.464866
+41 101 34.132096
+42 1 30.805844
+42 2 34.481879
+42 3 36.000000
+42 4 37.363083
+42 5 38.327536
+42 6 39.293765
+42 7 40.000000
+42 8 43.000000
+42 9 43.289722
+42 10 62.481997
+42 11 59.405387
+42 12 61.032778
+42 13 58.309519
+42 14 66.400301
+42 15 60.901560
+42 16 66.037868
+42 17 67.742158
+42 18 65.299311
+42 19 71.386273
+42 20 66.940272
+42 21 62.096699
+42 22 72.277244
+42 23 62.641839
+42 24 72.801099
+42 25 63.245553
+42 26 73.681748
+42 27 58.258047
+42 28 54.488531
+42 29 56.400355
+42 30 51.224994
+42 31 54.083269
+42 32 50.000000
+42 33 53.535035
+42 34 56.824291
+42 35 48.259714
+42 36 13.453624
+42 37 12.206556
+42 38 9.899495
+42 39 6.403124
+42 40 5.385165
+42 41 10.198039
+42 43 5.830952
+42 44 10.440307
+42 45 7.615773
+42 46 38.639358
+42 47 40.311289
+42 48 63.529521
+42 49 71.805292
+42 50 65.000000
+42 51 42.379240
+42 52 55.081757
+42 53 55.803226
+42 54 45.486262
+42 55 15.297059
+42 56 31.764760
+42 57 40.792156
+42 58 57.306195
+42 59 77.935871
+42 60 73.000000
+42 61 45.541190
+42 62 16.401219
+42 63 40.607881
+42 64 55.443665
+42 65 46.840154
+42 66 41.880783
+42 67 41.629317
+42 68 33.541020
+42 69 23.430749
+42 70 35.468296
+42 71 23.769729
+42 72 21.189620
+42 73 11.180340
+42 74 57.974132
+42 75 66.850580
+42 76 87.800911
+42 77 63.031738
+42 78 80.056230
+42 79 53.488316
+42 80 52.469038
+42 81 30.083218
+42 82 19.235384
+42 83 44.553339
+42 84 48.754487
+42 85 46.010868
+42 86 52.239832
+42 87 63.007936
+42 88 68.680419
+42 89 38.013156
+42 90 70.576200
+42 91 35.000000
+42 92 34.205263
+42 93 32.388269
+42 94 23.194827
+42 95 27.018512
+42 96 38.052595
+42 97 21.213203
+42 98 78.517514
+42 99 39.408121
+42 100 51.224994
+42 101 28.160256
+43 1 33.541020
+43 2 30.413813
+43 3 33.376639
+43 4 33.376639
+43 5 35.000000
+43 6 35.355339
+43 7 37.336309
+43 8 40.311289
+43 9 40.000000
+43 10 63.639610
+43 11 60.207973
+43 12 61.717096
+43 13 58.600341
+43 14 67.268120
+43 15 61.032778
+43 16 66.400301
+43 17 68.007353
+43 18 65.192024
+43 19 75.802375
+43 20 71.196910
+43 21 66.287254
+43 22 76.485293
+43 23 66.708320
+43 24 76.902536
+43 25 67.186308
+43 26 77.620873
+43 27 64.031242
+43 28 60.207973
+43 29 62.201286
+43 30 57.008771
+43 31 59.908263
+43 32 55.803226
+43 33 59.363288
+43 34 62.649820
+43 35 54.083269
+43 36 13.000000
+43 37 11.180340
+43 38 10.198039
+43 39 7.000000
+43 40 5.000000
+43 41 7.071068
+43 42 5.830952
+43 44 5.000000
+43 45 2.000000
+43 46 35.057096
+43 47 37.000000
+43 48 63.513778
+43 49 76.118329
+43 50 69.231496
+43 51 48.104054
+43 52 60.000000
+43 53 58.309519
+43 54 46.097722
+43 55 20.000000
+43 56 32.015621
+43 57 45.276926
+43 58 60.415230
+43 59 80.622577
+43 60 75.000000
+43 61 44.721360
+43 62 18.027756
+43 63 46.097722
+43 64 60.827625
+43 65 50.990195
+43 66 44.721360
+43 67 45.221676
+43 68 39.051248
+43 69 25.000000
+43 70 36.878178
+43 71 22.825424
+43 72 26.925824
+43 73 17.000000
+43 74 56.648036
+43 75 69.462220
+43 76 90.138782
+43 77 68.183576
+43 78 83.384651
+43 79 52.773099
+43 80 50.447993
+43 81 33.955854
+43 82 22.803509
+43 83 46.400431
+43 84 52.201533
+43 85 51.039201
+43 86 57.558666
+43 87 65.513357
+43 88 70.604532
+43 89 38.013156
+43 90 75.953933
+43 91 37.589892
+43 92 38.470768
+43 93 37.054015
+43 94 28.635642
+43 95 32.062439
+43 96 43.011626
+43 97 26.000000
+43 98 80.280757
+43 99 40.311289
+43 100 53.535035
+43 101 27.294688
+44 1 38.078866
+44 2 30.000000
+44 3 34.481879
+44 4 33.000000
+44 5 35.355339
+44 6 35.000000
+44 7 38.327536
+44 8 41.231056
+44 9 40.311289
+44 10 67.268120
+44 11 63.639610
+44 12 65.069194
+44 13 61.717096
+44 14 70.710678
+44 15 64.031242
+44 16 69.526973
+44 17 71.063352
+44 18 68.007353
+44 19 80.752709
+44 20 76.118329
+44 21 71.196910
+44 22 81.394103
+44 23 71.589105
+44 24 81.786307
+44 25 72.034714
+44 26 82.462113
+44 27 68.007353
+44 28 64.031242
+44 29 66.287254
+44 30 61.032778
+44 31 64.140471
+44 32 59.908263
+44 33 63.631753
+44 34 67.082039
+44 35 58.309519
+44 36 12.000000
+44 37 10.000000
+44 38 10.440307
+44 39 8.602325
+44 40 7.071068
+44 41 5.000000
+44 42 10.440307
+44 43 5.000000
+44 45 3.000000
+44 46 35.128336
+44 47 37.336309
+44 48 66.400301
+44 49 81.049368
+44 50 74.148500
+44 51 52.810984
+44 52 65.000000
+44 53 62.649820
+44 54 49.497475
+44 55 25.000000
+44 56 35.355339
+44 57 50.249378
+44 58 65.000000
+44 59 85.000000
+44 60 79.056942
+44 61 47.169906
+44 62 22.360680
+44 63 50.990195
+44 64 65.764732
+44 65 55.901699
+44 66 49.244289
+44 67 50.000000
+44 68 43.931765
+44 69 29.154759
+44 70 40.804412
+44 71 25.612497
+44 72 31.622777
+44 73 21.540659
+44 74 58.600341
+44 75 73.824115
+44 76 94.339811
+44 77 73.171033
+44 78 88.022724
+44 79 55.226805
+44 80 51.865210
+44 81 38.832976
+44 82 27.658633
+44 83 50.477718
+44 84 56.920998
+44 85 56.035703
+44 86 62.513998
+44 87 69.835521
+44 88 74.632433
+44 89 41.109610
+44 90 80.894994
+44 91 42.047592
+44 92 43.416587
+44 93 42.047592
+44 94 33.541020
+44 95 37.054015
+44 96 48.010416
+44 97 31.000000
+44 98 84.202138
+44 99 43.931765
+44 100 57.801384
+44 101 30.000000
+45 1 35.341194
+45 2 30.149627
+45 3 33.734256
+45 4 33.136083
+45 5 35.057096
+45 6 35.128336
+45 7 37.656341
+45 8 40.607881
+45 9 40.049969
+45 10 65.069194
+45 11 61.554854
+45 12 63.031738
+45 13 59.816386
+45 14 68.622154
+45 15 62.201286
+45 16 67.623960
+45 17 69.202601
+45 18 66.287254
+45 19 77.781746
+45 20 73.164199
+45 21 68.249542
+45 22 78.447435
+45 23 68.658576
+45 24 78.854296
+45 25 69.123079
+45 26 79.555012
+45 27 65.604878
+45 28 61.717096
+45 29 63.820060
+45 30 58.600341
+45 31 61.587336
+45 32 57.428216
+45 33 61.057350
+45 34 64.412732
+45 35 55.758407
+45 36 12.369317
+45 37 10.440307
+45 38 10.000000
+45 39 7.280110
+45 40 5.385165
+45 41 5.830952
+45 42 7.615773
+45 43 2.000000
+45 44 3.000000
+45 46 35.000000
+45 47 37.054015
+45 48 64.637450
+45 49 78.089692
+45 50 71.196910
+45 51 49.979996
+45 52 62.000000
+45 53 60.033324
+45 54 47.423623
+45 55 22.000000
+45 56 33.301652
+45 57 47.265209
+45 58 62.241465
+45 59 82.365041
+45 60 76.609399
+45 61 45.650849
+45 62 19.723083
+45 63 48.052055
+45 64 62.801274
+45 65 52.952809
+45 66 46.518813
+45 67 47.127487
+45 68 41.000000
+45 69 26.627054
+45 70 38.418745
+45 71 23.853721
+45 72 28.792360
+45 73 18.788294
+45 74 57.384667
+45 75 71.196910
+45 76 91.809586
+45 77 70.178344
+45 78 85.234969
+45 79 53.712196
+45 80 50.960769
+45 81 35.902646
+45 82 24.738634
+45 83 48.010416
+45 84 54.083269
+45 85 53.037722
+45 86 59.539903
+45 87 67.230945
+45 88 72.201108
+45 89 39.204592
+45 90 77.929455
+45 91 39.357337
+45 92 40.447497
+45 93 39.051248
+45 94 30.594117
+45 95 34.058773
+45 96 45.011110
+45 97 28.000000
+45 98 81.835200
+45 99 41.725292
+45 100 55.226805
+45 101 28.301943
+46 1 37.735925
+46 2 5.830952
+46 3 7.280110
+46 4 3.605551
+46 5 2.000000
+46 6 3.000000
+46 7 7.280110
+46 8 8.602325
+46 9 5.385165
+46 10 48.052055
+46 11 43.174066
+46 12 43.680659
+46 13 38.897301
+46 14 49.335586
+46 15 39.924930
+46 16 45.694639
+46 17 46.518813
+46 18 42.059482
+46 19 80.653580
+46 20 75.286121
+46 21 70.519501
+46 22 79.555012
+46 23 69.921384
+46 24 79.075913
+46 25 69.375788
+46 26 78.447435
+46 27 91.263355
+46 28 88.509886
+46 29 88.814413
+46 30 84.314886
+46 31 85.603738
+46 32 82.661962
+46 33 84.811556
+46 34 86.452299
+46 35 80.212219
+46 36 47.095647
+46 37 45.099889
+46 38 45.000000
+46 39 42.047592
+46 40 40.049969
+46 41 40.112342
+46 42 38.639358
+46 43 35.057096
+46 44 35.128336
+46 45 35.000000
+46 47 2.828427
+46 48 41.146081
+46 49 80.081209
+46 50 73.375745
+46 51 70.092796
+46 52 71.196910
+46 53 52.239832
+46 54 32.000000
+46 55 41.340053
+46 56 24.166092
+46 57 55.758407
+46 58 57.870545
+46 59 72.173402
+46 60 62.801274
+46 61 22.561028
+46 62 30.232433
+46 63 65.069194
+46 64 76.609399
+46 65 57.697487
+46 66 44.598206
+46 67 49.658836
+46 68 59.464275
+46 69 29.732137
+46 70 31.953091
+46 71 19.849433
+46 72 52.478567
+46 73 46.238512
+46 74 28.425341
+46 75 62.000000
+46 76 78.447435
+46 77 80.622577
+46 78 79.056942
+46 79 28.635642
+46 80 19.798990
+46 81 44.204072
+46 82 37.643060
+46 83 39.623226
+46 84 53.758720
+46 85 64.637450
+46 86 73.006849
+46 87 58.008620
+46 88 58.549125
+46 89 24.331050
+46 90 90.210864
+46 91 38.910153
+46 92 49.406477
+46 93 51.088159
+46 94 50.803543
+46 95 50.249378
+46 96 57.628118
+46 97 44.821870
+46 98 65.969690
+46 99 30.594117
+46 100 47.381431
+46 101 18.601075
+47 1 37.202150
+47 2 8.602325
+47 3 6.403124
+47 4 6.403124
+47 5 2.000000
+47 6 5.385165
+47 7 5.000000
+47 8 5.830952
+47 9 3.000000
+47 10 45.705580
+47 11 40.792156
+47 12 41.231056
+47 13 36.400549
+47 14 46.840154
+47 15 37.336309
+47 16 43.081318
+47 17 43.863424
+47 18 39.357337
+47 19 79.378838
+47 20 74.000000
+47 21 69.289249
+47 22 78.160092
+47 23 68.622154
+47 24 77.620873
+47 25 68.007353
+47 26 76.902536
+47 27 91.809586
+47 28 89.185201
+47 29 89.308454
+47 30 84.905830
+47 31 86.023253
+47 32 83.216585
+47 33 85.211502
+47 34 86.683332
+47 35 80.709355
+47 36 49.254441
+47 37 47.265209
+47 38 47.042534
+47 39 44.000000
+47 40 42.000000
+47 41 42.296572
+47 42 40.311289
+47 43 37.000000
+47 44 37.336309
+47 45 37.054015
+47 46 2.828427
+47 48 38.483763
+47 49 78.746428
+47 50 72.111026
+47 51 70.292247
+47 52 70.491134
+47 53 50.487622
+47 54 30.066593
+47 55 42.059482
+47 56 23.323808
+47 57 55.217751
+47 58 56.293872
+47 59 70.064256
+47 60 60.530984
+47 61 20.223748
+47 62 30.886890
+47 63 65.069194
+47 64 76.216796
+47 65 56.824291
+47 66 43.462628
+47 67 48.764741
+47 68 59.665736
+47 69 29.732137
+47 70 30.870698
+47 71 20.248457
+47 72 53.235327
+47 73 47.434165
+47 74 25.612497
+47 75 60.033324
+47 76 76.118329
+47 77 79.924965
+47 78 77.162167
+47 79 26.000000
+47 80 16.970563
+47 81 43.931765
+47 82 38.013156
+47 83 38.078866
+47 84 52.554733
+47 85 64.202804
+47 86 72.622311
+47 87 56.080300
+47 88 56.320511
+47 89 22.803509
+47 90 89.587946
+47 91 38.078866
+47 92 49.040799
+47 93 50.931326
+47 94 51.312766
+47 95 50.447993
+47 96 57.384667
+47 97 45.221676
+47 98 63.560994
+47 99 29.120440
+47 100 45.705580
+47 101 18.384776
+48 1 38.327536
+48 2 46.141088
+48 3 36.055513
+48 4 44.721360
+48 5 39.357337
+48 6 43.863424
+48 7 34.000000
+48 8 32.695565
+48 9 37.336309
+48 10 12.806248
+48 11 9.433981
+48 12 7.810250
+48 13 6.000000
+48 14 10.440307
+48 15 3.000000
+48 16 5.000000
+48 17 5.385165
+48 18 2.000000
+48 19 58.000000
+48 20 53.150729
+48 21 50.000000
+48 22 55.172457
+48 23 48.414874
+48 24 53.814496
+48 25 46.861498
+48 26 51.855569
+48 27 94.201911
+48 28 93.536089
+48 29 91.241438
+48 30 88.566359
+48 31 87.298339
+48 32 86.579443
+48 33 86.313383
+48 34 85.375641
+48 35 83.600239
+48 36 76.321688
+48 37 74.625733
+48 38 73.061618
+48 39 69.462220
+48 40 67.742158
+48 41 70.455660
+48 42 63.529521
+48 43 63.513778
+48 44 66.400301
+48 45 64.637450
+48 46 41.146081
+48 47 38.483763
+48 49 56.568542
+48 50 51.855569
+48 51 70.710678
+48 52 58.600341
+48 53 27.459060
+48 54 18.681542
+48 55 55.081757
+48 56 31.764760
+48 57 49.030603
+48 58 34.409301
+48 59 37.336309
+48 60 26.248809
+48 61 19.849433
+48 62 47.423623
+48 63 63.788714
+48 64 67.779053
+48 65 45.541190
+48 66 33.376639
+48 67 39.812058
+48 68 62.072538
+48 69 40.853396
+48 70 29.832868
+48 71 40.804412
+48 72 63.788714
+48 73 64.195015
+48 74 15.000000
+48 75 30.805844
+48 76 40.112342
+48 77 66.730802
+48 78 46.957428
+48 79 12.529964
+48 80 23.345235
+48 81 45.044423
+48 82 48.764741
+48 83 25.079872
+48 84 37.696154
+48 85 57.280014
+48 86 64.845971
+48 87 28.319605
+48 88 23.259407
+48 89 25.553865
+48 90 76.321688
+48 91 35.057096
+48 92 47.095647
+48 93 51.039201
+48 94 59.413803
+48 95 55.081757
+48 96 54.589376
+48 97 53.758720
+48 98 27.073973
+48 99 25.000000
+48 100 26.000000
+48 101 36.400549
+49 1 45.044423
+49 2 81.786307
+49 3 72.801099
+49 4 82.462113
+49 5 78.160092
+49 6 82.969874
+49 7 74.000000
+49 8 75.026662
+49 9 79.711982
+49 10 43.863424
+49 11 47.423623
+49 12 48.795492
+49 13 52.497619
+49 14 47.634021
+49 15 54.488531
+49 16 53.150729
+49 17 54.671748
+49 18 58.000000
+49 19 2.000000
+49 20 5.000000
+49 21 10.000000
+49 22 2.000000
+49 23 10.198039
+49 24 4.000000
+49 25 10.770330
+49 26 7.000000
+49 27 58.600341
+49 28 60.901560
+49 29 55.901699
+49 30 56.603887
+49 31 52.354560
+49 32 54.918121
+49 33 51.478151
+49 34 47.423623
+49 35 52.430907
+49 36 83.815273
+49 37 83.240615
+49 38 80.361682
+49 39 77.620873
+49 40 77.129761
+49 41 82.000000
+49 42 71.805292
+49 43 76.118329
+49 44 81.049368
+49 45 78.089692
+49 46 80.081209
+49 47 78.746428
+49 48 56.568542
+49 50 7.000000
+49 51 42.426407
+49 52 19.849433
+49 53 30.232433
+49 54 50.089919
+49 55 56.515485
+49 56 56.293872
+49 57 31.048349
+49 58 23.323808
+49 59 27.459060
+49 60 35.341194
+49 61 61.269895
+49 62 60.074953
+49 63 37.802116
+49 64 27.459060
+49 65 25.179357
+49 66 35.693137
+49 67 32.015621
+49 68 43.046487
+49 69 55.036352
+49 70 48.270074
+49 71 64.381674
+49 72 55.036352
+49 73 63.568860
+49 74 68.007353
+49 75 26.627054
+49 76 37.000000
+49 77 19.313208
+49 78 19.104973
+49 79 61.294372
+49 80 72.560320
+49 81 42.296572
+49 82 53.460266
+49 83 40.853396
+49 84 26.476405
+49 85 28.301943
+49 86 27.658633
+49 87 28.319605
+49 88 35.510562
+49 89 55.973208
+49 90 25.000000
+49 91 42.296572
+49 92 37.656341
+49 93 39.560081
+49 94 50.695167
+49 95 45.541190
+49 96 34.928498
+49 97 50.695167
+49 98 40.162171
+49 99 49.648766
+49 100 34.000000
+49 101 62.968246
+50 1 38.052595
+50 2 74.953319
+50 3 66.098411
+50 4 75.690158
+50 5 71.470274
+50 6 76.243032
+50 7 67.416615
+50 8 68.541958
+50 9 73.164199
+50 10 39.408121
+50 11 42.520583
+50 12 44.045431
+50 13 47.381431
+50 14 43.566042
+50 15 49.578221
+50 16 48.826222
+50 17 50.477718
+50 18 53.413481
+50 19 7.280110
+50 20 2.000000
+50 21 3.000000
+50 22 7.280110
+50 23 3.605551
+50 24 8.062258
+50 25 5.000000
+50 26 9.899495
+50 27 55.973208
+50 28 57.775427
+50 29 53.141321
+50 30 53.225934
+50 31 49.396356
+50 32 51.429563
+50 33 48.466483
+50 34 44.922155
+50 35 48.764741
+50 36 77.162167
+50 37 76.537572
+50 38 73.681748
+50 39 70.880181
+50 40 70.342022
+50 41 75.186435
+50 42 65.000000
+50 43 69.231496
+50 44 74.148500
+50 45 71.196910
+50 46 73.375745
+50 47 72.111026
+50 48 51.855569
+50 49 7.000000
+50 51 37.802116
+50 52 15.264338
+50 53 24.758837
+50 54 43.908997
+50 55 49.729267
+50 56 49.477268
+50 57 24.351591
+50 58 17.691806
+50 59 27.073973
+50 60 32.984845
+50 61 55.072679
+50 62 53.084838
+50 63 32.526912
+50 64 24.351591
+50 65 18.248288
+50 66 28.861739
+50 67 25.019992
+50 68 37.202150
+50 69 48.041649
+50 70 41.484937
+50 71 57.428216
+50 72 48.764741
+50 73 57.008771
+50 74 62.481997
+50 75 23.409400
+50 76 37.656341
+50 77 18.000000
+50 78 21.023796
+50 79 55.605755
+50 80 66.573268
+50 81 35.355339
+50 82 46.529560
+50 83 34.438351
+50 84 19.646883
+50 85 22.671568
+50 86 23.706539
+50 87 24.186773
+50 88 32.310989
+50 89 49.396356
+50 90 25.961510
+50 91 35.355339
+50 92 30.805844
+50 93 32.893768
+50 94 44.283180
+50 95 39.000000
+50 96 28.653098
+50 97 43.965896
+50 98 38.470768
+50 99 43.081318
+50 100 28.017851
+50 101 56.089215
+51 1 35.341194
+51 2 68.622154
+51 3 64.031242
+51 4 70.710678
+51 5 68.767725
+51 6 72.138755
+51 7 67.201190
+51 8 69.634761
+51 9 72.622311
+51 10 62.000000
+51 11 62.201286
+51 12 64.195015
+51 13 64.776539
+51 14 67.000000
+51 15 67.742158
+51 16 70.178344
+51 17 72.173402
+51 18 72.691127
+51 19 41.036569
+51 20 39.051248
+51 21 36.055513
+51 22 43.863424
+51 23 37.735925
+51 24 45.343136
+51 25 39.446166
+51 26 47.634021
+51 27 23.537205
+51 28 23.000000
+51 29 20.615528
+51 30 18.000000
+51 31 16.763055
+51 32 16.000000
+51 33 15.811388
+51 34 16.401219
+51 35 13.000000
+51 36 50.249378
+51 37 50.487622
+51 38 47.518417
+51 39 46.097722
+51 40 46.572524
+51 41 51.419841
+51 42 42.379240
+51 43 48.104054
+51 44 52.810984
+51 45 49.979996
+51 46 70.092796
+51 47 70.292247
+51 48 70.710678
+51 49 42.426407
+51 50 37.802116
+51 52 22.671568
+51 53 47.265209
+51 54 54.120237
+51 55 30.232433
+51 56 48.877398
+51 57 22.000000
+51 58 43.174066
+51 59 62.241465
+51 60 63.788714
+51 61 62.241465
+51 62 40.360872
+51 63 7.000000
+51 64 16.552945
+51 65 27.459060
+51 66 37.336309
+51 67 31.064449
+51 68 10.630146
+51 69 40.607881
+51 70 44.384682
+51 71 50.249378
+51 72 21.189620
+51 73 31.320920
+51 74 74.330344
+51 75 54.120237
+51 76 73.409809
+51 77 25.942244
+51 78 58.523500
+51 79 67.357256
+51 80 73.790243
+51 81 27.730849
+51 82 32.526912
+51 83 45.705580
+51 84 35.227830
+51 85 16.155494
+51 86 15.000000
+51 87 52.172790
+51 88 61.000000
+51 89 53.225934
+51 90 30.413813
+51 91 37.000000
+51 92 24.041631
+51 93 20.615528
+51 94 20.248457
+51 95 19.849433
+51 96 16.124515
+51 97 25.495098
+51 98 70.092796
+51 99 49.040799
+51 100 46.000000
+51 101 52.009614
+52 1 33.541020
+52 2 71.589105
+52 3 64.140471
+52 4 72.897188
+52 5 69.462220
+52 6 73.824115
+52 7 66.287254
+52 8 68.007353
+52 9 72.111026
+52 10 47.434165
+52 11 49.244289
+52 12 51.078371
+52 13 53.235327
+52 14 52.201533
+52 15 55.901699
+52 16 56.648036
+52 17 58.523500
+52 18 60.415230
+52 19 18.601075
+52 20 16.401219
+52 21 13.928388
+52 22 21.213203
+52 23 15.811388
+52 24 22.671568
+52 25 17.720045
+52 26 25.000000
+52 27 41.231056
+52 28 42.720019
+52 29 38.327536
+52 30 38.078866
+52 31 34.481879
+52 32 36.249138
+52 33 33.526109
+52 34 30.413813
+52 35 33.541020
+52 36 66.098411
+52 37 65.764732
+52 38 62.801274
+52 39 60.406953
+52 40 60.207973
+52 41 65.192024
+52 42 55.081757
+52 43 60.000000
+52 44 65.000000
+52 45 62.000000
+52 46 71.196910
+52 47 70.491134
+52 48 58.600341
+52 49 19.849433
+52 50 15.264338
+52 51 22.671568
+52 53 31.622777
+52 54 46.097722
+52 55 40.000000
+52 56 47.169906
+52 57 15.811388
+52 58 25.495098
+52 59 41.231056
+52 60 45.000000
+52 61 56.568542
+52 62 46.097722
+52 63 18.027756
+52 64 10.000000
+52 65 14.142136
+52 66 28.284271
+52 67 22.022716
+52 68 23.769729
+52 69 42.720019
+52 70 40.000000
+52 71 52.924474
+52 72 36.400549
+52 73 45.705580
+52 74 66.400301
+52 75 35.000000
+52 76 52.201533
+52 77 9.433981
+52 78 36.235342
+52 79 59.203040
+52 80 68.593003
+52 81 28.160256
+52 82 38.470768
+52 83 36.235342
+52 84 21.095023
+52 85 9.219544
+52 86 8.544004
+52 87 34.234486
+52 88 43.185646
+52 89 49.040799
+52 90 19.209373
+52 91 32.449961
+52 92 22.803509
+52 93 23.086793
+52 94 32.557641
+52 95 28.071338
+52 96 17.029386
+52 97 34.000000
+52 98 51.039201
+52 99 43.185646
+52 100 32.649655
+52 101 52.773099
+53 1 25.000000
+53 2 55.000000
+53 3 45.099889
+53 4 55.081757
+53 5 50.249378
+53 6 55.226805
+53 7 45.541190
+53 8 46.097722
+53 9 50.990195
+53 10 15.811388
+53 11 18.027756
+53 12 19.723083
+53 13 22.671568
+53 14 20.615528
+53 15 25.000000
+53 16 25.079872
+53 17 26.925824
+53 18 29.154759
+53 19 31.400637
+53 20 26.248809
+53 21 22.671568
+53 22 29.154759
+53 23 21.213203
+53 24 28.178006
+53 25 19.849433
+53 26 26.925824
+53 27 70.000000
+53 28 70.178344
+53 29 67.000000
+53 30 65.192024
+53 31 63.000000
+53 32 63.198101
+53 33 62.000000
+53 34 60.207973
+53 35 60.207973
+53 36 69.202601
+53 37 68.007353
+53 38 65.604878
+53 39 62.201286
+53 40 61.032778
+53 41 65.192024
+53 42 55.803226
+53 43 58.309519
+53 44 62.649820
+53 45 60.033324
+53 46 52.239832
+53 47 50.487622
+53 48 27.459060
+53 49 30.232433
+53 50 24.758837
+53 51 47.265209
+53 52 31.622777
+53 54 20.615528
+53 55 42.426407
+53 56 30.413813
+53 57 25.495098
+53 58 7.071068
+53 59 22.360680
+53 60 18.027756
+53 61 31.622777
+53 62 40.311289
+53 63 40.311289
+53 64 41.231056
+53 65 20.000000
+53 66 14.142136
+53 67 17.464249
+53 68 40.804412
+53 69 33.541020
+53 70 22.803509
+53 71 40.261644
+53 72 47.169906
+53 73 51.662365
+53 74 37.802116
+53 75 11.180340
+53 76 32.015621
+53 77 39.357337
+53 78 27.073973
+53 79 31.064449
+53 80 42.485292
+53 81 27.802878
+53 82 36.878178
+53 83 13.152946
+53 84 12.041595
+53 85 32.015621
+53 86 38.639358
+53 87 7.211103
+53 88 14.317821
+53 89 28.017851
+53 90 48.877398
+53 91 20.808652
+53 92 26.832816
+53 93 30.870698
+53 94 42.190046
+53 95 36.715120
+53 96 31.780497
+53 97 38.418745
+53 98 24.186773
+53 99 22.022716
+53 100 5.099020
+53 101 37.483330
+54 1 20.000000
+54 2 35.355339
+54 3 25.079872
+54 4 35.057096
+54 5 30.000000
+54 6 35.000000
+54 7 25.079872
+54 8 25.495098
+54 9 30.413813
+54 10 18.027756
+54 11 14.142136
+54 12 15.620499
+54 13 13.000000
+54 14 21.213203
+54 15 15.811388
+54 16 20.591260
+54 17 22.360680
+54 18 20.615528
+54 19 51.000000
+54 20 45.650849
+54 21 41.340053
+54 22 49.244289
+54 23 40.311289
+54 24 48.466483
+54 25 39.357337
+54 26 47.434165
+54 27 77.620873
+54 28 76.485293
+54 29 74.726167
+54 30 71.589105
+54 31 70.880181
+54 32 69.634761
+54 33 69.921384
+54 34 69.641941
+54 35 66.708320
+54 36 58.600341
+54 37 57.008771
+54 38 55.217751
+54 39 51.613952
+54 40 50.000000
+54 41 53.150729
+54 42 45.486262
+54 43 46.097722
+54 44 49.497475
+54 45 47.423623
+54 46 32.000000
+54 47 30.066593
+54 48 18.681542
+54 49 50.089919
+54 50 43.908997
+54 51 54.120237
+54 52 46.097722
+54 53 20.615528
+54 55 36.400549
+54 56 14.142136
+54 57 33.541020
+54 58 26.925824
+54 59 40.311289
+54 60 31.622777
+54 61 11.180340
+54 62 29.154759
+54 63 47.434165
+54 64 54.083269
+54 65 32.015621
+54 66 18.027756
+54 67 24.698178
+54 68 44.721360
+54 69 22.360680
+54 70 11.180340
+54 71 24.207437
+54 72 45.276926
+54 73 45.541190
+54 74 20.591260
+54 75 30.000000
+54 76 47.434165
+54 77 55.172457
+54 78 47.095647
+54 79 13.416408
+54 80 22.803509
+54 81 27.166155
+54 82 30.083218
+54 83 9.899495
+54 84 25.495098
+54 85 42.544095
+54 86 50.774009
+54 87 26.019224
+54 88 27.202941
+54 89 8.944272
+54 90 65.069194
+54 91 17.262677
+54 92 30.083218
+54 93 33.734256
+54 94 41.048752
+54 95 37.054015
+54 96 38.275318
+54 97 35.227830
+54 98 35.777088
+54 99 6.324555
+54 100 16.155494
+54 101 20.248457
+55 1 18.027756
+55 2 39.051248
+55 3 36.249138
+55 4 41.400483
+55 5 40.311289
+55 6 43.011626
+55 7 39.924930
+55 8 42.720019
+55 9 44.721360
+55 10 51.478151
+55 11 49.244289
+55 12 51.078371
+55 13 49.335586
+55 14 55.901699
+55 15 52.201533
+55 16 56.648036
+55 17 58.523500
+55 18 57.008771
+55 19 56.089215
+55 20 51.662365
+55 21 46.840154
+55 22 57.008771
+55 23 47.434165
+55 24 57.567352
+55 25 48.104054
+55 26 58.523500
+55 27 50.000000
+55 28 47.169906
+55 29 47.634021
+55 30 43.011626
+55 31 44.598206
+55 32 41.400483
+55 33 43.863424
+55 34 46.097722
+55 35 39.051248
+55 36 27.730849
+55 37 26.925824
+55 38 24.166092
+55 39 21.189620
+55 40 20.615528
+55 41 25.495098
+55 42 15.297059
+55 43 20.000000
+55 44 25.000000
+55 45 22.000000
+55 46 41.340053
+55 47 42.059482
+55 48 55.081757
+55 49 56.515485
+55 50 49.729267
+55 51 30.232433
+55 52 40.000000
+55 53 42.426407
+55 54 36.400549
+55 56 25.000000
+55 57 25.495098
+55 58 43.011626
+55 59 64.031242
+55 60 60.207973
+55 61 40.000000
+55 62 11.180340
+55 63 26.925824
+55 64 41.231056
+55 65 31.622777
+55 66 28.284271
+55 67 26.925824
+55 68 20.124612
+55 69 15.000000
+55 70 25.298221
+55 71 21.931712
+55 72 11.180340
+55 73 9.433981
+55 74 53.000000
+55 75 53.150729
+55 76 74.330344
+55 77 48.259714
+55 78 65.368188
+55 79 47.169906
+55 80 49.648766
+55 81 15.264338
+55 82 6.324555
+55 83 32.756679
+55 84 34.132096
+55 85 31.064449
+55 86 37.854986
+55 87 49.517674
+55 88 56.080300
+55 89 31.064449
+55 90 56.293872
+55 91 22.203603
+55 92 18.973666
+55 93 17.117243
+55 94 10.000000
+55 95 12.165525
+55 96 23.021729
+55 97 6.000000
+55 98 66.068147
+55 99 30.083218
+55 100 38.288379
+55 101 25.000000
+56 1 14.142136
+56 2 25.495098
+56 3 17.000000
+56 4 26.248809
+56 5 22.360680
+56 6 26.925824
+56 7 19.209373
+56 8 21.213203
+56 9 25.000000
+56 10 32.015621
+56 11 28.284271
+56 12 29.732137
+56 13 26.627054
+56 14 35.355339
+56 15 29.154759
+56 16 34.409301
+56 17 36.055513
+56 18 33.541020
+56 19 56.753854
+56 20 51.419841
+56 21 46.572524
+56 22 55.901699
+56 23 46.097722
+56 24 55.578773
+56 25 45.705580
+56 26 55.226805
+56 27 71.589105
+56 28 69.641941
+56 29 68.876701
+56 30 65.000000
+56 31 65.299311
+56 32 63.158531
+56 33 64.412732
+56 34 65.192024
+56 35 60.415230
+56 36 44.654227
+56 37 43.011626
+56 38 41.340053
+56 39 37.735925
+56 40 36.055513
+56 41 39.051248
+56 42 31.764760
+56 43 32.015621
+56 44 35.355339
+56 45 33.301652
+56 46 24.166092
+56 47 23.323808
+56 48 31.764760
+56 49 56.293872
+56 50 49.477268
+56 51 48.877398
+56 52 47.169906
+56 53 30.413813
+56 54 14.142136
+56 55 25.000000
+56 57 32.015621
+56 58 35.000000
+56 59 52.201533
+56 60 44.721360
+56 61 15.000000
+56 62 15.811388
+56 63 43.011626
+56 64 53.150729
+56 65 33.541020
+56 66 20.615528
+56 67 25.495098
+56 68 38.470768
+56 69 10.000000
+56 70 8.062258
+56 71 10.295630
+56 72 35.355339
+56 73 33.376639
+56 74 28.000000
+56 75 41.231056
+56 76 60.415230
+56 77 56.603887
+56 78 57.428216
+56 79 22.360680
+56 80 25.298221
+56 81 21.400935
+56 82 19.104973
+56 83 17.262677
+56 84 29.832868
+56 85 41.109610
+56 86 49.578221
+56 87 37.107951
+56 88 40.249224
+56 89 6.324555
+56 90 66.287254
+56 91 14.764823
+56 92 26.172505
+56 93 28.600699
+56 94 32.015621
+56 95 29.546573
+56 96 34.713110
+56 97 25.709920
+56 98 49.396356
+56 99 8.944272
+56 100 25.317978
+56 101 7.071068
+57 1 18.027756
+57 2 55.901699
+57 3 48.826222
+57 4 57.306195
+57 5 54.083269
+57 6 58.309519
+57 7 51.224994
+57 8 53.150729
+57 9 57.008771
+57 10 40.000000
+57 11 40.311289
+57 12 42.296572
+57 13 43.174066
+57 14 45.000000
+57 15 46.097722
+57 16 48.259714
+57 17 50.249378
+57 18 50.990195
+57 19 30.594117
+57 20 26.248809
+57 21 21.540659
+57 22 31.622777
+57 23 22.360680
+57 24 32.310989
+57 25 23.323808
+57 26 33.541020
+57 27 45.276926
+57 28 45.000000
+57 29 42.296572
+57 30 40.000000
+57 31 38.327536
+57 32 38.000000
+57 33 37.336309
+57 34 36.400549
+57 35 35.000000
+57 36 52.810984
+57 37 52.201533
+57 38 49.335586
+57 39 46.572524
+57 40 46.097722
+57 41 50.990195
+57 42 40.792156
+57 43 45.276926
+57 44 50.249378
+57 45 47.265209
+57 46 55.758407
+57 47 55.217751
+57 48 49.030603
+57 49 31.048349
+57 50 24.351591
+57 51 22.000000
+57 52 15.811388
+57 53 25.495098
+57 54 33.541020
+57 55 25.495098
+57 56 32.015621
+57 58 22.360680
+57 59 43.011626
+57 60 42.720019
+57 61 43.011626
+57 62 30.413813
+57 63 15.000000
+57 64 21.213203
+57 65 7.071068
+57 66 15.811388
+57 67 9.219544
+57 68 15.652476
+57 69 26.925824
+57 70 25.495098
+57 71 37.161808
+57 72 25.000000
+57 73 32.695565
+57 74 54.120237
+57 75 33.541020
+57 76 54.083269
+57 77 25.079872
+57 78 41.868843
+57 79 46.957428
+57 80 55.000000
+57 81 12.369317
+57 82 23.021729
+57 83 24.351591
+57 84 13.601471
+57 85 9.219544
+57 86 17.691806
+57 87 31.016125
+57 88 39.560081
+57 89 34.713110
+57 90 34.481879
+57 91 17.691806
+57 92 7.071068
+57 93 8.544004
+57 94 20.248457
+57 95 14.764823
+57 96 6.324555
+57 97 19.646883
+57 98 49.040799
+57 99 29.410882
+57 100 24.000000
+57 101 37.215588
+58 1 26.925824
+58 2 60.207973
+58 3 50.635956
+58 4 60.530984
+58 5 55.901699
+58 6 60.827625
+58 7 51.419841
+58 8 52.201533
+58 9 57.008771
+58 10 22.360680
+58 11 25.000000
+58 12 26.627054
+58 13 29.732137
+58 14 26.925824
+58 15 32.015621
+58 16 31.764760
+58 17 33.541020
+58 18 36.055513
+58 19 24.413111
+58 20 19.209373
+58 21 15.620499
+58 22 22.360680
+58 23 14.142136
+58 24 21.540659
+58 25 12.806248
+58 26 20.615528
+58 27 65.192024
+58 28 65.764732
+58 29 62.201286
+58 30 60.827625
+58 31 58.215118
+58 32 58.855756
+58 33 57.218878
+58 34 55.000000
+58 35 55.901699
+58 36 70.491134
+58 37 69.462220
+58 38 66.887966
+58 39 63.631753
+58 40 62.649820
+58 41 67.082039
+58 42 57.306195
+58 43 60.415230
+58 44 65.000000
+58 45 62.241465
+58 46 57.870545
+58 47 56.293872
+58 48 34.409301
+58 49 23.323808
+58 50 17.691806
+58 51 43.174066
+58 52 25.495098
+58 53 7.071068
+58 54 26.925824
+58 55 43.011626
+58 56 35.000000
+58 57 22.360680
+58 59 21.213203
+58 60 20.615528
+58 61 38.078866
+58 62 42.720019
+58 63 36.400549
+58 64 35.355339
+58 65 15.811388
+58 66 15.811388
+58 67 16.278821
+58 68 38.013156
+58 69 36.400549
+58 70 27.018512
+58 71 44.283180
+58 72 46.097722
+58 73 51.855569
+58 74 44.821870
+58 75 11.180340
+58 76 32.015621
+58 77 32.695565
+58 78 23.086793
+58 79 38.013156
+58 80 49.244289
+58 81 27.802878
+58 82 38.078866
+58 83 18.248288
+58 84 9.219544
+58 85 27.294688
+58 86 33.060551
+58 87 9.055385
+58 88 18.027756
+58 89 33.541020
+58 90 42.059482
+58 91 23.086793
+58 92 25.495098
+58 93 29.206164
+58 94 41.109610
+58 95 35.468296
+58 96 28.635642
+58 97 38.288379
+58 98 26.925824
+58 99 27.294688
+58 100 10.770330
+58 101 42.011903
+59 1 47.169906
+59 2 75.663730
+59 3 65.375837
+59 4 75.325958
+59 5 70.178344
+59 6 75.166482
+59 7 65.069194
+59 8 65.000000
+59 9 70.000000
+59 10 25.495098
+59 11 30.413813
+59 12 30.805844
+59 13 35.693137
+59 14 26.925824
+59 15 36.400549
+59 16 32.695565
+59 17 33.541020
+59 18 38.078866
+59 19 29.427878
+59 20 27.000000
+59 21 27.459060
+59 22 25.495098
+59 23 25.495098
+59 24 23.537205
+59 25 23.537205
+59 26 20.615528
+59 27 82.462113
+59 28 83.815273
+59 29 79.555012
+59 30 79.056942
+59 31 75.690158
+59 32 77.162167
+59 33 74.726167
+59 34 71.589105
+59 35 74.330344
+59 36 91.263355
+59 37 90.138782
+59 38 87.658428
+59 39 84.314886
+59 40 83.216585
+59 41 87.464278
+59 42 77.935871
+59 43 80.622577
+59 44 85.000000
+59 45 82.365041
+59 46 72.173402
+59 47 70.064256
+59 48 37.336309
+59 49 27.459060
+59 50 27.073973
+59 51 62.241465
+59 52 41.231056
+59 53 22.360680
+59 54 40.311289
+59 55 64.031242
+59 56 52.201533
+59 57 43.011626
+59 58 21.213203
+59 60 11.180340
+59 61 50.000000
+59 62 62.649820
+59 63 55.901699
+59 64 50.990195
+59 65 36.055513
+59 66 36.055513
+59 67 37.483330
+59 68 58.523500
+59 69 55.901699
+59 70 44.944410
+59 71 62.297673
+59 72 67.268120
+59 73 73.000000
+59 74 51.662365
+59 75 11.180340
+59 76 11.180340
+59 77 45.044423
+59 78 10.630146
+59 79 46.529560
+59 80 58.694122
+59 81 48.918299
+59 82 58.821765
+59 83 35.114100
+59 84 30.413813
+59 85 46.097722
+59 86 49.729267
+59 87 15.231546
+59 88 14.317821
+59 89 48.836462
+59 90 52.239832
+59 91 43.046487
+59 92 46.690470
+59 93 50.328918
+59 94 62.289646
+59 95 56.639209
+59 96 49.091751
+59 97 59.464275
+59 98 13.601471
+59 99 43.416587
+59 100 27.313001
+59 101 59.203040
+60 1 42.426407
+60 2 66.708320
+60 3 56.293872
+60 4 66.098411
+60 5 60.827625
+60 6 65.764732
+60 7 55.578773
+60 8 55.226805
+60 9 60.207973
+60 10 15.000000
+60 11 20.000000
+60 12 20.099751
+60 13 25.079872
+60 14 15.811388
+60 15 25.495098
+60 16 21.540659
+60 17 22.360680
+60 18 26.925824
+60 19 37.161808
+60 20 33.526109
+60 21 32.388269
+60 22 33.541020
+60 23 30.413813
+60 24 31.764760
+60 25 28.442925
+60 26 29.154759
+60 27 85.586214
+60 28 86.313383
+60 29 82.607506
+60 30 81.394103
+60 31 78.638413
+60 32 79.429214
+60 33 77.646635
+60 34 75.166482
+60 35 76.485293
+60 36 86.452299
+60 37 85.146932
+60 38 82.879430
+60 39 79.397733
+60 40 78.102497
+60 41 82.006097
+60 42 73.000000
+60 43 75.000000
+60 44 79.056942
+60 45 76.609399
+60 46 62.801274
+60 47 60.530984
+60 48 26.248809
+60 49 35.341194
+60 50 32.984845
+60 51 63.788714
+60 52 45.000000
+60 53 18.027756
+60 54 31.622777
+60 55 60.207973
+60 56 44.721360
+60 57 42.720019
+60 58 20.615528
+60 59 11.180340
+60 61 40.311289
+60 62 57.008771
+60 63 57.008771
+60 64 55.000000
+60 65 36.400549
+60 66 32.015621
+60 67 35.355339
+60 68 58.309519
+60 69 50.000000
+60 70 38.275318
+60 71 55.009090
+60 72 65.192024
+60 73 69.526973
+60 74 40.792156
+60 75 10.000000
+60 76 15.811388
+60 77 50.635956
+60 78 21.400935
+60 79 36.055513
+60 80 48.166378
+60 81 45.803930
+60 82 54.451814
+60 83 28.600699
+60 84 29.154759
+60 85 47.853944
+60 86 53.084838
+60 87 11.704700
+60 88 4.472136
+60 89 40.496913
+60 90 58.940648
+60 91 38.183766
+60 92 44.777226
+60 93 48.764741
+60 94 60.207973
+60 95 54.708317
+60 96 49.040799
+60 97 56.400355
+60 98 6.324555
+60 99 35.777088
+60 100 21.931712
+60 101 51.478151
+61 1 26.925824
+61 2 26.925824
+61 3 16.552945
+61 4 25.961510
+61 5 20.615528
+61 6 25.495098
+61 7 15.297059
+61 8 15.000000
+61 9 20.000000
+61 10 25.495098
+61 11 20.615528
+61 12 21.189620
+61 13 16.552945
+61 14 26.925824
+61 15 18.027756
+61 16 23.853721
+61 17 25.000000
+61 18 21.213203
+61 19 62.177166
+61 20 56.824291
+61 21 52.478567
+61 22 60.415230
+61 23 51.478151
+61 24 59.615434
+61 25 50.537115
+61 26 58.523500
+61 27 85.440037
+61 28 83.815273
+61 29 82.637764
+61 30 79.056942
+61 31 78.924014
+61 32 77.162167
+61 33 78.000000
+61 34 78.262379
+61 35 74.330344
+61 36 57.697487
+61 37 55.901699
+61 38 54.626001
+61 39 51.078371
+61 40 49.244289
+61 41 51.478151
+61 42 45.541190
+61 43 44.721360
+61 44 47.169906
+61 45 45.650849
+61 46 22.561028
+61 47 20.223748
+61 48 19.849433
+61 49 61.269895
+61 50 55.072679
+61 51 62.241465
+61 52 56.568542
+61 53 31.622777
+61 54 11.180340
+61 55 40.000000
+61 56 15.000000
+61 57 43.011626
+61 58 38.078866
+61 59 50.000000
+61 60 40.311289
+61 62 30.413813
+61 63 55.901699
+61 64 64.031242
+61 65 42.426407
+61 66 28.284271
+61 67 34.713110
+61 68 52.201533
+61 69 25.000000
+61 70 17.888544
+61 71 21.931712
+61 72 50.249378
+61 73 48.259714
+61 74 13.000000
+61 75 40.311289
+61 76 55.901699
+61 77 65.795137
+61 78 57.558666
+61 79 8.062258
+61 80 12.041595
+61 81 34.539832
+61 82 34.058773
+61 83 20.808652
+61 84 36.400549
+61 85 52.201533
+61 86 60.605280
+61 87 36.496575
+61 88 36.124784
+61 89 9.219544
+61 90 75.690158
+61 91 25.553865
+61 92 38.470768
+61 93 41.629317
+61 94 46.690470
+61 95 43.680659
+61 96 47.010637
+61 97 40.447497
+61 98 43.416587
+61 99 13.601471
+61 100 27.313001
+61 101 17.464249
+62 1 15.811388
+62 2 28.284271
+62 3 25.079872
+62 4 30.479501
+62 5 29.154759
+62 6 32.015621
+62 7 28.792360
+62 8 31.622777
+62 9 33.541020
+62 10 46.097722
+62 11 43.011626
+62 12 44.654227
+62 13 42.059482
+62 14 50.000000
+62 15 44.721360
+62 16 49.739320
+62 17 51.478151
+62 18 49.244289
+62 19 60.008333
+62 20 55.081757
+62 21 50.089919
+62 22 60.207973
+62 23 50.249378
+62 24 60.406953
+62 25 50.487622
+62 26 60.827625
+62 27 61.032778
+62 28 58.309519
+62 29 58.600341
+62 30 54.083269
+62 31 55.443665
+62 32 52.430907
+62 33 54.671748
+62 34 56.568542
+62 35 50.000000
+62 36 29.732137
+62 37 28.284271
+62 38 26.248809
+62 39 22.671568
+62 40 21.213203
+62 41 25.000000
+62 42 16.401219
+62 43 18.027756
+62 44 22.360680
+62 45 19.723083
+62 46 30.232433
+62 47 30.886890
+62 48 47.423623
+62 49 60.074953
+62 50 53.084838
+62 51 40.360872
+62 52 46.097722
+62 53 40.311289
+62 54 29.154759
+62 55 11.180340
+62 56 15.811388
+62 57 30.413813
+62 58 42.720019
+62 59 62.649820
+62 60 57.008771
+62 61 30.413813
+62 63 36.055513
+62 64 49.244289
+62 65 35.000000
+62 66 26.925824
+62 67 28.284271
+62 68 29.832868
+62 69 7.071068
+62 70 19.104973
+62 71 10.770330
+62 72 22.360680
+62 73 18.000000
+62 74 43.289722
+62 75 51.478151
+62 76 72.111026
+62 77 55.081757
+62 78 65.787537
+62 79 38.078866
+62 80 39.115214
+62 81 18.110770
+62 82 8.062258
+62 83 28.425341
+62 84 34.928498
+62 85 37.947332
+62 86 45.694639
+62 87 47.507894
+62 88 52.630789
+62 89 22.135944
+62 90 63.906181
+62 91 19.697716
+62 92 23.345235
+62 93 23.409400
+62 94 20.615528
+62 95 20.808652
+62 96 30.083218
+62 97 14.866069
+62 98 62.369865
+62 99 23.021729
+62 100 35.510562
+62 101 14.142136
+63 1 29.154759
+63 2 64.031242
+63 3 58.728187
+63 4 65.946948
+63 5 63.639610
+63 6 67.268120
+63 7 61.717096
+63 8 64.031242
+63 9 67.268120
+63 10 55.000000
+63 11 55.226805
+63 12 57.218878
+63 13 57.870545
+63 14 60.000000
+63 15 60.827625
+63 16 63.198101
+63 17 65.192024
+63 18 65.764732
+63 19 36.619667
+63 20 33.970576
+63 21 30.479501
+63 22 39.051248
+63 23 32.015621
+63 24 40.360872
+63 25 33.600595
+63 26 42.426407
+63 27 30.413813
+63 28 30.000000
+63 29 27.459060
+63 30 25.000000
+63 31 23.537205
+63 32 23.000000
+63 33 22.561028
+63 34 22.360680
+63 35 20.000000
+63 36 50.039984
+63 37 50.000000
+63 38 47.000000
+63 39 45.099889
+63 40 45.276926
+63 41 50.249378
+63 42 40.607881
+63 43 46.097722
+63 44 50.990195
+63 45 48.052055
+63 46 65.069194
+63 47 65.069194
+63 48 63.788714
+63 49 37.802116
+63 50 32.526912
+63 51 7.000000
+63 52 18.027756
+63 53 40.311289
+63 54 47.434165
+63 55 26.925824
+63 56 43.011626
+63 57 15.000000
+63 58 36.400549
+63 59 55.901699
+63 60 57.008771
+63 61 55.901699
+63 62 36.055513
+63 64 15.000000
+63 65 20.615528
+63 66 30.413813
+63 67 24.083189
+63 68 7.071068
+63 69 35.355339
+63 70 38.013156
+63 71 45.343136
+63 72 20.000000
+63 73 30.066593
+63 74 67.779053
+63 75 47.434165
+63 76 67.082039
+63 77 23.537205
+63 78 52.801515
+63 79 60.745370
+63 80 67.601775
+63 81 21.633308
+63 82 28.017851
+63 83 38.832976
+63 84 28.284271
+63 85 10.000000
+63 86 12.165525
+63 87 45.354162
+63 88 54.129474
+63 89 47.010637
+63 90 30.066593
+63 91 30.463092
+63 92 17.464249
+63 93 14.422205
+63 94 17.464249
+63 95 15.264338
+63 96 9.219544
+63 97 21.470911
+63 98 63.324561
+63 99 42.544095
+63 100 39.000000
+63 101 46.690470
+64 1 39.051248
+64 2 76.321688
+64 3 69.814039
+64 4 77.935871
+64 5 75.000000
+64 6 79.056942
+64 7 72.346389
+64 8 74.330344
+64 9 78.102497
+64 10 57.008771
+64 11 58.523500
+64 12 60.406953
+64 13 62.241465
+64 14 61.846584
+64 15 65.000000
+64 16 66.098411
+64 17 68.007353
+64 18 69.641941
+64 19 25.806976
+64 20 25.079872
+64 21 23.537205
+64 22 29.154759
+64 23 25.495098
+64 24 30.886890
+64 25 27.459060
+64 26 33.541020
+64 27 31.622777
+64 28 33.541020
+64 29 28.792360
+64 30 29.154759
+64 31 25.079872
+64 32 27.459060
+64 33 24.166092
+64 34 20.615528
+64 35 25.000000
+64 36 65.030762
+64 37 65.000000
+64 38 62.000000
+64 39 60.074953
+64 40 60.207973
+64 41 65.192024
+64 42 55.443665
+64 43 60.827625
+64 44 65.764732
+64 45 62.801274
+64 46 76.609399
+64 47 76.216796
+64 48 67.779053
+64 49 27.459060
+64 50 24.351591
+64 51 16.552945
+64 52 10.000000
+64 53 41.231056
+64 54 54.083269
+64 55 41.231056
+64 56 53.150729
+64 57 21.213203
+64 58 35.355339
+64 59 50.990195
+64 60 55.000000
+64 61 64.031242
+64 62 49.244289
+64 63 15.000000
+64 65 22.360680
+64 66 36.055513
+64 67 29.410882
+64 68 22.022716
+64 69 47.169906
+64 70 46.690470
+64 71 57.454330
+64 72 35.000000
+64 73 45.044423
+64 74 74.625733
+64 75 45.000000
+64 76 61.846584
+64 77 9.433981
+64 78 45.310043
+64 79 67.416615
+64 80 76.059187
+64 81 32.449961
+64 82 41.231056
+64 83 44.418465
+64 84 30.083218
+64 85 12.041595
+64 86 3.605551
+64 87 44.181444
+64 88 53.150729
+64 89 55.901699
+64 90 15.132746
+64 91 38.897301
+64 92 27.202941
+64 93 25.942244
+64 94 32.249031
+64 95 29.120440
+64 96 19.235384
+64 97 35.440090
+64 98 61.032778
+64 99 50.447993
+64 100 41.785165
+64 101 58.008620
+65 1 20.615528
+65 2 58.523500
+65 3 50.537115
+65 4 59.615434
+65 5 55.901699
+65 6 60.415230
+65 7 52.478567
+65 8 54.083269
+65 9 58.309519
+65 10 35.355339
+65 11 36.400549
+65 12 38.327536
+65 13 39.924930
+65 14 40.311289
+65 15 42.720019
+65 16 44.147480
+65 17 46.097722
+65 18 47.434165
+65 19 25.019992
+65 20 20.223748
+65 21 15.297059
+65 22 25.495098
+65 23 15.811388
+65 24 25.961510
+65 25 16.552945
+65 26 26.925824
+65 27 50.000000
+65 28 50.249378
+65 29 47.000000
+65 30 45.276926
+65 31 43.000000
+65 32 43.289722
+65 33 42.000000
+65 34 40.311289
+65 35 40.311289
+65 36 59.236813
+65 37 58.523500
+65 38 55.713553
+65 39 52.810984
+65 40 52.201533
+65 41 57.008771
+65 42 46.840154
+65 43 50.990195
+65 44 55.901699
+65 45 52.952809
+65 46 57.697487
+65 47 56.824291
+65 48 45.541190
+65 49 25.179357
+65 50 18.248288
+65 51 27.459060
+65 52 14.142136
+65 53 20.000000
+65 54 32.015621
+65 55 31.622777
+65 56 33.541020
+65 57 7.071068
+65 58 15.811388
+65 59 36.055513
+65 60 36.400549
+65 61 42.426407
+65 62 35.000000
+65 63 20.615528
+65 64 22.360680
+65 66 14.142136
+65 67 8.062258
+65 68 22.472205
+65 69 30.413813
+65 70 26.076810
+65 71 40.261644
+65 72 32.015621
+65 73 39.357337
+65 74 52.430907
+65 75 26.925824
+65 76 47.169906
+65 77 23.430749
+65 78 34.828150
+65 79 45.221676
+65 80 54.451814
+65 81 17.117243
+65 82 28.284271
+65 83 22.203603
+65 84 8.062258
+65 85 12.041595
+65 86 19.313208
+65 87 24.738634
+65 88 33.541020
+65 89 35.000000
+65 90 33.301652
+65 91 18.788294
+65 92 12.649111
+65 93 15.264338
+65 94 27.202941
+65 95 21.633308
+65 96 13.038405
+65 97 26.000000
+65 98 42.720019
+65 99 29.068884
+65 100 19.646883
+65 101 39.560081
+66 1 11.180340
+66 2 46.097722
+66 3 37.336309
+66 4 46.840154
+66 5 42.720019
+66 6 47.434165
+66 7 38.910153
+66 8 40.311289
+66 9 44.721360
+66 10 25.495098
+66 11 25.000000
+66 12 27.000000
+66 13 27.459060
+66 14 30.413813
+66 15 30.413813
+66 16 33.000000
+66 17 35.000000
+66 18 35.355339
+66 19 36.138622
+66 20 30.805844
+66 21 25.961510
+66 22 35.355339
+66 23 25.495098
+66 24 35.128336
+66 25 25.179357
+66 26 35.000000
+66 27 60.827625
+66 28 60.207973
+66 29 57.870545
+66 30 55.226805
+66 31 53.935146
+66 32 53.235327
+66 33 52.952809
+66 34 52.201533
+66 35 50.249378
+66 36 55.217751
+66 37 54.083269
+66 38 51.613952
+66 39 48.259714
+66 40 47.169906
+66 41 51.478151
+66 42 41.880783
+66 43 44.721360
+66 44 49.244289
+66 45 46.518813
+66 46 44.598206
+66 47 43.462628
+66 48 33.376639
+66 49 35.693137
+66 50 28.861739
+66 51 37.336309
+66 52 28.284271
+66 53 14.142136
+66 54 18.027756
+66 55 28.284271
+66 56 20.615528
+66 57 15.811388
+66 58 15.811388
+66 59 36.055513
+66 60 32.015621
+66 61 28.284271
+66 62 26.925824
+66 63 30.413813
+66 64 36.055513
+66 65 14.142136
+66 67 6.708204
+66 68 29.068884
+66 69 20.615528
+66 70 12.649111
+66 71 29.000000
+66 72 33.541020
+66 73 37.536649
+66 74 38.587563
+66 75 25.000000
+66 76 46.097722
+66 77 37.536649
+66 78 38.897301
+66 79 31.384710
+66 80 40.311289
+66 81 13.892444
+66 82 22.803509
+66 83 8.544004
+66 84 9.219544
+66 85 24.596748
+66 86 32.756679
+66 87 21.260292
+66 88 28.017851
+66 89 21.095023
+66 90 47.423623
+66 91 7.280110
+66 92 14.142136
+66 93 18.248288
+66 94 28.635642
+66 95 23.409400
+66 96 21.213203
+66 97 24.413111
+66 98 38.013156
+66 99 15.000000
+66 100 10.295630
+66 101 27.294688
+67 1 13.038405
+67 2 50.596443
+67 3 42.485292
+67 4 51.623638
+67 5 47.853944
+67 6 52.392748
+67 7 44.418465
+67 8 46.043458
+67 9 50.249378
+67 10 31.064449
+67 11 31.144823
+67 12 33.136083
+67 13 33.955854
+67 14 36.055513
+67 15 36.878178
+67 16 39.115214
+67 17 41.109610
+67 18 41.773197
+67 19 32.140317
+67 20 27.018512
+67 21 22.022716
+67 22 32.015621
+67 23 22.022716
+67 24 32.140317
+67 25 22.203603
+67 26 32.557641
+67 27 54.451814
+67 28 54.037024
+67 29 51.478151
+67 30 49.040799
+67 31 47.518417
+67 32 47.042534
+67 33 46.529560
+67 34 45.607017
+67 35 44.045431
+67 36 54.589376
+67 37 53.665631
+67 38 51.000000
+67 39 47.853944
+67 40 47.010637
+67 41 51.623638
+67 42 41.629317
+67 43 45.221676
+67 44 50.000000
+67 45 47.127487
+67 46 49.658836
+67 47 48.764741
+67 48 39.812058
+67 49 32.015621
+67 50 25.019992
+67 51 31.064449
+67 52 22.022716
+67 53 17.464249
+67 54 24.698178
+67 55 26.925824
+67 56 25.495098
+67 57 9.219544
+67 58 16.278821
+67 59 37.483330
+67 60 35.355339
+67 61 34.713110
+67 62 28.284271
+67 63 24.083189
+67 64 29.410882
+67 65 8.062258
+67 66 6.708204
+67 68 23.537205
+67 69 23.021729
+67 70 18.027756
+67 71 32.557641
+67 72 30.000000
+67 73 35.608988
+67 74 45.276926
+67 75 27.018512
+67 76 48.166378
+67 77 31.400637
+67 78 38.470768
+67 79 38.078866
+67 80 46.754679
+67 81 11.661904
+67 82 22.472205
+67 83 15.231546
+67 84 7.211103
+67 85 17.888544
+67 86 26.076810
+67 87 23.853721
+67 88 31.780497
+67 89 27.018512
+67 90 41.231056
+67 91 10.770330
+67 92 9.433981
+67 93 13.416408
+67 94 25.000000
+67 95 19.416488
+67 96 15.000000
+67 97 22.022716
+67 98 41.593269
+67 99 21.213203
+67 100 15.132746
+67 101 31.622777
+68 1 25.298221
+68 2 58.051701
+68 3 53.413481
+68 4 60.108236
+68 5 58.137767
+68 6 61.522354
+68 7 56.612719
+68 8 59.076222
+68 9 62.008064
+68 10 54.451814
+68 11 54.037024
+68 12 56.035703
+68 13 56.080300
+68 14 59.413803
+68 15 59.076222
+68 16 62.032250
+68 17 64.031242
+68 18 64.070274
+68 19 42.059482
+68 20 38.832976
+68 21 34.828150
+68 22 44.102154
+68 23 36.124784
+68 24 45.221676
+68 25 37.483330
+68 26 47.010637
+68 27 33.241540
+68 28 31.780497
+68 29 30.463092
+68 30 26.925824
+68 31 26.832816
+68 32 25.000000
+68 33 25.942244
+68 34 27.018512
+68 35 22.135944
+68 36 43.104524
+68 37 43.011626
+68 38 40.012498
+68 39 38.052595
+68 40 38.209946
+68 41 43.185646
+68 42 33.541020
+68 43 39.051248
+68 44 43.931765
+68 45 41.000000
+68 46 59.464275
+68 47 59.665736
+68 48 62.072538
+68 49 43.046487
+68 50 37.202150
+68 51 10.630146
+68 52 23.769729
+68 53 40.804412
+68 54 44.721360
+68 55 20.124612
+68 56 38.470768
+68 57 15.652476
+68 58 38.013156
+68 59 58.523500
+68 60 58.309519
+68 61 52.201533
+68 62 29.832868
+68 63 7.071068
+68 64 22.022716
+68 65 22.472205
+68 66 29.068884
+68 67 23.537205
+68 69 30.000000
+68 70 34.481879
+68 71 39.623226
+68 72 13.038405
+68 73 23.021729
+68 74 64.560050
+68 75 49.193496
+68 76 69.641941
+68 77 30.265492
+68 78 56.586217
+68 79 57.723479
+68 80 63.560994
+68 81 17.720045
+68 82 21.931712
+68 83 37.013511
+68 84 29.154759
+68 85 14.764823
+68 86 19.026298
+68 87 46.615448
+68 88 55.027266
+68 89 43.081318
+68 90 37.121422
+68 91 27.459060
+68 92 15.000000
+68 93 11.045361
+68 94 10.440307
+68 95 9.219544
+68 96 9.433981
+68 97 15.000000
+68 98 64.621978
+68 99 39.293765
+68 100 38.639358
+68 101 41.400483
+69 1 10.000000
+69 2 29.154759
+69 3 23.430749
+69 4 30.805844
+69 5 28.284271
+69 6 32.015621
+69 7 26.627054
+69 8 29.154759
+69 9 32.015621
+69 10 39.051248
+69 11 36.055513
+69 12 37.735925
+69 13 35.341194
+69 14 43.011626
+69 15 38.078866
+69 16 42.941821
+69 17 44.721360
+69 18 42.720019
+69 19 55.145263
+69 20 50.039984
+69 21 45.044423
+69 22 55.000000
+69 23 45.000000
+69 24 55.036352
+69 25 45.044423
+69 26 55.226805
+69 27 62.649820
+69 28 60.415230
+69 29 60.033324
+69 30 55.901699
+69 31 56.603887
+69 32 54.120237
+69 33 55.758407
+69 34 57.008771
+69 35 51.478151
+69 36 36.796739
+69 37 35.355339
+69 38 33.301652
+69 39 29.732137
+69 40 28.284271
+69 41 32.015621
+69 42 23.430749
+69 43 25.000000
+69 44 29.154759
+69 45 26.627054
+69 46 29.732137
+69 47 29.732137
+69 48 40.853396
+69 49 55.036352
+69 50 48.041649
+69 51 40.607881
+69 52 42.720019
+69 53 33.541020
+69 54 22.360680
+69 55 15.000000
+69 56 10.000000
+69 57 26.925824
+69 58 36.400549
+69 59 55.901699
+69 60 50.000000
+69 61 25.000000
+69 62 7.071068
+69 63 35.355339
+69 64 47.169906
+69 65 30.413813
+69 66 20.615528
+69 67 23.021729
+69 68 30.000000
+69 70 12.041595
+69 71 10.295630
+69 72 25.495098
+69 73 23.537205
+69 74 38.000000
+69 75 44.721360
+69 76 65.192024
+69 77 52.000000
+69 78 59.481089
+69 79 32.249031
+69 80 34.928498
+69 81 14.764823
+69 82 9.219544
+69 83 21.400935
+69 84 29.154759
+69 85 35.355339
+69 86 43.566042
+69 87 40.706265
+69 88 45.607017
+69 89 16.124515
+69 90 61.269895
+69 91 13.341664
+69 92 20.124612
+69 93 21.400935
+69 94 22.472205
+69 95 20.808652
+69 96 28.017851
+69 97 16.155494
+69 98 55.317267
+69 99 16.124515
+69 100 28.653098
+69 101 11.401754
+70 1 9.219544
+70 2 33.541020
+70 3 24.698178
+70 4 34.205263
+70 5 30.083218
+70 6 34.785054
+70 7 26.419690
+70 8 28.017851
+70 9 32.249031
+70 10 27.018512
+70 11 24.186773
+70 12 25.942244
+70 13 24.041631
+70 14 31.064449
+70 15 26.925824
+70 16 31.384710
+70 17 33.241540
+70 18 31.780497
+70 19 48.764741
+70 20 43.416587
+70 21 38.600518
+70 22 47.853944
+70 23 38.078866
+70 24 47.518417
+70 25 37.656341
+70 26 47.169906
+70 27 67.675697
+70 28 66.219333
+70 29 64.845971
+70 30 61.400326
+70 31 61.098281
+70 32 59.481089
+70 33 60.166436
+70 34 60.373835
+70 35 56.612719
+70 36 48.836462
+70 37 47.381431
+70 38 45.343136
+70 39 41.773197
+70 40 40.311289
+70 41 43.931765
+70 42 35.468296
+70 43 36.878178
+70 44 40.804412
+70 45 38.418745
+70 46 31.953091
+70 47 30.870698
+70 48 29.832868
+70 49 48.270074
+70 50 41.484937
+70 51 44.384682
+70 52 40.000000
+70 53 22.803509
+70 54 11.180340
+70 55 25.298221
+70 56 8.062258
+70 57 25.495098
+70 58 27.018512
+70 59 44.944410
+70 60 38.275318
+70 61 17.888544
+70 62 19.104973
+70 63 38.013156
+70 64 46.690470
+70 65 26.076810
+70 66 12.649111
+70 67 18.027756
+70 68 34.481879
+70 69 12.041595
+70 71 17.464249
+70 72 34.132096
+70 73 34.539832
+70 74 30.083218
+70 75 33.837849
+70 76 53.712196
+70 77 49.406477
+70 78 49.648766
+70 79 23.345235
+70 80 29.681644
+70 81 16.763055
+70 82 18.973666
+70 83 9.848858
+70 84 21.840330
+70 85 34.713110
+70 86 43.185646
+70 87 29.732137
+70 88 33.837849
+70 89 9.219544
+70 90 59.203040
+70 91 7.810250
+70 92 20.591260
+70 93 23.769729
+70 94 30.000000
+70 95 26.305893
+70 96 29.154759
+70 97 24.083189
+70 98 43.416587
+70 99 5.000000
+70 100 17.720045
+70 101 15.000000
+71 1 19.646883
+71 2 18.867962
+71 3 14.317821
+71 4 20.615528
+71 5 18.601075
+71 6 21.931712
+71 7 18.027756
+71 8 20.880613
+71 9 22.825424
+71 10 42.201896
+71 11 38.288379
+71 12 39.623226
+71 13 36.124784
+71 14 45.343136
+71 15 38.418745
+71 16 43.931765
+71 17 45.453273
+71 18 42.438190
+71 19 64.629715
+71 20 59.413803
+71 21 54.451814
+71 22 64.195015
+71 23 54.230987
+71 24 64.070274
+71 25 54.083269
+71 26 64.000000
+71 27 71.561163
+71 28 68.963759
+71 29 69.065187
+71 30 64.660653
+71 31 65.802736
+71 32 62.968246
+71 33 65.000000
+71 34 66.603303
+71 35 60.464866
+71 36 35.777088
+71 37 34.000000
+71 38 32.695565
+71 39 29.154759
+71 40 27.313001
+71 41 29.681644
+71 42 23.769729
+71 43 22.825424
+71 44 25.612497
+71 45 23.853721
+71 46 19.849433
+71 47 20.248457
+71 48 40.804412
+71 49 64.381674
+71 50 57.428216
+71 51 50.249378
+71 52 52.924474
+71 53 40.261644
+71 54 24.207437
+71 55 21.931712
+71 56 10.295630
+71 57 37.161808
+71 58 44.283180
+71 59 62.297673
+71 60 55.009090
+71 61 21.931712
+71 62 10.770330
+71 63 45.343136
+71 64 57.454330
+71 65 40.261644
+71 66 29.000000
+71 67 32.557641
+71 68 39.623226
+71 69 10.295630
+71 70 17.464249
+71 72 33.105891
+71 73 28.284271
+71 74 34.205263
+71 75 51.244512
+71 76 70.682388
+71 77 62.241465
+71 78 67.082039
+71 79 29.966648
+71 80 29.017236
+71 81 25.059928
+71 82 17.804494
+71 83 27.202941
+71 84 38.052595
+71 85 45.650849
+71 86 53.851648
+71 87 47.127487
+71 88 50.537115
+71 89 15.556349
+71 90 71.554175
+71 91 22.090722
+71 92 30.413813
+71 93 31.622777
+71 94 31.064449
+71 95 30.413813
+71 96 38.275318
+71 97 25.000000
+71 98 59.682493
+71 99 19.235384
+71 100 35.171011
+71 101 4.472136
+72 1 25.495098
+72 2 50.000000
+72 3 47.423623
+72 4 52.430907
+72 5 51.478151
+72 6 54.083269
+72 7 51.078371
+72 8 53.851648
+72 9 55.901699
+72 10 58.523500
+72 11 57.008771
+72 12 58.940648
+72 13 57.870545
+72 14 63.245553
+72 15 60.827625
+72 16 64.761099
+72 17 66.708320
+72 18 65.764732
+72 19 54.230987
+72 20 50.537115
+72 21 46.141088
+72 22 55.901699
+72 23 47.169906
+72 24 56.824291
+72 25 48.259714
+72 26 58.309519
+72 27 39.051248
+72 28 36.055513
+72 29 36.796739
+72 30 32.015621
+72 31 33.970576
+72 32 30.479501
+72 33 33.301652
+72 34 36.055513
+72 35 28.284271
+72 36 30.066593
+72 37 30.000000
+72 38 27.000000
+72 39 25.179357
+72 40 25.495098
+72 41 30.413813
+72 42 21.189620
+72 43 26.925824
+72 44 31.622777
+72 45 28.792360
+72 46 52.478567
+72 47 53.235327
+72 48 63.788714
+72 49 55.036352
+72 50 48.764741
+72 51 21.189620
+72 52 36.400549
+72 53 47.169906
+72 54 45.276926
+72 55 11.180340
+72 56 35.355339
+72 57 25.000000
+72 58 46.097722
+72 59 67.268120
+72 60 65.192024
+72 61 50.249378
+72 62 22.360680
+72 63 20.000000
+72 64 35.000000
+72 65 32.015621
+72 66 33.541020
+72 67 30.000000
+72 68 13.038405
+72 69 25.495098
+72 70 34.132096
+72 71 33.105891
+72 73 10.198039
+72 74 63.198101
+72 75 57.008771
+72 76 78.102497
+72 77 43.289722
+72 78 66.843100
+72 79 57.008771
+72 80 60.415230
+72 81 19.697716
+72 82 16.278821
+72 83 39.849718
+72 84 36.878178
+72 85 27.202941
+72 86 32.062439
+72 87 53.823787
+72 88 61.400326
+72 89 41.109610
+72 90 50.039984
+72 91 29.120440
+72 92 20.615528
+72 93 16.970563
+72 94 5.000000
+72 95 10.630146
+72 96 20.124612
+72 97 10.049876
+72 98 71.344236
+72 99 39.115214
+72 100 43.829214
+72 101 36.055513
+73 1 27.459060
+73 2 42.941821
+73 3 42.201896
+73 4 45.617979
+73 5 45.541190
+73 6 47.423623
+73 7 46.097722
+73 8 49.030603
+73 9 50.289164
+73 10 60.901560
+73 11 58.600341
+73 12 60.415230
+73 13 58.523500
+73 14 65.299311
+73 15 61.351447
+73 16 65.924199
+73 17 67.779053
+73 18 66.098411
+73 19 62.936476
+73 20 58.872744
+73 21 54.230987
+73 22 64.257295
+73 23 55.036352
+73 24 65.000000
+73 25 55.901699
+73 26 66.211781
+73 27 47.423623
+73 28 43.863424
+73 29 45.453273
+73 30 40.360872
+73 31 43.011626
+73 32 39.051248
+73 33 42.438190
+73 34 45.650849
+73 35 37.202150
+73 36 20.396078
+73 37 20.099751
+73 38 17.117243
+73 39 15.033296
+73 40 15.297059
+73 41 20.223748
+73 42 11.180340
+73 43 17.000000
+73 44 21.540659
+73 45 18.788294
+73 46 46.238512
+73 47 47.434165
+73 48 64.195015
+73 49 63.568860
+73 50 57.008771
+73 51 31.320920
+73 52 45.705580
+73 53 51.662365
+73 54 45.541190
+73 55 9.433981
+73 56 33.376639
+73 57 32.695565
+73 58 51.855569
+73 59 73.000000
+73 60 69.526973
+73 61 48.259714
+73 62 18.000000
+73 63 30.066593
+73 64 45.044423
+73 65 39.357337
+73 66 37.536649
+73 67 35.608988
+73 68 23.021729
+73 69 23.537205
+73 70 34.539832
+73 71 28.284271
+73 72 10.198039
+73 74 61.204575
+73 75 62.241465
+73 76 83.450584
+73 77 53.084838
+73 78 73.783467
+73 79 55.731499
+73 80 57.078893
+73 81 24.083189
+73 82 15.652476
+73 83 42.190046
+73 84 42.801869
+73 85 36.496575
+73 86 42.000000
+73 87 58.694122
+73 88 65.436993
+73 89 39.623226
+73 90 60.133186
+73 91 31.622777
+73 92 26.925824
+73 93 24.166092
+73 94 13.152946
+73 95 18.027756
+73 96 28.861739
+73 97 13.601471
+73 98 75.432089
+73 99 39.217343
+73 100 47.634021
+73 101 32.062439
+74 1 39.293765
+74 2 33.970576
+74 3 25.000000
+74 4 32.015621
+74 5 26.907248
+74 6 30.805844
+74 7 21.931712
+74 8 19.849433
+74 9 23.853721
+74 10 26.248809
+74 11 21.540659
+74 12 20.880613
+74 13 16.155494
+74 14 25.179357
+74 15 15.297059
+74 16 20.000000
+74 17 20.099751
+74 18 15.132746
+74 19 69.202601
+74 20 64.031242
+74 21 60.207973
+74 22 66.850580
+74 23 58.898217
+74 24 65.734314
+74 25 57.628118
+74 26 64.140471
+74 27 97.718985
+74 28 96.301610
+74 29 94.868330
+74 30 91.482239
+74 31 91.082380
+74 32 89.560036
+74 33 90.138782
+74 34 90.077744
+74 35 86.683332
+74 36 69.641941
+74 37 67.779053
+74 38 66.730802
+74 39 63.245553
+74 40 61.351447
+74 41 63.158531
+74 42 57.974132
+74 43 56.648036
+74 44 58.600341
+74 45 57.384667
+74 46 28.425341
+74 47 25.612497
+74 48 15.000000
+74 49 68.007353
+74 50 62.481997
+74 51 74.330344
+74 52 66.400301
+74 53 37.802116
+74 54 20.591260
+74 55 53.000000
+74 56 28.000000
+74 57 54.120237
+74 58 44.821870
+74 59 51.662365
+74 60 40.792156
+74 61 13.000000
+74 62 43.289722
+74 63 67.779053
+74 64 74.625733
+74 65 52.430907
+74 66 38.587563
+74 67 45.276926
+74 68 64.560050
+74 69 38.000000
+74 70 30.083218
+74 71 34.205263
+74 72 63.198101
+74 73 61.204575
+74 75 43.863424
+74 76 55.081757
+74 77 75.286121
+74 78 60.745370
+74 79 7.211103
+74 80 8.944272
+74 81 46.840154
+74 82 47.042534
+74 83 30.232433
+74 84 45.453273
+74 85 63.134776
+74 86 71.344236
+74 87 40.706265
+74 88 37.363083
+74 89 22.090722
+74 90 85.146932
+74 91 37.336309
+74 92 50.328918
+74 93 53.758720
+74 94 59.539903
+74 95 56.293872
+74 96 58.694122
+74 97 53.338541
+74 98 42.047592
+74 99 25.298221
+74 100 34.655447
+74 101 29.832868
+75 1 36.055513
+75 2 65.192024
+75 3 55.036352
+75 4 65.030762
+75 5 60.000000
+75 6 65.000000
+75 7 55.036352
+75 8 55.226805
+75 9 60.207973
+75 10 18.027756
+75 11 22.360680
+75 12 23.323808
+75 13 27.730849
+75 14 21.213203
+75 15 29.154759
+75 16 26.907248
+75 17 28.284271
+75 18 32.015621
+75 19 28.301943
+75 20 24.166092
+75 21 22.561028
+75 22 25.000000
+75 23 20.615528
+75 24 23.430749
+75 25 18.681542
+75 26 21.213203
+75 27 75.663730
+75 28 76.485293
+75 29 72.691127
+75 30 71.589105
+75 31 68.731361
+75 32 69.634761
+75 33 67.742158
+75 34 65.192024
+75 35 66.708320
+75 36 80.212219
+75 37 79.056942
+75 38 76.609399
+75 39 73.239334
+75 40 72.111026
+75 41 76.321688
+75 42 66.850580
+75 43 69.462220
+75 44 73.824115
+75 45 71.196910
+75 46 62.000000
+75 47 60.033324
+75 48 30.805844
+75 49 26.627054
+75 50 23.409400
+75 51 54.120237
+75 52 35.000000
+75 53 11.180340
+75 54 30.000000
+75 55 53.150729
+75 56 41.231056
+75 57 33.541020
+75 58 11.180340
+75 59 11.180340
+75 60 10.000000
+75 61 40.311289
+75 62 51.478151
+75 63 47.434165
+75 64 45.000000
+75 65 26.925824
+75 66 25.000000
+75 67 27.018512
+75 68 49.193496
+75 69 44.721360
+75 70 33.837849
+75 71 51.244512
+75 72 57.008771
+75 73 62.241465
+75 74 43.863424
+75 76 21.213203
+75 77 40.792156
+75 78 17.262677
+75 79 37.947332
+75 80 50.000000
+75 81 38.183766
+75 82 47.801674
+75 83 24.041631
+75 84 20.248457
+75 85 38.078866
+75 86 43.104524
+75 87 4.123106
+75 88 8.944272
+75 89 38.209946
+75 90 49.335586
+75 91 31.906112
+75 92 36.400549
+75 93 40.224371
+75 94 52.009614
+75 95 46.400431
+75 96 39.812058
+75 97 48.795492
+75 98 16.124515
+75 99 32.557641
+75 100 16.155494
+75 101 48.270074
+76 1 57.008771
+76 2 82.462113
+76 3 72.034714
+76 4 81.786307
+76 5 76.485293
+76 6 81.394103
+76 7 71.196910
+76 8 70.710678
+76 9 75.663730
+76 10 30.413813
+76 11 35.355339
+76 12 35.128336
+76 13 40.112342
+76 14 30.000000
+76 15 40.000000
+76 16 35.128336
+76 17 35.355339
+76 18 40.311289
+76 19 39.000000
+76 20 37.336309
+76 21 38.327536
+76 22 35.000000
+76 23 36.400549
+76 24 33.000000
+76 25 34.481879
+76 26 30.000000
+76 27 93.407708
+76 28 94.868330
+76 29 90.520716
+76 30 90.138782
+76 31 86.683332
+76 32 88.255311
+76 33 85.726309
+76 34 82.462113
+76 35 85.440037
+76 36 101.212647
+76 37 100.000000
+76 38 97.616597
+76 39 94.201911
+76 40 93.005376
+76 41 97.082439
+76 42 87.800911
+76 43 90.138782
+76 44 94.339811
+76 45 91.809586
+76 46 78.447435
+76 47 76.118329
+76 48 40.112342
+76 49 37.000000
+76 50 37.656341
+76 51 73.409809
+76 52 52.201533
+76 53 32.015621
+76 54 47.434165
+76 55 74.330344
+76 56 60.415230
+76 57 54.083269
+76 58 32.015621
+76 59 11.180340
+76 60 15.811388
+76 61 55.901699
+76 62 72.111026
+76 63 67.082039
+76 64 61.846584
+76 65 47.169906
+76 66 46.097722
+76 67 48.166378
+76 68 69.641941
+76 69 65.192024
+76 70 53.712196
+76 71 70.682388
+76 72 78.102497
+76 73 83.450584
+76 74 55.081757
+76 75 21.213203
+76 77 55.443665
+76 78 18.110770
+76 79 51.088159
+76 80 63.007936
+76 81 59.396970
+76 82 68.883960
+76 83 43.908997
+76 84 41.231056
+76 85 57.271284
+76 86 60.728906
+76 87 24.839485
+76 88 20.248457
+76 89 56.302753
+76 90 62.000000
+76 91 52.801515
+76 92 57.489129
+76 93 61.220911
+76 94 73.109507
+76 95 67.475922
+76 96 60.207973
+76 97 70.007142
+76 98 13.038405
+76 99 51.478151
+76 100 36.619667
+76 101 67.230945
+77 1 42.941821
+77 2 80.956779
+77 3 73.573093
+77 4 82.298238
+77 5 78.892332
+77 6 83.240615
+77 7 75.716577
+77 8 77.420927
+77 9 81.541401
+77 10 55.036352
+77 11 57.306195
+77 12 59.059292
+77 13 61.587336
+77 14 59.615434
+77 15 64.140471
+77 16 64.404969
+77 17 66.211781
+77 18 68.476273
+77 19 17.464249
+77 20 18.110770
+77 21 18.248288
+77 22 21.189620
+77 23 20.223748
+77 24 23.086793
+77 25 22.203603
+77 26 25.961510
+77 27 39.357337
+77 28 41.880783
+77 29 36.715120
+77 30 37.802116
+77 31 33.286634
+77 32 36.235342
+77 33 32.449961
+77 34 28.178006
+77 35 33.970576
+77 36 73.334848
+77 37 73.171033
+77 38 70.178344
+77 39 68.029405
+77 40 68.000000
+77 41 73.000000
+77 42 63.031738
+77 43 68.183576
+77 44 73.171033
+77 45 70.178344
+77 46 80.622577
+77 47 79.924965
+77 48 66.730802
+77 49 19.313208
+77 50 18.000000
+77 51 25.942244
+77 52 9.433981
+77 53 39.357337
+77 54 55.172457
+77 55 48.259714
+77 56 56.603887
+77 57 25.079872
+77 58 32.695565
+77 59 45.044423
+77 60 50.635956
+77 61 65.795137
+77 62 55.081757
+77 63 23.537205
+77 64 9.433981
+77 65 23.430749
+77 66 37.536649
+77 67 31.400637
+77 68 30.265492
+77 69 52.000000
+77 70 49.406477
+77 71 62.241465
+77 72 43.289722
+77 73 53.084838
+77 74 75.286121
+77 75 40.792156
+77 76 55.443665
+77 78 38.078866
+77 79 68.117545
+77 80 77.794601
+77 81 37.336309
+77 82 47.296934
+77 83 45.276926
+77 84 29.832868
+77 85 17.262677
+77 86 11.401754
+77 87 40.804412
+77 88 49.477268
+77 89 58.412327
+77 90 9.899495
+77 91 41.880783
+77 92 31.953091
+77 93 31.780497
+77 94 40.012498
+77 95 36.124784
+77 96 25.317978
+77 97 42.296572
+77 98 56.320511
+77 99 52.497619
+77 100 41.048752
+77 101 62.177166
+78 1 49.979996
+78 2 82.024387
+78 3 72.006944
+78 4 82.006097
+78 5 77.058419
+78 6 82.054860
+78 7 72.173402
+78 8 72.443081
+78 9 77.414469
+78 10 34.539832
+78 11 39.217343
+78 12 39.924930
+78 13 44.598206
+78 14 36.715120
+78 15 45.694639
+78 16 42.544095
+78 17 43.566042
+78 18 47.885280
+78 19 21.095023
+78 20 20.248457
+78 21 22.472205
+78 22 17.117243
+78 23 20.808652
+78 24 15.132746
+78 25 19.209373
+78 26 12.165525
+78 27 76.896034
+78 28 78.790862
+78 29 74.094534
+78 30 74.249579
+78 31 70.384657
+78 32 72.449983
+78 33 69.462220
+78 34 65.787537
+78 35 69.771054
+78 36 93.059121
+78 37 92.130342
+78 38 89.470666
+78 39 86.313383
+78 40 85.428333
+78 41 89.961103
+78 42 80.056230
+78 43 83.384651
+78 44 88.022724
+78 45 85.234969
+78 46 79.056942
+78 47 77.162167
+78 48 46.957428
+78 49 19.104973
+78 50 21.023796
+78 51 58.523500
+78 52 36.235342
+78 53 27.073973
+78 54 47.095647
+78 55 65.368188
+78 56 57.428216
+78 57 41.868843
+78 58 23.086793
+78 59 10.630146
+78 60 21.400935
+78 61 57.558666
+78 62 65.787537
+78 63 52.801515
+78 64 45.310043
+78 65 34.828150
+78 66 38.897301
+78 67 38.470768
+78 68 56.586217
+78 69 59.481089
+78 70 49.648766
+78 71 67.082039
+78 72 66.843100
+78 73 73.783467
+78 74 60.745370
+78 75 17.262677
+78 76 18.110770
+78 77 38.078866
+78 79 55.081757
+78 80 67.186308
+78 81 50.119856
+78 82 60.835845
+78 83 40.199502
+78 84 31.304952
+78 85 42.801869
+78 86 44.721360
+78 87 21.095023
+78 88 23.706539
+78 89 55.009090
+78 90 44.045431
+78 91 46.173586
+78 92 46.872167
+78 93 50.000000
+78 94 62.008064
+78 95 56.400355
+78 96 47.381431
+78 97 60.207973
+78 98 24.207437
+78 99 49.091751
+78 100 32.140317
+78 101 64.498062
+79 1 32.557641
+79 2 33.615473
+79 3 23.600847
+79 4 32.202484
+79 5 26.832816
+79 6 31.384710
+79 7 21.470911
+79 8 20.248457
+79 9 25.000000
+79 10 21.095023
+79 11 16.124515
+79 12 16.000000
+79 13 11.000000
+79 14 21.213203
+79 15 11.401754
+79 16 17.088007
+79 17 17.888544
+79 18 13.601471
+79 19 62.425956
+79 20 57.201399
+79 21 53.263496
+79 22 60.207973
+79 23 52.009614
+79 24 59.169249
+79 25 50.803543
+79 26 57.706152
+79 27 90.801982
+79 28 89.498603
+79 29 87.931792
+79 30 84.646323
+79 31 84.118963
+79 32 82.710338
+79 33 83.168504
+79 34 83.006024
+79 35 79.812280
+79 36 65.741920
+79 37 63.953108
+79 38 62.649820
+79 39 59.093147
+79 40 57.271284
+79 41 59.539903
+79 42 53.488316
+79 43 52.773099
+79 44 55.226805
+79 45 53.712196
+79 46 28.635642
+79 47 26.000000
+79 48 12.529964
+79 49 61.294372
+79 50 55.605755
+79 51 67.357256
+79 52 59.203040
+79 53 31.064449
+79 54 13.416408
+79 55 47.169906
+79 56 22.360680
+79 57 46.957428
+79 58 38.013156
+79 59 46.529560
+79 60 36.055513
+79 61 8.062258
+79 62 38.078866
+79 63 60.745370
+79 64 67.416615
+79 65 45.221676
+79 66 31.384710
+79 67 38.078866
+79 68 57.723479
+79 69 32.249031
+79 70 23.345235
+79 71 29.966648
+79 72 57.008771
+79 73 55.731499
+79 74 7.211103
+79 75 37.947332
+79 76 51.088159
+79 77 68.117545
+79 78 55.081757
+79 80 12.165525
+79 81 40.024992
+79 82 41.048752
+79 83 23.021729
+79 84 38.288379
+79 85 55.946403
+79 86 64.140471
+79 87 34.539832
+79 88 32.249031
+79 89 16.124515
+79 90 77.987178
+79 91 30.364453
+79 92 43.324358
+79 93 46.840154
+79 94 53.150729
+79 95 49.648766
+79 96 51.623638
+79 97 47.042534
+79 98 38.209946
+79 99 18.439089
+79 100 27.658633
+79 101 25.495098
+80 1 38.470768
+80 2 25.495098
+80 3 17.464249
+80 4 23.345235
+80 5 18.439089
+80 6 22.022716
+80 7 13.892444
+80 8 11.401754
+80 9 15.000000
+80 10 33.241540
+80 11 28.284271
+80 12 28.071338
+80 13 23.086793
+80 14 33.015148
+80 15 23.021729
+80 16 28.284271
+80 17 28.635642
+80 18 23.769729
+80 19 73.573093
+80 20 68.264193
+80 21 64.070274
+80 22 71.589105
+80 23 62.968246
+80 24 70.661163
+80 25 61.911227
+80 26 69.354164
+80 27 96.772930
+80 28 94.921020
+80 29 94.021274
+80 30 90.249654
+80 31 90.376988
+80 32 88.391176
+80 33 89.470666
+80 34 89.944427
+80 35 85.615419
+80 36 63.324561
+80 37 61.400326
+80 38 60.638272
+80 39 57.271284
+80 40 55.317267
+80 41 56.612719
+80 42 52.469038
+80 43 50.447993
+80 44 51.865210
+80 45 50.960769
+80 46 19.798990
+80 47 16.970563
+80 48 23.345235
+80 49 72.560320
+80 50 66.573268
+80 51 73.790243
+80 52 68.593003
+80 53 42.485292
+80 54 22.803509
+80 55 49.648766
+80 56 25.298221
+80 57 55.000000
+80 58 49.244289
+80 59 58.694122
+80 60 48.166378
+80 61 12.041595
+80 62 39.115214
+80 63 67.601775
+80 64 76.059187
+80 65 54.451814
+80 66 40.311289
+80 67 46.754679
+80 68 63.560994
+80 69 34.928498
+80 70 29.681644
+80 71 29.017236
+80 72 60.415230
+80 73 57.078893
+80 74 8.944272
+80 75 50.000000
+80 76 63.007936
+80 77 77.794601
+80 78 67.186308
+80 79 12.165525
+80 81 46.065171
+80 82 44.147480
+80 83 32.649655
+80 84 48.270074
+80 85 64.202804
+80 86 72.622311
+80 87 46.486557
+80 88 44.407207
+80 89 20.591260
+80 90 87.692645
+80 91 37.443290
+80 92 50.249378
+80 93 53.235327
+80 94 57.280014
+80 95 54.781384
+80 96 58.830264
+80 97 50.960769
+80 98 50.039984
+80 99 25.612497
+80 100 38.587563
+80 101 25.019992
+81 1 7.615773
+81 2 43.908997
+81 3 37.536649
+81 4 45.486262
+81 5 42.638011
+81 6 46.615448
+81 7 40.311289
+81 8 42.520583
+81 9 45.967380
+81 10 38.897301
+81 11 37.656341
+81 12 39.623226
+81 13 39.051248
+81 14 43.680659
+81 15 42.047592
+81 16 45.541190
+81 17 47.518417
+81 18 47.042534
+81 19 42.107007
+81 20 37.336309
+81 21 32.388269
+81 22 42.579338
+81 23 32.756679
+81 24 42.953463
+81 25 33.241540
+81 26 43.680659
+81 27 50.921508
+81 28 49.477268
+81 29 48.104054
+81 30 44.643029
+81 31 44.384682
+81 32 42.720019
+81 33 43.462628
+81 34 43.908997
+81 35 39.849718
+81 36 42.941821
+81 37 42.047592
+81 38 39.357337
+81 39 36.249138
+81 40 35.468296
+81 41 40.162171
+81 42 30.083218
+81 43 33.955854
+81 44 38.832976
+81 45 35.902646
+81 46 44.204072
+81 47 43.931765
+81 48 45.044423
+81 49 42.296572
+81 50 35.355339
+81 51 27.730849
+81 52 28.160256
+81 53 27.802878
+81 54 27.166155
+81 55 15.264338
+81 56 21.400935
+81 57 12.369317
+81 58 27.802878
+81 59 48.918299
+81 60 45.803930
+81 61 34.539832
+81 62 18.110770
+81 63 21.633308
+81 64 32.449961
+81 65 17.117243
+81 66 13.892444
+81 67 11.661904
+81 68 17.720045
+81 69 14.764823
+81 70 16.763055
+81 71 25.059928
+81 72 19.697716
+81 73 24.083189
+81 74 46.840154
+81 75 38.183766
+81 76 59.396970
+81 77 37.336309
+81 78 50.119856
+81 79 40.024992
+81 80 46.065171
+81 82 11.180340
+81 83 20.396078
+81 84 18.867962
+81 85 20.591260
+81 86 28.844410
+81 87 34.713110
+81 88 41.880783
+81 89 25.495098
+81 90 46.518813
+81 91 10.000000
+81 92 5.385165
+81 93 7.211103
+81 94 14.866069
+81 95 10.049876
+81 96 13.453624
+81 97 10.630146
+81 98 51.865210
+81 99 21.587033
+81 100 24.186773
+81 101 25.612497
+82 1 12.041595
+82 2 36.124784
+82 3 31.906112
+82 4 38.183766
+82 5 36.400549
+82 6 39.623226
+82 7 35.355339
+82 8 38.013156
+82 9 40.496913
+82 10 45.276926
+82 11 42.953463
+82 12 44.777226
+82 13 43.011626
+82 14 49.648766
+82 15 45.880279
+82 16 50.328918
+82 17 52.201533
+82 18 50.695167
+82 19 53.235327
+82 20 48.507731
+82 21 43.566042
+82 22 53.758720
+82 23 43.931765
+82 24 54.129474
+82 25 44.384682
+82 26 54.817880
+82 27 53.851648
+82 28 51.429563
+82 29 51.312766
+82 30 47.010637
+82 31 48.010416
+82 32 45.276926
+82 33 47.201695
+82 34 48.836462
+82 35 42.720019
+82 36 32.449961
+82 37 31.384710
+82 38 28.844410
+82 39 25.553865
+82 40 24.596748
+82 41 29.154759
+82 42 19.235384
+82 43 22.803509
+82 44 27.658633
+82 45 24.738634
+82 46 37.643060
+82 47 38.013156
+82 48 48.764741
+82 49 53.460266
+82 50 46.529560
+82 51 32.526912
+82 52 38.470768
+82 53 36.878178
+82 54 30.083218
+82 55 6.324555
+82 56 19.104973
+82 57 23.021729
+82 58 38.078866
+82 59 58.821765
+82 60 54.451814
+82 61 34.058773
+82 62 8.062258
+82 63 28.017851
+82 64 41.231056
+82 65 28.284271
+82 66 22.803509
+82 67 22.472205
+82 68 21.931712
+82 69 9.219544
+82 70 18.973666
+82 71 17.804494
+82 72 16.278821
+82 73 15.652476
+82 74 47.042534
+82 75 47.801674
+82 76 68.883960
+82 77 47.296934
+82 78 60.835845
+82 79 41.048752
+82 80 44.147480
+82 81 11.180340
+82 83 26.627054
+82 84 29.546573
+82 85 30.083218
+82 86 37.696154
+82 87 44.045431
+82 88 50.249378
+82 89 25.000000
+82 90 55.973208
+82 91 16.278821
+82 92 16.000000
+82 93 15.524175
+82 94 13.416408
+82 95 12.806248
+82 96 22.135944
+82 97 7.211103
+82 98 60.207973
+82 99 23.769729
+82 100 32.526912
+82 101 20.124612
+83 1 14.764823
+83 2 42.047592
+83 3 32.388269
+83 4 42.296572
+83 5 37.656341
+83 6 42.579338
+83 7 33.241540
+83 8 34.176015
+83 9 38.897301
+83 10 18.788294
+83 11 17.262677
+83 12 19.235384
+83 13 19.104973
+83 14 23.409400
+83 15 22.090722
+83 16 25.179357
+83 17 27.166155
+83 18 27.073973
+83 19 41.629317
+83 20 36.249138
+83 21 31.764760
+83 22 40.162171
+83 23 30.870698
+83 24 39.560081
+83 25 30.083218
+83 26 38.832976
+83 27 69.231496
+83 28 68.468971
+83 29 66.287254
+83 30 63.505905
+83 31 62.369865
+83 32 61.522354
+83 33 61.392182
+83 34 60.728906
+83 35 58.549125
+83 36 58.000000
+83 37 56.639209
+83 38 54.451814
+83 39 50.931326
+83 40 49.578221
+83 41 53.413481
+83 42 44.553339
+83 43 46.400431
+83 44 50.477718
+83 45 48.010416
+83 46 39.623226
+83 47 38.078866
+83 48 25.079872
+83 49 40.853396
+83 50 34.438351
+83 51 45.705580
+83 52 36.235342
+83 53 13.152946
+83 54 9.899495
+83 55 32.756679
+83 56 17.262677
+83 57 24.351591
+83 58 18.248288
+83 59 35.114100
+83 60 28.600699
+83 61 20.808652
+83 62 28.425341
+83 63 38.832976
+83 64 44.418465
+83 65 22.203603
+83 66 8.544004
+83 67 15.231546
+83 68 37.013511
+83 69 21.400935
+83 70 9.848858
+83 71 27.202941
+83 72 39.849718
+83 73 42.190046
+83 74 30.232433
+83 75 24.041631
+83 76 43.908997
+83 77 45.276926
+83 78 40.199502
+83 79 23.021729
+83 80 32.649655
+83 81 20.396078
+83 82 26.627054
+83 84 15.620499
+83 85 33.105891
+83 86 41.182521
+83 87 19.924859
+83 88 24.207437
+83 89 15.297059
+83 90 55.172457
+83 91 10.770330
+83 92 22.022716
+83 93 26.000000
+83 94 35.171011
+83 95 30.413813
+83 96 29.614186
+83 97 30.083218
+83 98 33.970576
+83 99 9.055385
+83 100 8.062258
+83 101 24.331050
+84 1 19.235384
+84 2 55.317267
+84 3 46.486557
+84 4 56.044625
+84 5 51.865210
+84 6 56.612719
+84 7 47.927028
+84 8 49.193496
+84 9 53.712196
+84 10 27.294688
+84 11 28.460499
+84 12 30.364453
+84 13 32.202484
+84 14 32.249031
+84 15 34.928498
+84 16 36.138622
+84 17 38.078866
+84 18 39.560081
+84 19 26.925824
+84 20 21.587033
+84 21 16.763055
+84 22 26.172505
+84 23 16.278821
+84 24 26.019224
+84 25 16.031220
+84 26 26.076810
+84 27 58.008620
+84 28 58.137767
+84 29 55.009090
+84 30 53.150729
+84 31 51.009803
+84 32 51.156622
+84 33 50.009999
+84 34 48.373546
+84 35 48.166378
+84 36 61.773781
+84 37 60.827625
+84 38 58.180753
+84 39 55.009090
+84 40 54.129474
+84 41 58.694122
+84 42 48.754487
+84 43 52.201533
+84 44 56.920998
+84 45 54.083269
+84 46 53.758720
+84 47 52.554733
+84 48 37.696154
+84 49 26.476405
+84 50 19.646883
+84 51 35.227830
+84 52 21.095023
+84 53 12.041595
+84 54 25.495098
+84 55 34.132096
+84 56 29.832868
+84 57 13.601471
+84 58 9.219544
+84 59 30.413813
+84 60 29.154759
+84 61 36.400549
+84 62 34.928498
+84 63 28.284271
+84 64 30.083218
+84 65 8.062258
+84 66 9.219544
+84 67 7.211103
+84 68 29.154759
+84 69 29.154759
+84 70 21.840330
+84 71 38.052595
+84 72 36.878178
+84 73 42.801869
+84 74 45.453273
+84 75 20.248457
+84 76 41.231056
+84 77 29.832868
+84 78 31.304952
+84 79 38.288379
+84 80 48.270074
+84 81 18.867962
+84 82 29.546573
+84 83 15.620499
+84 85 20.099751
+84 86 27.202941
+84 87 17.464249
+84 88 25.961510
+84 89 29.966648
+84 90 39.698866
+84 91 16.000000
+84 92 16.278821
+84 93 20.000000
+84 94 31.890437
+84 95 26.248809
+84 96 19.924859
+84 97 29.206164
+84 98 35.468296
+84 99 23.706539
+84 100 11.704700
+84 101 36.496575
+85 1 27.018512
+85 2 64.498062
+85 3 57.801384
+85 4 66.037868
+85 5 63.007936
+85 6 67.119297
+85 7 60.307545
+85 8 62.289646
+85 9 66.068147
+85 10 47.381431
+85 11 48.270074
+85 12 50.219518
+85 13 51.546096
+85 14 52.345009
+85 15 54.405882
+85 16 56.089215
+85 17 58.051701
+85 18 59.203040
+85 19 27.294688
+85 20 24.207437
+85 21 20.518285
+85 22 29.410882
+85 23 22.022716
+85 24 30.610456
+85 25 23.600847
+85 26 32.557641
+85 27 38.013156
+85 28 38.470768
+85 29 35.014283
+85 30 33.541020
+85 31 31.016125
+85 32 31.575307
+85 33 30.016662
+85 34 28.284271
+85 35 28.635642
+85 36 56.885851
+85 37 56.568542
+85 38 53.600373
+85 39 51.244512
+85 40 51.088159
+85 41 56.080300
+85 42 46.010868
+85 43 51.039201
+85 44 56.035703
+85 45 53.037722
+85 46 64.637450
+85 47 64.202804
+85 48 57.280014
+85 49 28.301943
+85 50 22.671568
+85 51 16.155494
+85 52 9.219544
+85 53 32.015621
+85 54 42.544095
+85 55 31.064449
+85 56 41.109610
+85 57 9.219544
+85 58 27.294688
+85 59 46.097722
+85 60 47.853944
+85 61 52.201533
+85 62 37.947332
+85 63 10.000000
+85 64 12.041595
+85 65 12.041595
+85 66 24.596748
+85 67 17.888544
+85 68 14.764823
+85 69 35.355339
+85 70 34.713110
+85 71 45.650849
+85 72 27.202941
+85 73 36.496575
+85 74 63.134776
+85 75 38.078866
+85 76 57.271284
+85 77 17.262677
+85 78 42.801869
+85 79 55.946403
+85 80 64.202804
+85 81 20.591260
+85 82 30.083218
+85 83 33.105891
+85 84 20.099751
+85 86 8.485281
+85 87 36.345564
+85 88 45.276926
+85 89 43.931765
+85 90 26.000000
+85 91 26.907248
+85 92 15.264338
+85 93 14.560220
+85 94 23.345235
+85 95 19.000000
+85 96 8.062258
+85 97 25.079872
+85 98 54.129474
+85 99 38.600518
+85 100 31.575307
+85 101 46.043458
+86 1 35.468296
+86 2 72.718636
+86 3 66.219333
+86 4 74.330344
+86 5 71.400280
+86 6 75.451971
+86 7 68.767725
+86 8 70.767224
+86 9 74.518454
+86 10 54.341513
+86 11 55.659680
+86 12 57.567352
+86 13 59.236813
+86 14 59.228372
+86 15 62.032250
+86 16 63.324561
+86 17 65.253352
+86 18 66.730802
+86 19 26.172505
+86 20 24.698178
+86 21 22.472205
+86 22 29.206164
+86 23 24.351591
+86 24 30.805844
+86 25 26.248809
+86 26 33.286634
+86 27 32.756679
+86 28 34.176015
+86 29 29.832868
+86 30 29.546573
+86 31 25.961510
+86 32 27.730849
+86 33 25.000000
+86 34 22.090722
+86 35 25.059928
+86 36 62.128898
+86 37 62.032250
+86 38 59.033889
+86 39 57.008771
+86 40 57.078893
+86 41 62.072538
+86 42 52.239832
+86 43 57.558666
+86 44 62.513998
+86 45 59.539903
+86 46 73.006849
+86 47 72.622311
+86 48 64.845971
+86 49 27.658633
+86 50 23.706539
+86 51 15.000000
+86 52 8.544004
+86 53 38.639358
+86 54 50.774009
+86 55 37.854986
+86 56 49.578221
+86 57 17.691806
+86 58 33.060551
+86 59 49.729267
+86 60 53.084838
+86 61 60.605280
+86 62 45.694639
+86 63 12.165525
+86 64 3.605551
+86 65 19.313208
+86 66 32.756679
+86 67 26.076810
+86 68 19.026298
+86 69 43.566042
+86 70 43.185646
+86 71 53.851648
+86 72 32.062439
+86 73 42.000000
+86 74 71.344236
+86 75 43.104524
+86 76 60.728906
+86 77 11.401754
+86 78 44.721360
+86 79 64.140471
+86 80 72.622311
+86 81 28.844410
+86 82 37.696154
+86 83 41.182521
+86 84 27.202941
+86 85 8.485281
+86 87 42.011903
+86 88 51.009803
+86 89 52.402290
+86 90 18.439089
+86 91 35.383612
+86 92 23.600847
+86 93 22.360680
+86 94 29.068884
+86 95 25.709920
+86 96 15.652476
+86 97 32.015621
+86 98 59.211485
+86 99 47.010637
+86 100 38.897301
+86 101 54.405882
+87 1 32.202484
+87 2 61.131007
+87 3 51.009803
+87 4 61.008196
+87 5 56.008928
+87 6 61.008196
+87 7 51.088159
+87 8 51.351728
+87 9 56.320511
+87 10 15.556349
+87 11 19.416488
+87 12 20.615528
+87 13 24.698178
+87 14 19.416488
+87 15 26.400758
+87 16 24.839485
+87 17 26.400758
+87 18 29.698485
+87 19 29.832868
+87 20 25.238859
+87 21 22.847319
+87 22 26.870058
+87 23 21.023796
+87 24 25.495098
+87 25 19.235384
+87 26 23.600847
+87 27 74.242845
+87 28 74.813100
+87 29 71.253070
+87 30 69.871310
+87 31 67.268120
+87 32 67.896981
+87 33 66.272166
+87 34 64.007812
+87 35 64.938432
+87 36 76.400262
+87 37 75.213031
+87 38 72.801099
+87 39 69.404611
+87 40 68.242216
+87 41 72.401657
+87 42 63.007936
+87 43 65.513357
+87 44 69.835521
+87 45 67.230945
+87 46 58.008620
+87 47 56.080300
+87 48 28.319605
+87 49 28.319605
+87 50 24.186773
+87 51 52.172790
+87 52 34.234486
+87 53 7.211103
+87 54 26.019224
+87 55 49.517674
+87 56 37.107951
+87 57 31.016125
+87 58 9.055385
+87 59 15.231546
+87 60 11.704700
+87 61 36.496575
+87 62 47.507894
+87 63 45.354162
+87 64 44.181444
+87 65 24.738634
+87 66 21.260292
+87 67 23.853721
+87 68 46.615448
+87 69 40.706265
+87 70 29.732137
+87 71 47.127487
+87 72 53.823787
+87 73 58.694122
+87 74 40.706265
+87 75 4.123106
+87 76 24.839485
+87 77 40.804412
+87 78 21.095023
+87 79 34.539832
+87 80 46.486557
+87 81 34.713110
+87 82 44.045431
+87 83 19.924859
+87 84 17.464249
+87 85 36.345564
+87 86 42.011903
+87 88 9.000000
+87 89 34.132096
+87 90 49.769469
+87 91 28.017851
+87 92 33.286634
+87 93 37.215588
+87 94 48.826222
+87 95 43.266615
+87 96 37.336309
+87 97 45.343136
+87 98 18.027756
+87 99 28.442925
+87 100 12.083046
+87 101 44.147480
+88 1 38.209946
+88 2 62.369865
+88 3 51.971146
+88 4 61.814238
+88 5 56.568542
+88 6 61.522354
+88 7 51.351728
+88 8 51.088159
+88 9 56.080300
+88 10 11.180340
+88 11 16.124515
+88 12 16.492423
+88 13 21.377558
+88 14 13.038405
+88 15 22.135944
+88 16 18.867962
+88 17 20.000000
+88 18 24.186773
+88 19 37.215588
+88 20 33.105891
+88 21 31.320920
+88 22 33.837849
+88 23 29.410882
+88 24 32.202484
+88 25 27.513633
+88 26 29.832868
+88 27 83.216585
+88 28 83.725743
+88 29 80.224684
+88 30 78.771822
+88 31 76.236474
+88 32 76.791927
+88 33 75.239617
+88 34 73.006849
+88 35 73.824115
+88 36 82.134037
+88 37 80.808415
+88 38 78.568442
+88 39 75.073298
+88 40 73.756356
+88 41 77.620873
+88 42 68.680419
+88 43 70.604532
+88 44 74.632433
+88 45 72.201108
+88 46 58.549125
+88 47 56.320511
+88 48 23.259407
+88 49 35.510562
+88 50 32.310989
+88 51 61.000000
+88 52 43.185646
+88 53 14.317821
+88 54 27.202941
+88 55 56.080300
+88 56 40.249224
+88 57 39.560081
+88 58 18.027756
+88 59 14.317821
+88 60 4.472136
+88 61 36.124784
+88 62 52.630789
+88 63 54.129474
+88 64 53.150729
+88 65 33.541020
+88 66 28.017851
+88 67 31.780497
+88 68 55.027266
+88 69 45.607017
+88 70 33.837849
+88 71 50.537115
+88 72 61.400326
+88 73 65.436993
+88 74 37.363083
+88 75 8.944272
+88 76 20.248457
+88 77 49.477268
+88 78 23.706539
+88 79 32.249031
+88 80 44.407207
+88 81 41.880783
+88 82 50.249378
+88 83 24.207437
+88 84 25.961510
+88 85 45.276926
+88 86 51.009803
+88 87 9.000000
+88 89 36.055513
+88 90 58.189346
+88 91 33.970576
+88 92 41.146081
+88 93 45.188494
+88 94 56.435804
+88 95 51.000000
+88 96 45.880279
+88 97 52.430907
+88 98 10.000000
+88 99 31.304952
+88 100 17.804494
+88 101 47.010637
+89 1 17.888544
+89 2 27.018512
+89 3 17.117243
+89 4 27.073973
+89 5 22.360680
+89 6 27.294688
+89 7 18.027756
+89 8 19.235384
+89 9 23.769729
+89 10 26.925824
+89 11 22.803509
+89 12 24.083189
+89 13 20.615528
+89 14 29.832868
+89 15 23.021729
+89 16 28.425341
+89 17 30.000000
+89 18 27.294688
+89 19 56.648036
+89 20 51.264022
+89 21 46.615448
+89 22 55.362442
+89 23 45.880279
+89 24 54.817880
+89 25 45.221676
+89 26 54.129474
+89 27 76.321688
+89 28 74.632433
+89 29 73.539105
+89 30 69.892775
+89 31 69.856997
+89 32 68.007353
+89 33 68.942005
+89 34 69.354164
+89 35 65.192024
+89 36 50.774009
+89 37 49.091751
+89 38 47.507894
+89 39 43.908997
+89 40 42.190046
+89 41 45.000000
+89 42 38.013156
+89 43 38.013156
+89 44 41.109610
+89 45 39.204592
+89 46 24.331050
+89 47 22.803509
+89 48 25.553865
+89 49 55.973208
+89 50 49.396356
+89 51 53.225934
+89 52 49.040799
+89 53 28.017851
+89 54 8.944272
+89 55 31.064449
+89 56 6.324555
+89 57 34.713110
+89 58 33.541020
+89 59 48.836462
+89 60 40.496913
+89 61 9.219544
+89 62 22.135944
+89 63 47.010637
+89 64 55.901699
+89 65 35.000000
+89 66 21.095023
+89 67 27.018512
+89 68 43.081318
+89 69 16.124515
+89 70 9.219544
+89 71 15.556349
+89 72 41.109610
+89 73 39.623226
+89 74 22.090722
+89 75 38.209946
+89 76 56.302753
+89 77 58.412327
+89 78 55.009090
+89 79 16.124515
+89 80 20.591260
+89 81 25.495098
+89 82 25.000000
+89 83 15.297059
+89 84 29.966648
+89 85 43.931765
+89 86 52.402290
+89 87 34.132096
+89 88 36.055513
+89 90 68.249542
+89 91 17.029386
+89 92 29.681644
+89 93 32.649655
+89 94 37.483330
+89 95 34.481879
+89 96 38.275318
+89 97 31.256999
+89 98 44.721360
+89 99 6.324555
+89 100 23.086793
+89 101 11.401754
+90 1 52.478567
+90 2 90.354856
+90 3 83.216585
+90 4 91.787799
+90 5 88.509886
+90 6 92.784697
+90 7 85.445889
+90 8 87.200917
+90 9 91.263355
+90 10 64.412732
+90 11 66.887966
+90 12 68.600292
+90 13 71.281134
+90 14 68.876701
+90 15 73.783467
+90 16 73.824115
+90 17 75.591005
+90 18 78.032045
+90 19 23.000000
+90 20 25.495098
+90 21 26.925824
+90 22 27.000000
+90 23 28.792360
+90 24 29.000000
+90 25 30.675723
+90 26 32.000000
+90 27 37.536649
+90 28 41.036569
+90 29 35.355339
+90 30 37.802116
+90 31 32.649655
+90 32 36.619667
+90 33 32.015621
+90 34 26.907248
+90 35 34.985711
+90 36 80.000000
+90 37 80.024996
+90 38 77.025970
+90 39 75.166482
+90 40 75.325958
+90 41 80.305666
+90 42 70.576200
+90 43 75.953933
+90 44 80.894994
+90 45 77.929455
+90 46 90.210864
+90 47 89.587946
+90 48 76.321688
+90 49 25.000000
+90 50 25.961510
+90 51 30.413813
+90 52 19.209373
+90 53 48.877398
+90 54 65.069194
+90 55 56.293872
+90 56 66.287254
+90 57 34.481879
+90 58 42.059482
+90 59 52.239832
+90 60 58.940648
+90 61 75.690158
+90 62 63.906181
+90 63 30.066593
+90 64 15.132746
+90 65 33.301652
+90 66 47.423623
+90 67 41.231056
+90 68 37.121422
+90 69 61.269895
+90 70 59.203040
+90 71 71.554175
+90 72 50.039984
+90 73 60.133186
+90 74 85.146932
+90 75 49.335586
+90 76 62.000000
+90 77 9.899495
+90 78 44.045431
+90 79 77.987178
+90 80 87.692645
+90 81 46.518813
+90 82 55.973208
+90 83 55.172457
+90 84 39.698866
+90 85 26.000000
+90 86 18.439089
+90 87 49.769469
+90 88 58.189346
+90 89 68.249542
+90 91 51.613952
+90 92 41.146081
+90 93 40.496913
+90 94 47.381431
+90 95 44.147480
+90 96 33.837849
+90 97 50.447993
+90 98 64.327288
+90 99 62.369865
+90 100 50.803543
+90 101 71.693793
+91 1 4.242641
+91 2 39.849718
+91 3 31.764760
+91 4 40.853396
+91 5 37.121422
+91 6 41.629317
+91 7 33.837849
+91 8 35.608988
+91 9 39.661064
+91 10 29.546573
+91 11 27.892651
+91 12 29.832868
+91 13 29.068884
+91 14 34.176015
+91 15 32.062439
+91 16 35.693137
+91 17 37.656341
+91 18 37.054015
+91 19 42.579338
+91 20 37.336309
+91 21 32.388269
+91 22 42.107007
+91 23 32.140317
+91 24 42.011903
+91 25 32.015621
+91 26 42.047592
+91 27 60.440053
+91 28 59.228372
+91 29 57.567352
+91 30 54.341513
+91 31 53.758720
+91 32 52.392748
+91 33 52.810984
+91 34 52.801515
+91 35 49.477268
+91 36 48.414874
+91 37 47.201695
+91 38 44.821870
+91 39 41.400483
+91 40 40.224371
+91 41 44.418465
+91 42 35.000000
+91 43 37.589892
+91 44 42.047592
+91 45 39.357337
+91 46 38.910153
+91 47 38.078866
+91 48 35.057096
+91 49 42.296572
+91 50 35.355339
+91 51 37.000000
+91 52 32.449961
+91 53 20.808652
+91 54 17.262677
+91 55 22.203603
+91 56 14.764823
+91 57 17.691806
+91 58 23.086793
+91 59 43.046487
+91 60 38.183766
+91 61 25.553865
+91 62 19.697716
+91 63 30.463092
+91 64 38.897301
+91 65 18.788294
+91 66 7.280110
+91 67 10.770330
+91 68 27.459060
+91 69 13.341664
+91 70 7.810250
+91 71 22.090722
+91 72 29.120440
+91 73 31.622777
+91 74 37.336309
+91 75 31.906112
+91 76 52.801515
+91 77 41.880783
+91 78 46.173586
+91 79 30.364453
+91 80 37.443290
+91 81 10.000000
+91 82 16.278821
+91 83 10.770330
+91 84 16.000000
+91 85 26.907248
+91 86 35.383612
+91 87 28.017851
+91 88 33.970576
+91 89 17.029386
+91 90 51.613952
+91 92 13.000000
+91 93 16.492423
+91 94 24.515301
+91 95 20.024984
+91 96 21.470911
+91 97 19.313208
+91 98 43.931765
+91 99 12.083046
+91 100 16.278821
+91 101 20.880613
+92 1 12.041595
+92 2 49.244289
+92 3 42.638011
+92 4 50.774009
+92 5 47.801674
+92 6 51.865210
+92 7 45.276926
+92 8 47.381431
+92 9 50.990195
+92 10 39.623226
+92 11 39.051248
+92 12 41.048752
+92 13 41.109610
+92 14 44.553339
+92 15 44.102154
+92 16 47.042534
+92 17 49.040799
+92 18 49.091751
+92 19 37.336309
+92 20 32.756679
+92 21 27.892651
+92 22 38.078866
+92 23 28.460499
+92 24 38.600518
+92 25 29.154759
+92 26 39.560081
+92 27 47.539457
+92 28 46.529560
+92 29 44.643029
+92 30 41.593269
+92 31 40.804412
+92 32 39.623226
+92 33 39.849718
+92 34 39.812058
+92 35 36.674242
+92 36 46.615448
+92 37 45.880279
+92 38 43.081318
+92 39 40.162171
+92 40 39.560081
+92 41 44.384682
+92 42 34.205263
+92 43 38.470768
+92 44 43.416587
+92 45 40.447497
+92 46 49.406477
+92 47 49.040799
+92 48 47.095647
+92 49 37.656341
+92 50 30.805844
+92 51 24.041631
+92 52 22.803509
+92 53 26.832816
+92 54 30.083218
+92 55 18.973666
+92 56 26.172505
+92 57 7.071068
+92 58 25.495098
+92 59 46.690470
+92 60 44.777226
+92 61 38.470768
+92 62 23.345235
+92 63 17.464249
+92 64 27.202941
+92 65 12.649111
+92 66 14.142136
+92 67 9.433981
+92 68 15.000000
+92 69 20.124612
+92 70 20.591260
+92 71 30.413813
+92 72 20.615528
+92 73 26.925824
+92 74 50.328918
+92 75 36.400549
+92 76 57.489129
+92 77 31.953091
+92 78 46.872167
+92 79 43.324358
+92 80 50.249378
+92 81 5.385165
+92 82 16.000000
+92 83 22.022716
+92 84 16.278821
+92 85 15.264338
+92 86 23.600847
+92 87 33.286634
+92 88 41.146081
+92 89 29.681644
+92 90 41.146081
+92 91 13.000000
+92 93 4.123106
+92 94 15.620499
+92 95 10.000000
+92 96 8.602325
+92 97 13.416408
+92 98 51.000000
+92 99 25.079872
+92 100 24.041631
+92 101 30.805844
+93 1 14.764823
+93 2 50.477718
+93 3 44.553339
+93 4 52.201533
+93 5 49.578221
+93 6 53.413481
+93 7 47.423623
+93 8 49.678969
+93 9 53.037722
+93 10 43.737855
+93 11 43.104524
+93 12 45.099889
+93 13 45.044423
+93 14 48.662100
+93 15 48.041649
+93 16 51.088159
+93 17 53.084838
+93 18 53.037722
+93 19 39.051248
+93 20 34.785054
+93 21 30.083218
+93 22 40.162171
+93 23 30.870698
+93 24 40.853396
+93 25 31.764760
+93 26 42.047592
+93 27 43.965896
+93 28 42.755117
+93 29 41.109610
+93 30 37.854986
+93 31 37.336309
+93 32 35.902646
+93 33 36.400549
+93 34 36.715120
+93 35 32.984845
+93 36 44.271887
+93 37 43.680659
+93 38 40.804412
+93 39 38.078866
+93 40 37.656341
+93 41 42.579338
+93 42 32.388269
+93 43 37.054015
+93 44 42.047592
+93 45 39.051248
+93 46 51.088159
+93 47 50.931326
+93 48 51.039201
+93 49 39.560081
+93 50 32.893768
+93 51 20.615528
+93 52 23.086793
+93 53 30.870698
+93 54 33.734256
+93 55 17.117243
+93 56 28.600699
+93 57 8.544004
+93 58 29.206164
+93 59 50.328918
+93 60 48.764741
+93 61 41.629317
+93 62 23.409400
+93 63 14.422205
+93 64 25.942244
+93 65 15.264338
+93 66 18.248288
+93 67 13.416408
+93 68 11.045361
+93 69 21.400935
+93 70 23.769729
+93 71 31.622777
+93 72 16.970563
+93 73 24.166092
+93 74 53.758720
+93 75 40.224371
+93 76 61.220911
+93 77 31.780497
+93 78 50.000000
+93 79 46.840154
+93 80 53.235327
+93 81 7.211103
+93 82 15.524175
+93 83 26.000000
+93 84 20.000000
+93 85 14.560220
+93 86 22.360680
+93 87 37.215588
+93 88 45.188494
+93 89 32.649655
+93 90 40.496913
+93 91 16.492423
+93 92 4.123106
+93 94 12.041595
+93 95 6.403124
+93 96 6.708204
+93 97 11.180340
+93 98 55.009090
+93 99 28.460499
+93 100 28.160256
+93 101 32.557641
+94 1 21.095023
+94 2 48.836462
+94 3 45.276926
+94 4 51.088159
+94 5 49.648766
+94 6 52.630789
+94 7 48.764741
+94 8 51.429563
+94 9 53.851648
+94 10 53.758720
+94 11 52.392748
+94 12 54.341513
+94 13 53.460266
+94 14 58.523500
+94 15 56.435804
+94 16 60.207973
+94 17 62.169124
+94 18 61.400326
+94 19 49.979996
+94 20 46.097722
+94 21 41.593269
+94 22 51.478151
+94 23 42.544095
+94 24 52.325902
+94 25 43.566042
+94 26 53.712196
+94 27 40.496913
+94 28 38.013156
+94 29 38.013156
+94 30 33.615473
+94 31 34.828150
+94 32 31.906112
+94 33 34.058773
+94 34 36.124784
+94 35 29.410882
+94 36 33.541020
+94 37 33.241540
+94 38 30.265492
+94 39 28.017851
+94 40 28.017851
+94 41 33.015148
+94 42 23.194827
+94 43 28.635642
+94 44 33.541020
+94 45 30.594117
+94 46 50.803543
+94 47 51.312766
+94 48 59.413803
+94 49 50.695167
+94 50 44.283180
+94 51 20.248457
+94 52 32.557641
+94 53 42.190046
+94 54 41.048752
+94 55 10.000000
+94 56 32.015621
+94 57 20.248457
+94 58 41.109610
+94 59 62.289646
+94 60 60.207973
+94 61 46.690470
+94 62 20.615528
+94 63 17.464249
+94 64 32.249031
+94 65 27.202941
+94 66 28.635642
+94 67 25.000000
+94 68 10.440307
+94 69 22.472205
+94 70 30.000000
+94 71 31.064449
+94 72 5.000000
+94 73 13.152946
+94 74 59.539903
+94 75 52.009614
+94 76 73.109507
+94 77 40.012498
+94 78 62.008064
+94 79 53.150729
+94 80 57.280014
+94 81 14.866069
+94 82 13.416408
+94 83 35.171011
+94 84 31.890437
+94 85 23.345235
+94 86 29.068884
+94 87 48.826222
+94 88 56.435804
+94 89 37.483330
+94 90 47.381431
+94 91 24.515301
+94 92 15.620499
+94 93 12.041595
+94 95 5.656854
+94 96 15.811388
+94 97 6.324555
+94 98 66.370174
+94 99 35.000000
+94 100 38.910153
+94 101 33.541020
+95 1 17.117243
+95 2 48.918299
+95 3 44.204072
+95 4 50.931326
+95 5 48.918299
+95 6 52.325902
+95 7 47.434165
+95 8 49.929951
+95 9 52.801515
+95 10 48.764741
+95 11 47.675990
+95 12 49.648766
+95 13 49.091751
+95 14 53.600373
+95 15 52.086467
+95 16 55.578773
+95 17 57.558666
+95 18 57.078893
+95 19 44.922155
+95 20 40.853396
+95 21 36.249138
+95 22 46.238512
+95 23 37.121422
+95 24 47.010637
+95 25 38.078866
+95 26 48.301139
+95 27 42.047592
+95 28 40.162171
+95 29 39.357337
+95 30 35.468296
+95 31 35.846897
+95 32 33.615473
+95 33 34.985711
+95 34 36.235342
+95 35 30.870698
+95 36 38.327536
+95 37 37.854986
+95 38 34.928498
+95 39 32.388269
+95 40 32.140317
+95 41 37.121422
+95 42 27.018512
+95 43 32.062439
+95 44 37.054015
+95 45 34.058773
+95 46 50.249378
+95 47 50.447993
+95 48 55.081757
+95 49 45.541190
+95 50 39.000000
+95 51 19.849433
+95 52 28.071338
+95 53 36.715120
+95 54 37.054015
+95 55 12.165525
+95 56 29.546573
+95 57 14.764823
+95 58 35.468296
+95 59 56.639209
+95 60 54.708317
+95 61 43.680659
+95 62 20.808652
+95 63 15.264338
+95 64 29.120440
+95 65 21.633308
+95 66 23.409400
+95 67 19.416488
+95 68 9.219544
+95 69 20.808652
+95 70 26.305893
+95 71 30.413813
+95 72 10.630146
+95 73 18.027756
+95 74 56.293872
+95 75 46.400431
+95 76 67.475922
+95 77 36.124784
+95 78 56.400355
+95 79 49.648766
+95 80 54.781384
+95 81 10.049876
+95 82 12.806248
+95 83 30.413813
+95 84 26.248809
+95 85 19.000000
+95 86 25.709920
+95 87 43.266615
+95 88 51.000000
+95 89 34.481879
+95 90 44.147480
+95 91 20.024984
+95 92 10.000000
+95 93 6.403124
+95 94 5.656854
+95 96 11.045361
+95 97 6.324555
+95 98 60.901560
+95 99 31.256999
+95 100 33.615473
+95 101 32.202484
+96 1 20.615528
+96 2 57.140179
+96 3 50.990195
+96 4 58.821765
+96 5 56.080300
+96 6 60.000000
+96 7 53.740115
+96 8 55.901699
+96 9 59.413803
+96 10 46.043458
+96 11 46.097722
+96 12 48.093659
+96 13 48.662100
+96 14 51.039201
+96 15 51.623638
+96 16 54.083269
+96 17 56.080300
+96 18 56.568542
+96 19 34.176015
+96 20 30.413813
+96 21 26.076810
+96 22 35.777088
+96 23 27.202941
+96 24 36.715120
+96 25 28.425341
+96 26 38.275318
+96 27 39.623226
+96 28 39.051248
+96 29 36.674242
+96 30 34.058773
+96 31 32.756679
+96 32 32.062439
+96 33 31.780497
+96 34 31.384710
+96 35 29.068884
+96 36 49.244289
+96 37 48.836462
+96 38 45.891176
+96 39 43.416587
+96 40 43.185646
+96 41 48.166378
+96 42 38.052595
+96 43 43.011626
+96 44 48.010416
+96 45 45.011110
+96 46 57.628118
+96 47 57.384667
+96 48 54.589376
+96 49 34.928498
+96 50 28.653098
+96 51 16.124515
+96 52 17.029386
+96 53 31.780497
+96 54 38.275318
+96 55 23.021729
+96 56 34.713110
+96 57 6.324555
+96 58 28.635642
+96 59 49.091751
+96 60 49.040799
+96 61 47.010637
+96 62 30.083218
+96 63 9.219544
+96 64 19.235384
+96 65 13.038405
+96 66 21.213203
+96 67 15.000000
+96 68 9.433981
+96 69 28.017851
+96 70 29.154759
+96 71 38.275318
+96 72 20.124612
+96 73 28.861739
+96 74 58.694122
+96 75 39.812058
+96 76 60.207973
+96 77 25.317978
+96 78 47.381431
+96 79 51.623638
+96 80 58.830264
+96 81 13.453624
+96 82 22.135944
+96 83 29.614186
+96 84 19.924859
+96 85 8.062258
+96 86 15.652476
+96 87 37.336309
+96 88 45.880279
+96 89 38.275318
+96 90 33.837849
+96 91 21.470911
+96 92 8.602325
+96 93 6.708204
+96 94 15.811388
+96 95 11.045361
+96 97 17.029386
+96 98 55.362442
+96 99 33.541020
+96 100 30.066593
+96 101 39.051248
+97 1 15.524175
+97 2 43.139309
+97 3 39.115214
+97 4 45.276926
+97 5 43.600459
+97 6 46.754679
+97 7 42.544095
+97 8 45.177428
+97 9 47.707442
+97 10 48.846699
+97 11 47.127487
+97 12 49.040799
+97 13 47.853944
+97 14 53.488316
+97 15 50.803543
+97 16 54.817880
+97 17 56.753854
+97 18 55.731499
+97 19 50.219518
+97 20 45.880279
+97 21 41.109610
+97 22 51.244512
+97 23 41.785165
+97 24 51.865210
+97 25 42.544095
+97 26 52.924474
+97 27 46.647615
+97 28 44.283180
+97 29 44.102154
+97 30 39.824616
+97 31 40.804412
+97 32 38.078866
+97 33 40.000000
+97 34 41.725292
+97 35 35.510562
+97 36 33.241540
+97 37 32.572995
+97 38 29.732137
+97 39 26.925824
+97 40 26.476405
+97 41 31.400637
+97 42 21.213203
+97 43 26.000000
+97 44 31.000000
+97 45 28.000000
+97 46 44.821870
+97 47 45.221676
+97 48 53.758720
+97 49 50.695167
+97 50 43.965896
+97 51 25.495098
+97 52 34.000000
+97 53 38.418745
+97 54 35.227830
+97 55 6.000000
+97 56 25.709920
+97 57 19.646883
+97 58 38.288379
+97 59 59.464275
+97 60 56.400355
+97 61 40.447497
+97 62 14.866069
+97 63 21.470911
+97 64 35.440090
+97 65 26.000000
+97 66 24.413111
+97 67 22.022716
+97 68 15.000000
+97 69 16.155494
+97 70 24.083189
+97 71 25.000000
+97 72 10.049876
+97 73 13.601471
+97 74 53.338541
+97 75 48.795492
+97 76 70.007142
+97 77 42.296572
+97 78 60.207973
+97 79 47.042534
+97 80 50.960769
+97 81 10.630146
+97 82 7.211103
+97 83 30.083218
+97 84 29.206164
+97 85 25.079872
+97 86 32.015621
+97 87 45.343136
+97 88 52.430907
+97 89 31.256999
+97 90 50.447993
+97 91 19.313208
+97 92 13.416408
+97 93 11.180340
+97 94 6.324555
+97 95 6.324555
+97 96 17.029386
+97 98 62.425956
+97 99 29.068884
+97 100 34.669872
+97 101 27.294688
+98 1 48.166378
+98 2 70.213959
+98 3 59.774577
+98 4 69.375788
+98 5 64.031242
+98 6 68.883960
+98 7 58.694122
+98 8 58.051701
+98 9 62.968246
+98 10 18.027756
+98 11 22.803509
+98 12 22.360680
+98 13 27.294688
+98 14 17.029386
+98 15 27.018512
+98 16 22.090722
+98 17 22.360680
+98 18 27.294688
+98 19 42.059482
+98 20 38.832976
+98 21 38.118237
+98 22 38.275318
+98 23 36.124784
+98 24 36.400549
+98 25 34.132096
+98 26 33.615473
+98 27 91.787799
+98 28 92.574294
+98 29 88.814413
+98 30 87.664132
+98 31 84.852814
+98 32 85.702975
+98 33 83.862983
+98 34 81.301906
+98 35 82.764727
+98 36 91.967386
+98 37 90.609050
+98 38 88.413800
+98 39 84.899941
+98 40 83.546394
+98 41 87.321246
+98 42 78.517514
+98 43 80.280757
+98 44 84.202138
+98 45 81.835200
+98 46 65.969690
+98 47 63.560994
+98 48 27.073973
+98 49 40.162171
+98 50 38.470768
+98 51 70.092796
+98 52 51.039201
+98 53 24.186773
+98 54 35.777088
+98 55 66.068147
+98 56 49.396356
+98 57 49.040799
+98 58 26.925824
+98 59 13.601471
+98 60 6.324555
+98 61 43.416587
+98 62 62.369865
+98 63 63.324561
+98 64 61.032778
+98 65 42.720019
+98 66 38.013156
+98 67 41.593269
+98 68 64.621978
+98 69 55.317267
+98 70 43.416587
+98 71 59.682493
+98 72 71.344236
+98 73 75.432089
+98 74 42.047592
+98 75 16.124515
+98 76 13.038405
+98 77 56.320511
+98 78 24.207437
+98 79 38.209946
+98 80 50.039984
+98 81 51.865210
+98 82 60.207973
+98 83 33.970576
+98 84 35.468296
+98 85 54.129474
+98 86 59.211485
+98 87 18.027756
+98 88 10.000000
+98 89 44.721360
+98 90 64.327288
+98 91 43.931765
+98 92 51.000000
+98 93 55.009090
+98 94 66.370174
+98 95 60.901560
+98 96 55.362442
+98 97 62.425956
+98 99 40.496913
+98 100 27.802878
+98 101 55.946403
+99 1 14.142136
+99 2 33.015148
+99 3 23.345235
+99 4 33.241540
+99 5 28.635642
+99 6 33.541020
+99 7 24.351591
+99 8 25.495098
+99 9 30.083218
+99 10 23.345235
+99 11 20.000000
+99 12 21.633308
+99 13 19.313208
+99 14 27.018512
+99 15 22.135944
+99 16 26.832816
+99 17 28.635642
+99 18 26.925824
+99 19 50.328918
+99 20 44.944410
+99 21 40.311289
+99 22 49.040799
+99 23 39.560081
+99 24 48.507731
+99 25 38.897301
+99 26 47.853944
+99 27 72.422372
+99 28 71.063352
+99 29 69.570109
+99 30 66.219333
+99 31 65.787537
+99 32 64.288413
+99 33 64.845971
+99 34 64.884513
+99 35 61.400326
+99 36 52.630789
+99 37 51.088159
+99 38 49.203658
+99 39 45.607017
+99 40 44.045431
+99 41 47.381431
+99 42 39.408121
+99 43 40.311289
+99 44 43.931765
+99 45 41.725292
+99 46 30.594117
+99 47 29.120440
+99 48 25.000000
+99 49 49.648766
+99 50 43.081318
+99 51 49.040799
+99 52 43.185646
+99 53 22.022716
+99 54 6.324555
+99 55 30.083218
+99 56 8.944272
+99 57 29.410882
+99 58 27.294688
+99 59 43.416587
+99 60 35.777088
+99 61 13.601471
+99 62 23.021729
+99 63 42.544095
+99 64 50.447993
+99 65 29.068884
+99 66 15.000000
+99 67 21.213203
+99 68 39.293765
+99 69 16.124515
+99 70 5.000000
+99 71 19.235384
+99 72 39.115214
+99 73 39.217343
+99 74 25.298221
+99 75 32.557641
+99 76 51.478151
+99 77 52.497619
+99 78 49.091751
+99 79 18.439089
+99 80 25.612497
+99 81 21.587033
+99 82 23.769729
+99 83 9.055385
+99 84 23.706539
+99 85 38.600518
+99 86 47.010637
+99 87 28.442925
+99 88 31.304952
+99 89 6.324555
+99 90 62.369865
+99 91 12.083046
+99 92 25.079872
+99 93 28.460499
+99 94 35.000000
+99 95 31.256999
+99 96 33.541020
+99 97 29.068884
+99 98 40.496913
+99 100 17.000000
+99 101 15.811388
+100 1 20.518285
+100 2 50.009999
+100 3 40.199502
+100 4 50.159745
+100 5 45.398238
+100 6 50.358713
+100 7 40.792156
+100 8 41.484937
+100 9 46.324939
+100 10 16.000000
+100 11 16.763055
+100 12 18.681542
+100 13 20.591260
+100 14 21.000000
+100 15 23.259407
+100 16 24.515301
+100 17 26.476405
+100 18 27.856777
+100 19 34.985711
+100 20 29.681644
+100 21 25.612497
+100 22 33.105891
+100 23 24.413111
+100 24 32.310989
+100 25 23.323808
+100 26 31.320920
+100 27 69.180922
+100 28 69.000000
+100 29 66.189123
+100 30 64.000000
+100 31 62.201286
+100 32 62.000000
+100 33 61.204575
+100 34 59.841457
+100 35 59.000000
+100 36 64.660653
+100 37 63.411355
+100 38 61.073726
+100 39 57.628118
+100 40 56.400355
+100 41 60.464866
+100 42 51.224994
+100 43 53.535035
+100 44 57.801384
+100 45 55.226805
+100 46 47.381431
+100 47 45.705580
+100 48 26.000000
+100 49 34.000000
+100 50 28.017851
+100 51 46.000000
+100 52 32.649655
+100 53 5.099020
+100 54 16.155494
+100 55 38.288379
+100 56 25.317978
+100 57 24.000000
+100 58 10.770330
+100 59 27.313001
+100 60 21.931712
+100 61 27.313001
+100 62 35.510562
+100 63 39.000000
+100 64 41.785165
+100 65 19.646883
+100 66 10.295630
+100 67 15.132746
+100 68 38.639358
+100 69 28.653098
+100 70 17.720045
+100 71 35.171011
+100 72 43.829214
+100 73 47.634021
+100 74 34.655447
+100 75 16.155494
+100 76 36.619667
+100 77 41.048752
+100 78 32.140317
+100 79 27.658633
+100 80 38.587563
+100 81 24.186773
+100 82 32.526912
+100 83 8.062258
+100 84 11.704700
+100 85 31.575307
+100 86 38.897301
+100 87 12.083046
+100 88 17.804494
+100 89 23.086793
+100 90 50.803543
+100 91 16.278821
+100 92 24.041631
+100 93 28.160256
+100 94 38.910153
+100 95 33.615473
+100 96 30.066593
+100 97 34.669872
+100 98 27.802878
+100 99 17.000000
+100 101 32.388269
+101 1 19.235384
+101 2 18.973666
+101 3 12.041595
+101 4 20.124612
+101 5 17.029386
+101 6 21.095023
+101 7 15.264338
+101 8 17.888544
+101 9 20.615528
+101 10 38.275318
+101 11 34.205263
+101 12 35.468296
+101 13 31.827661
+101 14 41.231056
+101 15 34.058773
+101 16 39.623226
+101 17 41.109610
+101 18 38.013156
+101 19 63.348244
+101 20 58.051701
+101 21 53.150729
+101 22 62.649820
+101 23 52.773099
+101 24 62.393910
+101 25 52.469038
+101 26 62.128898
+101 27 73.925638
+101 28 71.554175
+101 29 71.344236
+101 30 67.119297
+101 31 67.955868
+101 32 65.368188
+101 33 67.119297
+101 34 68.410526
+101 35 62.769419
+101 36 40.249224
+101 37 38.470768
+101 38 37.161808
+101 39 33.615473
+101 40 31.780497
+101 41 34.132096
+101 42 28.160256
+101 43 27.294688
+101 44 30.000000
+101 45 28.301943
+101 46 18.601075
+101 47 18.384776
+101 48 36.400549
+101 49 62.968246
+101 50 56.089215
+101 51 52.009614
+101 52 52.773099
+101 53 37.483330
+101 54 20.248457
+101 55 25.000000
+101 56 7.071068
+101 57 37.215588
+101 58 42.011903
+101 59 59.203040
+101 60 51.478151
+101 61 17.464249
+101 62 14.142136
+101 63 46.690470
+101 64 58.008620
+101 65 39.560081
+101 66 27.294688
+101 67 31.622777
+101 68 41.400483
+101 69 11.401754
+101 70 15.000000
+101 71 4.472136
+101 72 36.055513
+101 73 32.062439
+101 74 29.832868
+101 75 48.270074
+101 76 67.230945
+101 77 62.177166
+101 78 64.498062
+101 79 25.495098
+101 80 25.019992
+101 81 25.612497
+101 82 20.124612
+101 83 24.331050
+101 84 36.496575
+101 85 46.043458
+101 86 54.405882
+101 87 44.147480
+101 88 47.010637
+101 89 11.401754
+101 90 71.693793
+101 91 20.880613
+101 92 30.805844
+101 93 32.557641
+101 94 33.541020
+101 95 32.202484
+101 96 39.051248
+101 97 27.294688
+101 98 55.946403
+101 99 15.811388
+101 100 32.388269
diff --git a/src/vrp_basic/test/Orders.txt b/src/vrp_basic/test/Orders.txt
new file mode 100644
index 0000000..f4b621a
--- /dev/null
+++ b/src/vrp_basic/test/Orders.txt
@@ -0,0 +1,102 @@
+ CUST_NO. XCOORD. YCOORD. DEMAND READY_TIME DUE_Time SERVICE_TIME
+ 1 40.00 50.00 0.00 0.00 240.00 0.00
+ 2 25.00 85.00 20.00 145.00 175.00 10.00
+ 3 22.00 75.00 30.00 50.00 80.00 10.00
+ 4 22.00 85.00 10.00 109.00 139.00 10.00
+ 5 20.00 80.00 40.00 141.00 171.00 10.00
+ 6 20.00 85.00 20.00 41.00 71.00 10.00
+ 7 18.00 75.00 20.00 95.00 125.00 10.00
+ 8 15.00 75.00 20.00 79.00 109.00 10.00
+ 9 15.00 80.00 10.00 91.00 121.00 10.00
+ 10 10.00 35.00 20.00 91.00 121.00 10.00
+ 11 10.00 40.00 30.00 119.00 149.00 10.00
+ 12 8.00 40.00 40.00 59.00 89.00 10.00
+ 13 8.00 45.00 20.00 64.00 94.00 10.00
+ 14 5.00 35.00 10.00 142.00 172.00 10.00
+ 15 5.00 45.00 10.00 35.00 65.00 10.00
+ 16 2.00 40.00 20.00 58.00 88.00 10.00
+ 17 0.00 40.00 20.00 72.00 102.00 10.00
+ 18 0.00 45.00 20.00 149.00 179.00 10.00
+ 19 44.00 5.00 20.00 87.00 117.00 10.00
+ 20 42.00 10.00 40.00 72.00 102.00 10.00
+ 21 42.00 15.00 10.00 122.00 152.00 10.00
+ 22 40.00 5.00 10.00 67.00 97.00 10.00
+ 23 40.00 15.00 40.00 92.00 122.00 10.00
+ 24 38.00 5.00 30.00 65.00 95.00 10.00
+ 25 38.00 15.00 10.00 148.00 178.00 10.00
+ 26 35.00 5.00 20.00 154.00 184.00 10.00
+ 27 95.00 30.00 30.00 115.00 145.00 10.00
+ 28 95.00 35.00 20.00 62.00 92.00 10.00
+ 29 92.00 30.00 10.00 62.00 92.00 10.00
+ 30 90.00 35.00 10.00 67.00 97.00 10.00
+ 31 88.00 30.00 10.00 74.00 104.00 10.00
+ 32 88.00 35.00 20.00 61.00 91.00 10.00
+ 33 87.00 30.00 10.00 131.00 161.00 10.00
+ 34 85.00 25.00 10.00 51.00 81.00 10.00
+ 35 85.00 35.00 30.00 111.00 141.00 10.00
+ 36 67.00 85.00 20.00 139.00 169.00 10.00
+ 37 65.00 85.00 40.00 43.00 73.00 10.00
+ 38 65.00 82.00 10.00 124.00 154.00 10.00
+ 39 62.00 80.00 30.00 75.00 105.00 10.00
+ 40 60.00 80.00 10.00 37.00 67.00 10.00
+ 41 60.00 85.00 30.00 85.00 115.00 10.00
+ 42 58.00 75.00 20.00 92.00 122.00 10.00
+ 43 55.00 80.00 10.00 33.00 63.00 10.00
+ 44 55.00 85.00 20.00 128.00 158.00 10.00
+ 45 55.00 82.00 10.00 64.00 94.00 10.00
+ 46 20.00 82.00 10.00 37.00 67.00 10.00
+ 47 18.00 80.00 10.00 113.00 143.00 10.00
+ 48 2.00 45.00 10.00 45.00 75.00 10.00
+ 49 42.00 5.00 10.00 151.00 181.00 10.00
+ 50 42.00 12.00 10.00 104.00 134.00 10.00
+ 51 72.00 35.00 30.00 116.00 146.00 10.00
+ 52 55.00 20.00 19.00 83.00 113.00 10.00
+ 53 25.00 30.00 3.00 52.00 82.00 10.00
+ 54 20.00 50.00 5.00 91.00 121.00 10.00
+ 55 55.00 60.00 16.00 139.00 169.00 10.00
+ 56 30.00 60.00 16.00 140.00 170.00 10.00
+ 57 50.00 35.00 19.00 130.00 160.00 10.00
+ 58 30.00 25.00 23.00 96.00 126.00 10.00
+ 59 15.00 10.00 20.00 152.00 182.00 10.00
+ 60 10.00 20.00 19.00 42.00 72.00 10.00
+ 61 15.00 60.00 17.00 155.00 185.00 10.00
+ 62 45.00 65.00 9.00 66.00 96.00 10.00
+ 63 65.00 35.00 3.00 52.00 82.00 10.00
+ 64 65.00 20.00 6.00 39.00 69.00 10.00
+ 65 45.00 30.00 17.00 53.00 83.00 10.00
+ 66 35.00 40.00 16.00 11.00 41.00 10.00
+ 67 41.00 37.00 16.00 133.00 163.00 10.00
+ 68 64.00 42.00 9.00 70.00 100.00 10.00
+ 69 40.00 60.00 21.00 144.00 174.00 10.00
+ 70 31.00 52.00 27.00 41.00 71.00 10.00
+ 71 35.00 69.00 23.00 180.00 210.00 10.00
+ 72 65.00 55.00 14.00 65.00 95.00 10.00
+ 73 63.00 65.00 8.00 30.00 60.00 10.00
+ 74 2.00 60.00 5.00 77.00 107.00 10.00
+ 75 20.00 20.00 8.00 141.00 171.00 10.00
+ 76 5.00 5.00 16.00 74.00 104.00 10.00
+ 77 60.00 12.00 31.00 75.00 105.00 10.00
+ 78 23.00 3.00 7.00 150.00 180.00 10.00
+ 79 8.00 56.00 27.00 90.00 120.00 10.00
+ 80 6.00 68.00 30.00 89.00 119.00 10.00
+ 81 47.00 47.00 13.00 192.00 222.00 10.00
+ 82 49.00 58.00 10.00 86.00 116.00 10.00
+ 83 27.00 43.00 9.00 42.00 72.00 10.00
+ 84 37.00 31.00 14.00 35.00 65.00 10.00
+ 85 57.00 29.00 18.00 96.00 126.00 10.00
+ 86 63.00 23.00 2.00 87.00 117.00 10.00
+ 87 21.00 24.00 28.00 87.00 117.00 10.00
+ 88 12.00 24.00 13.00 90.00 120.00 10.00
+ 89 24.00 58.00 19.00 67.00 97.00 10.00
+ 90 67.00 5.00 25.00 144.00 174.00 10.00
+ 91 37.00 47.00 6.00 86.00 116.00 10.00
+ 92 49.00 42.00 13.00 167.00 197.00 10.00
+ 93 53.00 43.00 14.00 14.00 44.00 10.00
+ 94 61.00 52.00 3.00 178.00 208.00 10.00
+ 95 57.00 48.00 23.00 95.00 125.00 10.00
+ 96 56.00 37.00 6.00 34.00 64.00 10.00
+ 97 55.00 54.00 26.00 132.00 162.00 10.00
+ 98 4.00 18.00 35.00 120.00 150.00 10.00
+ 99 26.00 52.00 9.00 46.00 76.00 10.00
+ 100 26.00 35.00 15.00 77.00 107.00 10.00
+ 101 31.00 67.00 3.00 180.00 210.00 10.00
\ No newline at end of file
diff --git a/src/vrp_basic/test/VRP-any-00.data b/src/vrp_basic/test/VRP-any-00.data
new file mode 100644
index 0000000..15e1b0b
--- /dev/null
+++ b/src/vrp_basic/test/VRP-any-00.data
@@ -0,0 +1,10259 @@
+
+drop table if exists vrp_orders cascade;
+create table vrp_orders (
+ id integer not null primary key,
+ order_unit integer,
+ open_time integer,
+ close_time integer,
+ service_time integer,
+ x float8,
+ y float8
+
+);
+
+copy vrp_orders (id, x, y, order_unit, open_time, close_time, service_time) from stdin;
+1 40.000000 50.000000 0 0 240 0
+2 25.000000 85.000000 20 145 175 10
+3 22.000000 75.000000 30 50 80 10
+4 22.000000 85.000000 10 109 139 10
+5 20.000000 80.000000 40 141 171 10
+6 20.000000 85.000000 20 41 71 10
+7 18.000000 75.000000 20 95 125 10
+8 15.000000 75.000000 20 79 109 10
+9 15.000000 80.000000 10 91 121 10
+10 10.000000 35.000000 20 91 121 10
+11 10.000000 40.000000 30 119 149 10
+12 8.000000 40.000000 40 59 89 10
+13 8.000000 45.000000 20 64 94 10
+14 5.000000 35.000000 10 142 172 10
+15 5.000000 45.000000 10 35 65 10
+16 2.000000 40.000000 20 58 88 10
+17 0.000000 40.000000 20 72 102 10
+18 0.000000 45.000000 20 149 179 10
+19 44.000000 5.000000 20 87 117 10
+20 42.000000 10.000000 40 72 102 10
+21 42.000000 15.000000 10 122 152 10
+22 40.000000 5.000000 10 67 97 10
+23 40.000000 15.000000 40 92 122 10
+24 38.000000 5.000000 30 65 95 10
+25 38.000000 15.000000 10 148 178 10
+26 35.000000 5.000000 20 154 184 10
+27 95.000000 30.000000 30 115 145 10
+28 95.000000 35.000000 20 62 92 10
+29 92.000000 30.000000 10 62 92 10
+30 90.000000 35.000000 10 67 97 10
+31 88.000000 30.000000 10 74 104 10
+32 88.000000 35.000000 20 61 91 10
+33 87.000000 30.000000 10 131 161 10
+34 85.000000 25.000000 10 51 81 10
+35 85.000000 35.000000 30 111 141 10
+36 67.000000 85.000000 20 139 169 10
+37 65.000000 85.000000 40 43 73 10
+38 65.000000 82.000000 10 124 154 10
+39 62.000000 80.000000 30 75 105 10
+40 60.000000 80.000000 10 37 67 10
+41 60.000000 85.000000 30 85 115 10
+42 58.000000 75.000000 20 92 122 10
+43 55.000000 80.000000 10 33 63 10
+44 55.000000 85.000000 20 128 158 10
+45 55.000000 82.000000 10 64 94 10
+46 20.000000 82.000000 10 37 67 10
+47 18.000000 80.000000 10 113 143 10
+48 2.000000 45.000000 10 45 75 10
+49 42.000000 5.000000 10 151 181 10
+50 42.000000 12.000000 10 104 134 10
+51 72.000000 35.000000 30 116 146 10
+52 55.000000 20.000000 19 83 113 10
+53 25.000000 30.000000 3 52 82 10
+54 20.000000 50.000000 5 91 121 10
+55 55.000000 60.000000 16 139 169 10
+56 30.000000 60.000000 16 140 170 10
+57 50.000000 35.000000 19 130 160 10
+58 30.000000 25.000000 23 96 126 10
+59 15.000000 10.000000 20 152 182 10
+60 10.000000 20.000000 19 42 72 10
+61 15.000000 60.000000 17 155 185 10
+62 45.000000 65.000000 9 66 96 10
+63 65.000000 35.000000 3 52 82 10
+64 65.000000 20.000000 6 39 69 10
+65 45.000000 30.000000 17 53 83 10
+66 35.000000 40.000000 16 11 41 10
+67 41.000000 37.000000 16 133 163 10
+68 64.000000 42.000000 9 70 100 10
+69 40.000000 60.000000 21 144 174 10
+70 31.000000 52.000000 27 41 71 10
+71 35.000000 69.000000 23 180 210 10
+72 65.000000 55.000000 14 65 95 10
+73 63.000000 65.000000 8 30 60 10
+74 2.000000 60.000000 5 77 107 10
+75 20.000000 20.000000 8 141 171 10
+76 5.000000 5.000000 16 74 104 10
+77 60.000000 12.000000 31 75 105 10
+78 23.000000 3.000000 7 150 180 10
+79 8.000000 56.000000 27 90 120 10
+80 6.000000 68.000000 30 89 119 10
+81 47.000000 47.000000 13 192 222 10
+82 49.000000 58.000000 10 86 116 10
+83 27.000000 43.000000 9 42 72 10
+84 37.000000 31.000000 14 35 65 10
+85 57.000000 29.000000 18 96 126 10
+86 63.000000 23.000000 2 87 117 10
+87 21.000000 24.000000 28 87 117 10
+88 12.000000 24.000000 13 90 120 10
+89 24.000000 58.000000 19 67 97 10
+90 67.000000 5.000000 25 144 174 10
+91 37.000000 47.000000 6 86 116 10
+92 49.000000 42.000000 13 167 197 10
+93 53.000000 43.000000 14 14 44 10
+94 61.000000 52.000000 3 178 208 10
+95 57.000000 48.000000 23 95 125 10
+96 56.000000 37.000000 6 34 64 10
+97 55.000000 54.000000 26 132 162 10
+98 4.000000 18.000000 35 120 150 10
+99 26.000000 52.000000 9 46 76 10
+100 26.000000 35.000000 15 77 107 10
+101 31.000000 67.000000 3 180 210 10
+\.
+
+drop table if exists vrp_vehicles cascade;
+create table vrp_vehicles (
+ vehicle_id integer not null primary key,
+ capacity integer,
+ case_no integer
+);
+
+copy vrp_vehicles (vehicle_id, capacity, case_no) from stdin;
+1 200 5
+2 200 5
+3 200 5
+4 200 5
+5 200 5
+6 200 5
+7 200 5
+8 200 5
+9 200 5
+10 200 5
+11 200 5
+12 200 5
+13 200 5
+14 200 5
+15 200 5
+16 200 5
+17 200 5
+18 200 5
+19 200 5
+20 200 5
+\.
+
+drop table if exists vrp_distance cascade;
+create table vrp_distance (
+ src_id integer,
+ dest_id integer,
+ cost Float8,
+ distance Float8,
+ traveltime Float8
+);
+
+copy vrp_distance (src_id, dest_id, cost, distance, traveltime) from stdin;
+1 2 38.078866 38.078866 38.078866
+1 3 30.805844 30.805844 30.805844
+1 4 39.357337 39.357337 39.357337
+1 5 36.055513 36.055513 36.055513
+1 6 40.311289 40.311289 40.311289
+1 7 33.301652 33.301652 33.301652
+1 8 35.355339 35.355339 35.355339
+1 9 39.051248 39.051248 39.051248
+1 10 33.541020 33.541020 33.541020
+1 11 31.622777 31.622777 31.622777
+1 12 33.526109 33.526109 33.526109
+1 13 32.388269 32.388269 32.388269
+1 14 38.078866 38.078866 38.078866
+1 15 35.355339 35.355339 35.355339
+1 16 39.293765 39.293765 39.293765
+1 17 41.231056 41.231056 41.231056
+1 18 40.311289 40.311289 40.311289
+1 19 45.177428 45.177428 45.177428
+1 20 40.049969 40.049969 40.049969
+1 21 35.057096 35.057096 35.057096
+1 22 45.000000 45.000000 45.000000
+1 23 35.000000 35.000000 35.000000
+1 24 45.044423 45.044423 45.044423
+1 25 35.057096 35.057096 35.057096
+1 26 45.276926 45.276926 45.276926
+1 27 58.523500 58.523500 58.523500
+1 28 57.008771 57.008771 57.008771
+1 29 55.713553 55.713553 55.713553
+1 30 52.201533 52.201533 52.201533
+1 31 52.000000 52.000000 52.000000
+1 32 50.289164 50.289164 50.289164
+1 33 51.078371 51.078371 51.078371
+1 34 51.478151 51.478151 51.478151
+1 35 47.434165 47.434165 47.434165
+1 36 44.204072 44.204072 44.204072
+1 37 43.011626 43.011626 43.011626
+1 38 40.607881 40.607881 40.607881
+1 39 37.202150 37.202150 37.202150
+1 40 36.055513 36.055513 36.055513
+1 41 40.311289 40.311289 40.311289
+1 42 30.805844 30.805844 30.805844
+1 43 33.541020 33.541020 33.541020
+1 44 38.078866 38.078866 38.078866
+1 45 35.341194 35.341194 35.341194
+1 46 37.735925 37.735925 37.735925
+1 47 37.202150 37.202150 37.202150
+1 48 38.327536 38.327536 38.327536
+1 49 45.044423 45.044423 45.044423
+1 50 38.052595 38.052595 38.052595
+1 51 35.341194 35.341194 35.341194
+1 52 33.541020 33.541020 33.541020
+1 53 25.000000 25.000000 25.000000
+1 54 20.000000 20.000000 20.000000
+1 55 18.027756 18.027756 18.027756
+1 56 14.142136 14.142136 14.142136
+1 57 18.027756 18.027756 18.027756
+1 58 26.925824 26.925824 26.925824
+1 59 47.169906 47.169906 47.169906
+1 60 42.426407 42.426407 42.426407
+1 61 26.925824 26.925824 26.925824
+1 62 15.811388 15.811388 15.811388
+1 63 29.154759 29.154759 29.154759
+1 64 39.051248 39.051248 39.051248
+1 65 20.615528 20.615528 20.615528
+1 66 11.180340 11.180340 11.180340
+1 67 13.038405 13.038405 13.038405
+1 68 25.298221 25.298221 25.298221
+1 69 10.000000 10.000000 10.000000
+1 70 9.219544 9.219544 9.219544
+1 71 19.646883 19.646883 19.646883
+1 72 25.495098 25.495098 25.495098
+1 73 27.459060 27.459060 27.459060
+1 74 39.293765 39.293765 39.293765
+1 75 36.055513 36.055513 36.055513
+1 76 57.008771 57.008771 57.008771
+1 77 42.941821 42.941821 42.941821
+1 78 49.979996 49.979996 49.979996
+1 79 32.557641 32.557641 32.557641
+1 80 38.470768 38.470768 38.470768
+1 81 7.615773 7.615773 7.615773
+1 82 12.041595 12.041595 12.041595
+1 83 14.764823 14.764823 14.764823
+1 84 19.235384 19.235384 19.235384
+1 85 27.018512 27.018512 27.018512
+1 86 35.468296 35.468296 35.468296
+1 87 32.202484 32.202484 32.202484
+1 88 38.209946 38.209946 38.209946
+1 89 17.888544 17.888544 17.888544
+1 90 52.478567 52.478567 52.478567
+1 91 4.242641 4.242641 4.242641
+1 92 12.041595 12.041595 12.041595
+1 93 14.764823 14.764823 14.764823
+1 94 21.095023 21.095023 21.095023
+1 95 17.117243 17.117243 17.117243
+1 96 20.615528 20.615528 20.615528
+1 97 15.524175 15.524175 15.524175
+1 98 48.166378 48.166378 48.166378
+1 99 14.142136 14.142136 14.142136
+1 100 20.518285 20.518285 20.518285
+1 101 19.235384 19.235384 19.235384
+2 1 38.078866 38.078866 38.078866
+2 3 10.440307 10.440307 10.440307
+2 4 3.000000 3.000000 3.000000
+2 5 7.071068 7.071068 7.071068
+2 6 5.000000 5.000000 5.000000
+2 7 12.206556 12.206556 12.206556
+2 8 14.142136 14.142136 14.142136
+2 9 11.180340 11.180340 11.180340
+2 10 52.201533 52.201533 52.201533
+2 11 47.434165 47.434165 47.434165
+2 12 48.104054 48.104054 48.104054
+2 13 43.462628 43.462628 43.462628
+2 14 53.851648 53.851648 53.851648
+2 15 44.721360 44.721360 44.721360
+2 16 50.537115 50.537115 50.537115
+2 17 51.478151 51.478151 51.478151
+2 18 47.169906 47.169906 47.169906
+2 19 82.225300 82.225300 82.225300
+2 20 76.902536 76.902536 76.902536
+2 21 72.034714 72.034714 72.034714
+2 22 81.394103 81.394103 81.394103
+2 23 71.589105 71.589105 71.589105
+2 24 81.049368 81.049368 81.049368
+2 25 71.196910 71.196910 71.196910
+2 26 80.622577 80.622577 80.622577
+2 27 89.022469 89.022469 89.022469
+2 28 86.023253 86.023253 86.023253
+2 29 86.683332 86.683332 86.683332
+2 30 82.006097 82.006097 82.006097
+2 31 83.630138 83.630138 83.630138
+2 32 80.430094 80.430094 80.430094
+2 33 82.879430 82.879430 82.879430
+2 34 84.852814 84.852814 84.852814
+2 35 78.102497 78.102497 78.102497
+2 36 42.000000 42.000000 42.000000
+2 37 40.000000 40.000000 40.000000
+2 38 40.112342 40.112342 40.112342
+2 39 37.336309 37.336309 37.336309
+2 40 35.355339 35.355339 35.355339
+2 41 35.000000 35.000000 35.000000
+2 42 34.481879 34.481879 34.481879
+2 43 30.413813 30.413813 30.413813
+2 44 30.000000 30.000000 30.000000
+2 45 30.149627 30.149627 30.149627
+2 46 5.830952 5.830952 5.830952
+2 47 8.602325 8.602325 8.602325
+2 48 46.141088 46.141088 46.141088
+2 49 81.786307 81.786307 81.786307
+2 50 74.953319 74.953319 74.953319
+2 51 68.622154 68.622154 68.622154
+2 52 71.589105 71.589105 71.589105
+2 53 55.000000 55.000000 55.000000
+2 54 35.355339 35.355339 35.355339
+2 55 39.051248 39.051248 39.051248
+2 56 25.495098 25.495098 25.495098
+2 57 55.901699 55.901699 55.901699
+2 58 60.207973 60.207973 60.207973
+2 59 75.663730 75.663730 75.663730
+2 60 66.708320 66.708320 66.708320
+2 61 26.925824 26.925824 26.925824
+2 62 28.284271 28.284271 28.284271
+2 63 64.031242 64.031242 64.031242
+2 64 76.321688 76.321688 76.321688
+2 65 58.523500 58.523500 58.523500
+2 66 46.097722 46.097722 46.097722
+2 67 50.596443 50.596443 50.596443
+2 68 58.051701 58.051701 58.051701
+2 69 29.154759 29.154759 29.154759
+2 70 33.541020 33.541020 33.541020
+2 71 18.867962 18.867962 18.867962
+2 72 50.000000 50.000000 50.000000
+2 73 42.941821 42.941821 42.941821
+2 74 33.970576 33.970576 33.970576
+2 75 65.192024 65.192024 65.192024
+2 76 82.462113 82.462113 82.462113
+2 77 80.956779 80.956779 80.956779
+2 78 82.024387 82.024387 82.024387
+2 79 33.615473 33.615473 33.615473
+2 80 25.495098 25.495098 25.495098
+2 81 43.908997 43.908997 43.908997
+2 82 36.124784 36.124784 36.124784
+2 83 42.047592 42.047592 42.047592
+2 84 55.317267 55.317267 55.317267
+2 85 64.498062 64.498062 64.498062
+2 86 72.718636 72.718636 72.718636
+2 87 61.131007 61.131007 61.131007
+2 88 62.369865 62.369865 62.369865
+2 89 27.018512 27.018512 27.018512
+2 90 90.354856 90.354856 90.354856
+2 91 39.849718 39.849718 39.849718
+2 92 49.244289 49.244289 49.244289
+2 93 50.477718 50.477718 50.477718
+2 94 48.836462 48.836462 48.836462
+2 95 48.918299 48.918299 48.918299
+2 96 57.140179 57.140179 57.140179
+2 97 43.139309 43.139309 43.139309
+2 98 70.213959 70.213959 70.213959
+2 99 33.015148 33.015148 33.015148
+2 100 50.009999 50.009999 50.009999
+2 101 18.973666 18.973666 18.973666
+3 1 30.805844 30.805844 30.805844
+3 2 10.440307 10.440307 10.440307
+3 4 10.000000 10.000000 10.000000
+3 5 5.385165 5.385165 5.385165
+3 6 10.198039 10.198039 10.198039
+3 7 4.000000 4.000000 4.000000
+3 8 7.000000 7.000000 7.000000
+3 9 8.602325 8.602325 8.602325
+3 10 41.761226 41.761226 41.761226
+3 11 37.000000 37.000000 37.000000
+3 12 37.696154 37.696154 37.696154
+3 13 33.105891 33.105891 33.105891
+3 14 43.462628 43.462628 43.462628
+3 15 34.481879 34.481879 34.481879
+3 16 40.311289 40.311289 40.311289
+3 17 41.340053 41.340053 41.340053
+3 18 37.202150 37.202150 37.202150
+3 19 73.375745 73.375745 73.375745
+3 20 68.007353 68.007353 68.007353
+3 21 63.245553 63.245553 63.245553
+3 22 72.277244 72.277244 72.277244
+3 23 62.641839 62.641839 62.641839
+3 24 71.805292 71.805292 71.805292
+3 25 62.096699 62.096699 62.096699
+3 26 71.196910 71.196910 71.196910
+3 27 85.755466 85.755466 85.755466
+3 28 83.240615 83.240615 83.240615
+3 29 83.216585 83.216585 83.216585
+3 30 78.892332 78.892332 78.892332
+3 31 79.881162 79.881162 79.881162
+3 32 77.175126 77.175126 77.175126
+3 33 79.056942 79.056942 79.056942
+3 34 80.430094 80.430094 80.430094
+3 35 74.625733 74.625733 74.625733
+3 36 46.097722 46.097722 46.097722
+3 37 44.147480 44.147480 44.147480
+3 38 43.566042 43.566042 43.566042
+3 39 40.311289 40.311289 40.311289
+3 40 38.327536 38.327536 38.327536
+3 41 39.293765 39.293765 39.293765
+3 42 36.000000 36.000000 36.000000
+3 43 33.376639 33.376639 33.376639
+3 44 34.481879 34.481879 34.481879
+3 45 33.734256 33.734256 33.734256
+3 46 7.280110 7.280110 7.280110
+3 47 6.403124 6.403124 6.403124
+3 48 36.055513 36.055513 36.055513
+3 49 72.801099 72.801099 72.801099
+3 50 66.098411 66.098411 66.098411
+3 51 64.031242 64.031242 64.031242
+3 52 64.140471 64.140471 64.140471
+3 53 45.099889 45.099889 45.099889
+3 54 25.079872 25.079872 25.079872
+3 55 36.249138 36.249138 36.249138
+3 56 17.000000 17.000000 17.000000
+3 57 48.826222 48.826222 48.826222
+3 58 50.635956 50.635956 50.635956
+3 59 65.375837 65.375837 65.375837
+3 60 56.293872 56.293872 56.293872
+3 61 16.552945 16.552945 16.552945
+3 62 25.079872 25.079872 25.079872
+3 63 58.728187 58.728187 58.728187
+3 64 69.814039 69.814039 69.814039
+3 65 50.537115 50.537115 50.537115
+3 66 37.336309 37.336309 37.336309
+3 67 42.485292 42.485292 42.485292
+3 68 53.413481 53.413481 53.413481
+3 69 23.430749 23.430749 23.430749
+3 70 24.698178 24.698178 24.698178
+3 71 14.317821 14.317821 14.317821
+3 72 47.423623 47.423623 47.423623
+3 73 42.201896 42.201896 42.201896
+3 74 25.000000 25.000000 25.000000
+3 75 55.036352 55.036352 55.036352
+3 76 72.034714 72.034714 72.034714
+3 77 73.573093 73.573093 73.573093
+3 78 72.006944 72.006944 72.006944
+3 79 23.600847 23.600847 23.600847
+3 80 17.464249 17.464249 17.464249
+3 81 37.536649 37.536649 37.536649
+3 82 31.906112 31.906112 31.906112
+3 83 32.388269 32.388269 32.388269
+3 84 46.486557 46.486557 46.486557
+3 85 57.801384 57.801384 57.801384
+3 86 66.219333 66.219333 66.219333
+3 87 51.009803 51.009803 51.009803
+3 88 51.971146 51.971146 51.971146
+3 89 17.117243 17.117243 17.117243
+3 90 83.216585 83.216585 83.216585
+3 91 31.764760 31.764760 31.764760
+3 92 42.638011 42.638011 42.638011
+3 93 44.553339 44.553339 44.553339
+3 94 45.276926 45.276926 45.276926
+3 95 44.204072 44.204072 44.204072
+3 96 50.990195 50.990195 50.990195
+3 97 39.115214 39.115214 39.115214
+3 98 59.774577 59.774577 59.774577
+3 99 23.345235 23.345235 23.345235
+3 100 40.199502 40.199502 40.199502
+3 101 12.041595 12.041595 12.041595
+4 1 39.357337 39.357337 39.357337
+4 2 3.000000 3.000000 3.000000
+4 3 10.000000 10.000000 10.000000
+4 5 5.385165 5.385165 5.385165
+4 6 2.000000 2.000000 2.000000
+4 7 10.770330 10.770330 10.770330
+4 8 12.206556 12.206556 12.206556
+4 9 8.602325 8.602325 8.602325
+4 10 51.419841 51.419841 51.419841
+4 11 46.572524 46.572524 46.572524
+4 12 47.127487 47.127487 47.127487
+4 13 42.379240 42.379240 42.379240
+4 14 52.810984 52.810984 52.810984
+4 15 43.462628 43.462628 43.462628
+4 16 49.244289 49.244289 49.244289
+4 17 50.089919 50.089919 50.089919
+4 18 45.650849 45.650849 45.650849
+4 19 82.969874 82.969874 82.969874
+4 20 77.620873 77.620873 77.620873
+4 21 72.801099 72.801099 72.801099
+4 22 82.000000 82.000000 82.000000
+4 23 72.277244 72.277244 72.277244
+4 24 81.584312 81.584312 81.584312
+4 25 71.805292 71.805292 71.805292
+4 26 81.049368 81.049368 81.049368
+4 27 91.400219 91.400219 91.400219
+4 28 88.481637 88.481637 88.481637
+4 29 89.022469 89.022469 89.022469
+4 30 84.403791 84.403791 84.403791
+4 31 85.912746 85.912746 85.912746
+4 32 82.800966 82.800966 82.800966
+4 33 85.146932 85.146932 85.146932
+4 34 87.000000 87.000000 87.000000
+4 35 80.430094 80.430094 80.430094
+4 36 45.000000 45.000000 45.000000
+4 37 43.000000 43.000000 43.000000
+4 38 43.104524 43.104524 43.104524
+4 39 40.311289 40.311289 40.311289
+4 40 38.327536 38.327536 38.327536
+4 41 38.000000 38.000000 38.000000
+4 42 37.363083 37.363083 37.363083
+4 43 33.376639 33.376639 33.376639
+4 44 33.000000 33.000000 33.000000
+4 45 33.136083 33.136083 33.136083
+4 46 3.605551 3.605551 3.605551
+4 47 6.403124 6.403124 6.403124
+4 48 44.721360 44.721360 44.721360
+4 49 82.462113 82.462113 82.462113
+4 50 75.690158 75.690158 75.690158
+4 51 70.710678 70.710678 70.710678
+4 52 72.897188 72.897188 72.897188
+4 53 55.081757 55.081757 55.081757
+4 54 35.057096 35.057096 35.057096
+4 55 41.400483 41.400483 41.400483
+4 56 26.248809 26.248809 26.248809
+4 57 57.306195 57.306195 57.306195
+4 58 60.530984 60.530984 60.530984
+4 59 75.325958 75.325958 75.325958
+4 60 66.098411 66.098411 66.098411
+4 61 25.961510 25.961510 25.961510
+4 62 30.479501 30.479501 30.479501
+4 63 65.946948 65.946948 65.946948
+4 64 77.935871 77.935871 77.935871
+4 65 59.615434 59.615434 59.615434
+4 66 46.840154 46.840154 46.840154
+4 67 51.623638 51.623638 51.623638
+4 68 60.108236 60.108236 60.108236
+4 69 30.805844 30.805844 30.805844
+4 70 34.205263 34.205263 34.205263
+4 71 20.615528 20.615528 20.615528
+4 72 52.430907 52.430907 52.430907
+4 73 45.617979 45.617979 45.617979
+4 74 32.015621 32.015621 32.015621
+4 75 65.030762 65.030762 65.030762
+4 76 81.786307 81.786307 81.786307
+4 77 82.298238 82.298238 82.298238
+4 78 82.006097 82.006097 82.006097
+4 79 32.202484 32.202484 32.202484
+4 80 23.345235 23.345235 23.345235
+4 81 45.486262 45.486262 45.486262
+4 82 38.183766 38.183766 38.183766
+4 83 42.296572 42.296572 42.296572
+4 84 56.044625 56.044625 56.044625
+4 85 66.037868 66.037868 66.037868
+4 86 74.330344 74.330344 74.330344
+4 87 61.008196 61.008196 61.008196
+4 88 61.814238 61.814238 61.814238
+4 89 27.073973 27.073973 27.073973
+4 90 91.787799 91.787799 91.787799
+4 91 40.853396 40.853396 40.853396
+4 92 50.774009 50.774009 50.774009
+4 93 52.201533 52.201533 52.201533
+4 94 51.088159 51.088159 51.088159
+4 95 50.931326 50.931326 50.931326
+4 96 58.821765 58.821765 58.821765
+4 97 45.276926 45.276926 45.276926
+4 98 69.375788 69.375788 69.375788
+4 99 33.241540 33.241540 33.241540
+4 100 50.159745 50.159745 50.159745
+4 101 20.124612 20.124612 20.124612
+5 1 36.055513 36.055513 36.055513
+5 2 7.071068 7.071068 7.071068
+5 3 5.385165 5.385165 5.385165
+5 4 5.385165 5.385165 5.385165
+5 6 5.000000 5.000000 5.000000
+5 7 5.385165 5.385165 5.385165
+5 8 7.071068 7.071068 7.071068
+5 9 5.000000 5.000000 5.000000
+5 10 46.097722 46.097722 46.097722
+5 11 41.231056 41.231056 41.231056
+5 12 41.761226 41.761226 41.761226
+5 13 37.000000 37.000000 37.000000
+5 14 47.434165 47.434165 47.434165
+5 15 38.078866 38.078866 38.078866
+5 16 43.863424 43.863424 43.863424
+5 17 44.721360 44.721360 44.721360
+5 18 40.311289 40.311289 40.311289
+5 19 78.746428 78.746428 78.746428
+5 20 73.375745 73.375745 73.375745
+5 21 68.622154 68.622154 68.622154
+5 22 77.620873 77.620873 77.620873
+5 23 68.007353 68.007353 68.007353
+5 24 77.129761 77.129761 77.129761
+5 25 67.446275 67.446275 67.446275
+5 26 76.485293 76.485293 76.485293
+5 27 90.138782 90.138782 90.138782
+5 28 87.464278 87.464278 87.464278
+5 29 87.658428 87.658428 87.658428
+5 30 83.216585 83.216585 83.216585
+5 31 84.403791 84.403791 84.403791
+5 32 81.541401 81.541401 81.541401
+5 33 83.600239 83.600239 83.600239
+5 34 85.146932 85.146932 85.146932
+5 35 79.056942 79.056942 79.056942
+5 36 47.265209 47.265209 47.265209
+5 37 45.276926 45.276926 45.276926
+5 38 45.044423 45.044423 45.044423
+5 39 42.000000 42.000000 42.000000
+5 40 40.000000 40.000000 40.000000
+5 41 40.311289 40.311289 40.311289
+5 42 38.327536 38.327536 38.327536
+5 43 35.000000 35.000000 35.000000
+5 44 35.355339 35.355339 35.355339
+5 45 35.057096 35.057096 35.057096
+5 46 2.000000 2.000000 2.000000
+5 47 2.000000 2.000000 2.000000
+5 48 39.357337 39.357337 39.357337
+5 49 78.160092 78.160092 78.160092
+5 50 71.470274 71.470274 71.470274
+5 51 68.767725 68.767725 68.767725
+5 52 69.462220 69.462220 69.462220
+5 53 50.249378 50.249378 50.249378
+5 54 30.000000 30.000000 30.000000
+5 55 40.311289 40.311289 40.311289
+5 56 22.360680 22.360680 22.360680
+5 57 54.083269 54.083269 54.083269
+5 58 55.901699 55.901699 55.901699
+5 59 70.178344 70.178344 70.178344
+5 60 60.827625 60.827625 60.827625
+5 61 20.615528 20.615528 20.615528
+5 62 29.154759 29.154759 29.154759
+5 63 63.639610 63.639610 63.639610
+5 64 75.000000 75.000000 75.000000
+5 65 55.901699 55.901699 55.901699
+5 66 42.720019 42.720019 42.720019
+5 67 47.853944 47.853944 47.853944
+5 68 58.137767 58.137767 58.137767
+5 69 28.284271 28.284271 28.284271
+5 70 30.083218 30.083218 30.083218
+5 71 18.601075 18.601075 18.601075
+5 72 51.478151 51.478151 51.478151
+5 73 45.541190 45.541190 45.541190
+5 74 26.907248 26.907248 26.907248
+5 75 60.000000 60.000000 60.000000
+5 76 76.485293 76.485293 76.485293
+5 77 78.892332 78.892332 78.892332
+5 78 77.058419 77.058419 77.058419
+5 79 26.832816 26.832816 26.832816
+5 80 18.439089 18.439089 18.439089
+5 81 42.638011 42.638011 42.638011
+5 82 36.400549 36.400549 36.400549
+5 83 37.656341 37.656341 37.656341
+5 84 51.865210 51.865210 51.865210
+5 85 63.007936 63.007936 63.007936
+5 86 71.400280 71.400280 71.400280
+5 87 56.008928 56.008928 56.008928
+5 88 56.568542 56.568542 56.568542
+5 89 22.360680 22.360680 22.360680
+5 90 88.509886 88.509886 88.509886
+5 91 37.121422 37.121422 37.121422
+5 92 47.801674 47.801674 47.801674
+5 93 49.578221 49.578221 49.578221
+5 94 49.648766 49.648766 49.648766
+5 95 48.918299 48.918299 48.918299
+5 96 56.080300 56.080300 56.080300
+5 97 43.600459 43.600459 43.600459
+5 98 64.031242 64.031242 64.031242
+5 99 28.635642 28.635642 28.635642
+5 100 45.398238 45.398238 45.398238
+5 101 17.029386 17.029386 17.029386
+6 1 40.311289 40.311289 40.311289
+6 2 5.000000 5.000000 5.000000
+6 3 10.198039 10.198039 10.198039
+6 4 2.000000 2.000000 2.000000
+6 5 5.000000 5.000000 5.000000
+6 7 10.198039 10.198039 10.198039
+6 8 11.180340 11.180340 11.180340
+6 9 7.071068 7.071068 7.071068
+6 10 50.990195 50.990195 50.990195
+6 11 46.097722 46.097722 46.097722
+6 12 46.572524 46.572524 46.572524
+6 13 41.761226 41.761226 41.761226
+6 14 52.201533 52.201533 52.201533
+6 15 42.720019 42.720019 42.720019
+6 16 48.466483 48.466483 48.466483
+6 17 49.244289 49.244289 49.244289
+6 18 44.721360 44.721360 44.721360
+6 19 83.522452 83.522452 83.522452
+6 20 78.160092 78.160092 78.160092
+6 21 73.375745 73.375745 73.375745
+6 22 82.462113 82.462113 82.462113
+6 23 72.801099 72.801099 72.801099
+6 24 82.000000 82.000000 82.000000
+6 25 72.277244 72.277244 72.277244
+6 26 81.394103 81.394103 81.394103
+6 27 93.005376 93.005376 93.005376
+6 28 90.138782 90.138782 90.138782
+6 29 90.603532 90.603532 90.603532
+6 30 86.023253 86.023253 86.023253
+6 31 87.458562 87.458562 87.458562
+6 32 84.403791 84.403791 84.403791
+6 33 86.683332 86.683332 86.683332
+6 34 88.459030 88.459030 88.459030
+6 35 82.006097 82.006097 82.006097
+6 36 47.000000 47.000000 47.000000
+6 37 45.000000 45.000000 45.000000
+6 38 45.099889 45.099889 45.099889
+6 39 42.296572 42.296572 42.296572
+6 40 40.311289 40.311289 40.311289
+6 41 40.000000 40.000000 40.000000
+6 42 39.293765 39.293765 39.293765
+6 43 35.355339 35.355339 35.355339
+6 44 35.000000 35.000000 35.000000
+6 45 35.128336 35.128336 35.128336
+6 46 3.000000 3.000000 3.000000
+6 47 5.385165 5.385165 5.385165
+6 48 43.863424 43.863424 43.863424
+6 49 82.969874 82.969874 82.969874
+6 50 76.243032 76.243032 76.243032
+6 51 72.138755 72.138755 72.138755
+6 52 73.824115 73.824115 73.824115
+6 53 55.226805 55.226805 55.226805
+6 54 35.000000 35.000000 35.000000
+6 55 43.011626 43.011626 43.011626
+6 56 26.925824 26.925824 26.925824
+6 57 58.309519 58.309519 58.309519
+6 58 60.827625 60.827625 60.827625
+6 59 75.166482 75.166482 75.166482
+6 60 65.764732 65.764732 65.764732
+6 61 25.495098 25.495098 25.495098
+6 62 32.015621 32.015621 32.015621
+6 63 67.268120 67.268120 67.268120
+6 64 79.056942 79.056942 79.056942
+6 65 60.415230 60.415230 60.415230
+6 66 47.434165 47.434165 47.434165
+6 67 52.392748 52.392748 52.392748
+6 68 61.522354 61.522354 61.522354
+6 69 32.015621 32.015621 32.015621
+6 70 34.785054 34.785054 34.785054
+6 71 21.931712 21.931712 21.931712
+6 72 54.083269 54.083269 54.083269
+6 73 47.423623 47.423623 47.423623
+6 74 30.805844 30.805844 30.805844
+6 75 65.000000 65.000000 65.000000
+6 76 81.394103 81.394103 81.394103
+6 77 83.240615 83.240615 83.240615
+6 78 82.054860 82.054860 82.054860
+6 79 31.384710 31.384710 31.384710
+6 80 22.022716 22.022716 22.022716
+6 81 46.615448 46.615448 46.615448
+6 82 39.623226 39.623226 39.623226
+6 83 42.579338 42.579338 42.579338
+6 84 56.612719 56.612719 56.612719
+6 85 67.119297 67.119297 67.119297
+6 86 75.451971 75.451971 75.451971
+6 87 61.008196 61.008196 61.008196
+6 88 61.522354 61.522354 61.522354
+6 89 27.294688 27.294688 27.294688
+6 90 92.784697 92.784697 92.784697
+6 91 41.629317 41.629317 41.629317
+6 92 51.865210 51.865210 51.865210
+6 93 53.413481 53.413481 53.413481
+6 94 52.630789 52.630789 52.630789
+6 95 52.325902 52.325902 52.325902
+6 96 60.000000 60.000000 60.000000
+6 97 46.754679 46.754679 46.754679
+6 98 68.883960 68.883960 68.883960
+6 99 33.541020 33.541020 33.541020
+6 100 50.358713 50.358713 50.358713
+6 101 21.095023 21.095023 21.095023
+7 1 33.301652 33.301652 33.301652
+7 2 12.206556 12.206556 12.206556
+7 3 4.000000 4.000000 4.000000
+7 4 10.770330 10.770330 10.770330
+7 5 5.385165 5.385165 5.385165
+7 6 10.198039 10.198039 10.198039
+7 8 3.000000 3.000000 3.000000
+7 9 5.830952 5.830952 5.830952
+7 10 40.792156 40.792156 40.792156
+7 11 35.902646 35.902646 35.902646
+7 12 36.400549 36.400549 36.400549
+7 13 31.622777 31.622777 31.622777
+7 14 42.059482 42.059482 42.059482
+7 15 32.695565 32.695565 32.695565
+7 16 38.483763 38.483763 38.483763
+7 17 39.357337 39.357337 39.357337
+7 18 34.985711 34.985711 34.985711
+7 19 74.672619 74.672619 74.672619
+7 20 69.289249 69.289249 69.289249
+7 21 64.621978 64.621978 64.621978
+7 22 73.375745 73.375745 73.375745
+7 23 63.906181 63.906181 63.906181
+7 24 72.801099 72.801099 72.801099
+7 25 63.245553 63.245553 63.245553
+7 26 72.034714 72.034714 72.034714
+7 27 89.185201 89.185201 89.185201
+7 28 86.769810 86.769810 86.769810
+7 29 86.608314 86.608314 86.608314
+7 30 82.365041 82.365041 82.365041
+7 31 83.216585 83.216585 83.216585
+7 32 80.622577 80.622577 80.622577
+7 33 82.377181 82.377181 82.377181
+7 34 83.600239 83.600239 83.600239
+7 35 78.032045 78.032045 78.032045
+7 36 50.009999 50.009999 50.009999
+7 37 48.052055 48.052055 48.052055
+7 38 47.518417 47.518417 47.518417
+7 39 44.283180 44.283180 44.283180
+7 40 42.296572 42.296572 42.296572
+7 41 43.174066 43.174066 43.174066
+7 42 40.000000 40.000000 40.000000
+7 43 37.336309 37.336309 37.336309
+7 44 38.327536 38.327536 38.327536
+7 45 37.656341 37.656341 37.656341
+7 46 7.280110 7.280110 7.280110
+7 47 5.000000 5.000000 5.000000
+7 48 34.000000 34.000000 34.000000
+7 49 74.000000 74.000000 74.000000
+7 50 67.416615 67.416615 67.416615
+7 51 67.201190 67.201190 67.201190
+7 52 66.287254 66.287254 66.287254
+7 53 45.541190 45.541190 45.541190
+7 54 25.079872 25.079872 25.079872
+7 55 39.924930 39.924930 39.924930
+7 56 19.209373 19.209373 19.209373
+7 57 51.224994 51.224994 51.224994
+7 58 51.419841 51.419841 51.419841
+7 59 65.069194 65.069194 65.069194
+7 60 55.578773 55.578773 55.578773
+7 61 15.297059 15.297059 15.297059
+7 62 28.792360 28.792360 28.792360
+7 63 61.717096 61.717096 61.717096
+7 64 72.346389 72.346389 72.346389
+7 65 52.478567 52.478567 52.478567
+7 66 38.910153 38.910153 38.910153
+7 67 44.418465 44.418465 44.418465
+7 68 56.612719 56.612719 56.612719
+7 69 26.627054 26.627054 26.627054
+7 70 26.419690 26.419690 26.419690
+7 71 18.027756 18.027756 18.027756
+7 72 51.078371 51.078371 51.078371
+7 73 46.097722 46.097722 46.097722
+7 74 21.931712 21.931712 21.931712
+7 75 55.036352 55.036352 55.036352
+7 76 71.196910 71.196910 71.196910
+7 77 75.716577 75.716577 75.716577
+7 78 72.173402 72.173402 72.173402
+7 79 21.470911 21.470911 21.470911
+7 80 13.892444 13.892444 13.892444
+7 81 40.311289 40.311289 40.311289
+7 82 35.355339 35.355339 35.355339
+7 83 33.241540 33.241540 33.241540
+7 84 47.927028 47.927028 47.927028
+7 85 60.307545 60.307545 60.307545
+7 86 68.767725 68.767725 68.767725
+7 87 51.088159 51.088159 51.088159
+7 88 51.351728 51.351728 51.351728
+7 89 18.027756 18.027756 18.027756
+7 90 85.445889 85.445889 85.445889
+7 91 33.837849 33.837849 33.837849
+7 92 45.276926 45.276926 45.276926
+7 93 47.423623 47.423623 47.423623
+7 94 48.764741 48.764741 48.764741
+7 95 47.434165 47.434165 47.434165
+7 96 53.740115 53.740115 53.740115
+7 97 42.544095 42.544095 42.544095
+7 98 58.694122 58.694122 58.694122
+7 99 24.351591 24.351591 24.351591
+7 100 40.792156 40.792156 40.792156
+7 101 15.264338 15.264338 15.264338
+8 1 35.355339 35.355339 35.355339
+8 2 14.142136 14.142136 14.142136
+8 3 7.000000 7.000000 7.000000
+8 4 12.206556 12.206556 12.206556
+8 5 7.071068 7.071068 7.071068
+8 6 11.180340 11.180340 11.180340
+8 7 3.000000 3.000000 3.000000
+8 9 5.000000 5.000000 5.000000
+8 10 40.311289 40.311289 40.311289
+8 11 35.355339 35.355339 35.355339
+8 12 35.693137 35.693137 35.693137
+8 13 30.805844 30.805844 30.805844
+8 14 41.231056 41.231056 41.231056
+8 15 31.622777 31.622777 31.622777
+8 16 37.336309 37.336309 37.336309
+8 17 38.078866 38.078866 38.078866
+8 18 33.541020 33.541020 33.541020
+8 19 75.769387 75.769387 75.769387
+8 20 70.384657 70.384657 70.384657
+8 21 65.795137 65.795137 65.795137
+8 22 74.330344 74.330344 74.330344
+8 23 65.000000 65.000000 65.000000
+8 24 73.681748 73.681748 73.681748
+8 25 64.257295 64.257295 64.257295
+8 26 72.801099 72.801099 72.801099
+8 27 91.787799 91.787799 91.787799
+8 28 89.442719 89.442719 89.442719
+8 29 89.185201 89.185201 89.185201
+8 30 85.000000 85.000000 85.000000
+8 31 85.755466 85.755466 85.755466
+8 32 83.240615 83.240615 83.240615
+8 33 84.905830 84.905830 84.905830
+8 34 86.023253 86.023253 86.023253
+8 35 80.622577 80.622577 80.622577
+8 36 52.952809 52.952809 52.952809
+8 37 50.990195 50.990195 50.990195
+8 38 50.487622 50.487622 50.487622
+8 39 47.265209 47.265209 47.265209
+8 40 45.276926 45.276926 45.276926
+8 41 46.097722 46.097722 46.097722
+8 42 43.000000 43.000000 43.000000
+8 43 40.311289 40.311289 40.311289
+8 44 41.231056 41.231056 41.231056
+8 45 40.607881 40.607881 40.607881
+8 46 8.602325 8.602325 8.602325
+8 47 5.830952 5.830952 5.830952
+8 48 32.695565 32.695565 32.695565
+8 49 75.026662 75.026662 75.026662
+8 50 68.541958 68.541958 68.541958
+8 51 69.634761 69.634761 69.634761
+8 52 68.007353 68.007353 68.007353
+8 53 46.097722 46.097722 46.097722
+8 54 25.495098 25.495098 25.495098
+8 55 42.720019 42.720019 42.720019
+8 56 21.213203 21.213203 21.213203
+8 57 53.150729 53.150729 53.150729
+8 58 52.201533 52.201533 52.201533
+8 59 65.000000 65.000000 65.000000
+8 60 55.226805 55.226805 55.226805
+8 61 15.000000 15.000000 15.000000
+8 62 31.622777 31.622777 31.622777
+8 63 64.031242 64.031242 64.031242
+8 64 74.330344 74.330344 74.330344
+8 65 54.083269 54.083269 54.083269
+8 66 40.311289 40.311289 40.311289
+8 67 46.043458 46.043458 46.043458
+8 68 59.076222 59.076222 59.076222
+8 69 29.154759 29.154759 29.154759
+8 70 28.017851 28.017851 28.017851
+8 71 20.880613 20.880613 20.880613
+8 72 53.851648 53.851648 53.851648
+8 73 49.030603 49.030603 49.030603
+8 74 19.849433 19.849433 19.849433
+8 75 55.226805 55.226805 55.226805
+8 76 70.710678 70.710678 70.710678
+8 77 77.420927 77.420927 77.420927
+8 78 72.443081 72.443081 72.443081
+8 79 20.248457 20.248457 20.248457
+8 80 11.401754 11.401754 11.401754
+8 81 42.520583 42.520583 42.520583
+8 82 38.013156 38.013156 38.013156
+8 83 34.176015 34.176015 34.176015
+8 84 49.193496 49.193496 49.193496
+8 85 62.289646 62.289646 62.289646
+8 86 70.767224 70.767224 70.767224
+8 87 51.351728 51.351728 51.351728
+8 88 51.088159 51.088159 51.088159
+8 89 19.235384 19.235384 19.235384
+8 90 87.200917 87.200917 87.200917
+8 91 35.608988 35.608988 35.608988
+8 92 47.381431 47.381431 47.381431
+8 93 49.678969 49.678969 49.678969
+8 94 51.429563 51.429563 51.429563
+8 95 49.929951 49.929951 49.929951
+8 96 55.901699 55.901699 55.901699
+8 97 45.177428 45.177428 45.177428
+8 98 58.051701 58.051701 58.051701
+8 99 25.495098 25.495098 25.495098
+8 100 41.484937 41.484937 41.484937
+8 101 17.888544 17.888544 17.888544
+9 1 39.051248 39.051248 39.051248
+9 2 11.180340 11.180340 11.180340
+9 3 8.602325 8.602325 8.602325
+9 4 8.602325 8.602325 8.602325
+9 5 5.000000 5.000000 5.000000
+9 6 7.071068 7.071068 7.071068
+9 7 5.830952 5.830952 5.830952
+9 8 5.000000 5.000000 5.000000
+9 10 45.276926 45.276926 45.276926
+9 11 40.311289 40.311289 40.311289
+9 12 40.607881 40.607881 40.607881
+9 13 35.693137 35.693137 35.693137
+9 14 46.097722 46.097722 46.097722
+9 15 36.400549 36.400549 36.400549
+9 16 42.059482 42.059482 42.059482
+9 17 42.720019 42.720019 42.720019
+9 18 38.078866 38.078866 38.078866
+9 19 80.411442 80.411442 80.411442
+9 20 75.026662 75.026662 75.026662
+9 21 70.384657 70.384657 70.384657
+9 22 79.056942 79.056942 79.056942
+9 23 69.641941 69.641941 69.641941
+9 24 78.447435 78.447435 78.447435
+9 25 68.949257 68.949257 68.949257
+9 26 77.620873 77.620873 77.620873
+9 27 94.339811 94.339811 94.339811
+9 28 91.787799 91.787799 91.787799
+9 29 91.809586 91.809586 91.809586
+9 30 87.464278 87.464278 87.464278
+9 31 88.481637 88.481637 88.481637
+9 32 85.755466 85.755466 85.755466
+9 33 87.658428 87.658428 87.658428
+9 34 89.022469 89.022469 89.022469
+9 35 83.216585 83.216585 83.216585
+9 36 52.239832 52.239832 52.239832
+9 37 50.249378 50.249378 50.249378
+9 38 50.039984 50.039984 50.039984
+9 39 47.000000 47.000000 47.000000
+9 40 45.000000 45.000000 45.000000
+9 41 45.276926 45.276926 45.276926
+9 42 43.289722 43.289722 43.289722
+9 43 40.000000 40.000000 40.000000
+9 44 40.311289 40.311289 40.311289
+9 45 40.049969 40.049969 40.049969
+9 46 5.385165 5.385165 5.385165
+9 47 3.000000 3.000000 3.000000
+9 48 37.336309 37.336309 37.336309
+9 49 79.711982 79.711982 79.711982
+9 50 73.164199 73.164199 73.164199
+9 51 72.622311 72.622311 72.622311
+9 52 72.111026 72.111026 72.111026
+9 53 50.990195 50.990195 50.990195
+9 54 30.413813 30.413813 30.413813
+9 55 44.721360 44.721360 44.721360
+9 56 25.000000 25.000000 25.000000
+9 57 57.008771 57.008771 57.008771
+9 58 57.008771 57.008771 57.008771
+9 59 70.000000 70.000000 70.000000
+9 60 60.207973 60.207973 60.207973
+9 61 20.000000 20.000000 20.000000
+9 62 33.541020 33.541020 33.541020
+9 63 67.268120 67.268120 67.268120
+9 64 78.102497 78.102497 78.102497
+9 65 58.309519 58.309519 58.309519
+9 66 44.721360 44.721360 44.721360
+9 67 50.249378 50.249378 50.249378
+9 68 62.008064 62.008064 62.008064
+9 69 32.015621 32.015621 32.015621
+9 70 32.249031 32.249031 32.249031
+9 71 22.825424 22.825424 22.825424
+9 72 55.901699 55.901699 55.901699
+9 73 50.289164 50.289164 50.289164
+9 74 23.853721 23.853721 23.853721
+9 75 60.207973 60.207973 60.207973
+9 76 75.663730 75.663730 75.663730
+9 77 81.541401 81.541401 81.541401
+9 78 77.414469 77.414469 77.414469
+9 79 25.000000 25.000000 25.000000
+9 80 15.000000 15.000000 15.000000
+9 81 45.967380 45.967380 45.967380
+9 82 40.496913 40.496913 40.496913
+9 83 38.897301 38.897301 38.897301
+9 84 53.712196 53.712196 53.712196
+9 85 66.068147 66.068147 66.068147
+9 86 74.518454 74.518454 74.518454
+9 87 56.320511 56.320511 56.320511
+9 88 56.080300 56.080300 56.080300
+9 89 23.769729 23.769729 23.769729
+9 90 91.263355 91.263355 91.263355
+9 91 39.661064 39.661064 39.661064
+9 92 50.990195 50.990195 50.990195
+9 93 53.037722 53.037722 53.037722
+9 94 53.851648 53.851648 53.851648
+9 95 52.801515 52.801515 52.801515
+9 96 59.413803 59.413803 59.413803
+9 97 47.707442 47.707442 47.707442
+9 98 62.968246 62.968246 62.968246
+9 99 30.083218 30.083218 30.083218
+9 100 46.324939 46.324939 46.324939
+9 101 20.615528 20.615528 20.615528
+10 1 33.541020 33.541020 33.541020
+10 2 52.201533 52.201533 52.201533
+10 3 41.761226 41.761226 41.761226
+10 4 51.419841 51.419841 51.419841
+10 5 46.097722 46.097722 46.097722
+10 6 50.990195 50.990195 50.990195
+10 7 40.792156 40.792156 40.792156
+10 8 40.311289 40.311289 40.311289
+10 9 45.276926 45.276926 45.276926
+10 11 5.000000 5.000000 5.000000
+10 12 5.385165 5.385165 5.385165
+10 13 10.198039 10.198039 10.198039
+10 14 5.000000 5.000000 5.000000
+10 15 11.180340 11.180340 11.180340
+10 16 9.433981 9.433981 9.433981
+10 17 11.180340 11.180340 11.180340
+10 18 14.142136 14.142136 14.142136
+10 19 45.343136 45.343136 45.343136
+10 20 40.607881 40.607881 40.607881
+10 21 37.735925 37.735925 37.735925
+10 22 42.426407 42.426407 42.426407
+10 23 36.055513 36.055513 36.055513
+10 24 41.036569 41.036569 41.036569
+10 25 34.409301 34.409301 34.409301
+10 26 39.051248 39.051248 39.051248
+10 27 85.146932 85.146932 85.146932
+10 28 85.000000 85.000000 85.000000
+10 29 82.152298 82.152298 82.152298
+10 30 80.000000 80.000000 80.000000
+10 31 78.160092 78.160092 78.160092
+10 32 78.000000 78.000000 78.000000
+10 33 77.162167 77.162167 77.162167
+10 34 75.663730 75.663730 75.663730
+10 35 75.000000 75.000000 75.000000
+10 36 75.822160 75.822160 75.822160
+10 37 74.330344 74.330344 74.330344
+10 38 72.346389 72.346389 72.346389
+10 39 68.767725 68.767725 68.767725
+10 40 67.268120 67.268120 67.268120
+10 41 70.710678 70.710678 70.710678
+10 42 62.481997 62.481997 62.481997
+10 43 63.639610 63.639610 63.639610
+10 44 67.268120 67.268120 67.268120
+10 45 65.069194 65.069194 65.069194
+10 46 48.052055 48.052055 48.052055
+10 47 45.705580 45.705580 45.705580
+10 48 12.806248 12.806248 12.806248
+10 49 43.863424 43.863424 43.863424
+10 50 39.408121 39.408121 39.408121
+10 51 62.000000 62.000000 62.000000
+10 52 47.434165 47.434165 47.434165
+10 53 15.811388 15.811388 15.811388
+10 54 18.027756 18.027756 18.027756
+10 55 51.478151 51.478151 51.478151
+10 56 32.015621 32.015621 32.015621
+10 57 40.000000 40.000000 40.000000
+10 58 22.360680 22.360680 22.360680
+10 59 25.495098 25.495098 25.495098
+10 60 15.000000 15.000000 15.000000
+10 61 25.495098 25.495098 25.495098
+10 62 46.097722 46.097722 46.097722
+10 63 55.000000 55.000000 55.000000
+10 64 57.008771 57.008771 57.008771
+10 65 35.355339 35.355339 35.355339
+10 66 25.495098 25.495098 25.495098
+10 67 31.064449 31.064449 31.064449
+10 68 54.451814 54.451814 54.451814
+10 69 39.051248 39.051248 39.051248
+10 70 27.018512 27.018512 27.018512
+10 71 42.201896 42.201896 42.201896
+10 72 58.523500 58.523500 58.523500
+10 73 60.901560 60.901560 60.901560
+10 74 26.248809 26.248809 26.248809
+10 75 18.027756 18.027756 18.027756
+10 76 30.413813 30.413813 30.413813
+10 77 55.036352 55.036352 55.036352
+10 78 34.539832 34.539832 34.539832
+10 79 21.095023 21.095023 21.095023
+10 80 33.241540 33.241540 33.241540
+10 81 38.897301 38.897301 38.897301
+10 82 45.276926 45.276926 45.276926
+10 83 18.788294 18.788294 18.788294
+10 84 27.294688 27.294688 27.294688
+10 85 47.381431 47.381431 47.381431
+10 86 54.341513 54.341513 54.341513
+10 87 15.556349 15.556349 15.556349
+10 88 11.180340 11.180340 11.180340
+10 89 26.925824 26.925824 26.925824
+10 90 64.412732 64.412732 64.412732
+10 91 29.546573 29.546573 29.546573
+10 92 39.623226 39.623226 39.623226
+10 93 43.737855 43.737855 43.737855
+10 94 53.758720 53.758720 53.758720
+10 95 48.764741 48.764741 48.764741
+10 96 46.043458 46.043458 46.043458
+10 97 48.846699 48.846699 48.846699
+10 98 18.027756 18.027756 18.027756
+10 99 23.345235 23.345235 23.345235
+10 100 16.000000 16.000000 16.000000
+10 101 38.275318 38.275318 38.275318
+11 1 31.622777 31.622777 31.622777
+11 2 47.434165 47.434165 47.434165
+11 3 37.000000 37.000000 37.000000
+11 4 46.572524 46.572524 46.572524
+11 5 41.231056 41.231056 41.231056
+11 6 46.097722 46.097722 46.097722
+11 7 35.902646 35.902646 35.902646
+11 8 35.355339 35.355339 35.355339
+11 9 40.311289 40.311289 40.311289
+11 10 5.000000 5.000000 5.000000
+11 12 2.000000 2.000000 2.000000
+11 13 5.385165 5.385165 5.385165
+11 14 7.071068 7.071068 7.071068
+11 15 7.071068 7.071068 7.071068
+11 16 8.000000 8.000000 8.000000
+11 17 10.000000 10.000000 10.000000
+11 18 11.180340 11.180340 11.180340
+11 19 48.795492 48.795492 48.795492
+11 20 43.863424 43.863424 43.863424
+11 21 40.607881 40.607881 40.607881
+11 22 46.097722 46.097722 46.097722
+11 23 39.051248 39.051248 39.051248
+11 24 44.821870 44.821870 44.821870
+11 25 37.536649 37.536649 37.536649
+11 26 43.011626 43.011626 43.011626
+11 27 85.586214 85.586214 85.586214
+11 28 85.146932 85.146932 85.146932
+11 29 82.607506 82.607506 82.607506
+11 30 80.156098 80.156098 80.156098
+11 31 78.638413 78.638413 78.638413
+11 32 78.160092 78.160092 78.160092
+11 33 77.646635 77.646635 77.646635
+11 34 76.485293 76.485293 76.485293
+11 35 75.166482 75.166482 75.166482
+11 36 72.622311 72.622311 72.622311
+11 37 71.063352 71.063352 71.063352
+11 38 69.202601 69.202601 69.202601
+11 39 65.604878 65.604878 65.604878
+11 40 64.031242 64.031242 64.031242
+11 41 67.268120 67.268120 67.268120
+11 42 59.405387 59.405387 59.405387
+11 43 60.207973 60.207973 60.207973
+11 44 63.639610 63.639610 63.639610
+11 45 61.554854 61.554854 61.554854
+11 46 43.174066 43.174066 43.174066
+11 47 40.792156 40.792156 40.792156
+11 48 9.433981 9.433981 9.433981
+11 49 47.423623 47.423623 47.423623
+11 50 42.520583 42.520583 42.520583
+11 51 62.201286 62.201286 62.201286
+11 52 49.244289 49.244289 49.244289
+11 53 18.027756 18.027756 18.027756
+11 54 14.142136 14.142136 14.142136
+11 55 49.244289 49.244289 49.244289
+11 56 28.284271 28.284271 28.284271
+11 57 40.311289 40.311289 40.311289
+11 58 25.000000 25.000000 25.000000
+11 59 30.413813 30.413813 30.413813
+11 60 20.000000 20.000000 20.000000
+11 61 20.615528 20.615528 20.615528
+11 62 43.011626 43.011626 43.011626
+11 63 55.226805 55.226805 55.226805
+11 64 58.523500 58.523500 58.523500
+11 65 36.400549 36.400549 36.400549
+11 66 25.000000 25.000000 25.000000
+11 67 31.144823 31.144823 31.144823
+11 68 54.037024 54.037024 54.037024
+11 69 36.055513 36.055513 36.055513
+11 70 24.186773 24.186773 24.186773
+11 71 38.288379 38.288379 38.288379
+11 72 57.008771 57.008771 57.008771
+11 73 58.600341 58.600341 58.600341
+11 74 21.540659 21.540659 21.540659
+11 75 22.360680 22.360680 22.360680
+11 76 35.355339 35.355339 35.355339
+11 77 57.306195 57.306195 57.306195
+11 78 39.217343 39.217343 39.217343
+11 79 16.124515 16.124515 16.124515
+11 80 28.284271 28.284271 28.284271
+11 81 37.656341 37.656341 37.656341
+11 82 42.953463 42.953463 42.953463
+11 83 17.262677 17.262677 17.262677
+11 84 28.460499 28.460499 28.460499
+11 85 48.270074 48.270074 48.270074
+11 86 55.659680 55.659680 55.659680
+11 87 19.416488 19.416488 19.416488
+11 88 16.124515 16.124515 16.124515
+11 89 22.803509 22.803509 22.803509
+11 90 66.887966 66.887966 66.887966
+11 91 27.892651 27.892651 27.892651
+11 92 39.051248 39.051248 39.051248
+11 93 43.104524 43.104524 43.104524
+11 94 52.392748 52.392748 52.392748
+11 95 47.675990 47.675990 47.675990
+11 96 46.097722 46.097722 46.097722
+11 97 47.127487 47.127487 47.127487
+11 98 22.803509 22.803509 22.803509
+11 99 20.000000 20.000000 20.000000
+11 100 16.763055 16.763055 16.763055
+11 101 34.205263 34.205263 34.205263
+12 1 33.526109 33.526109 33.526109
+12 2 48.104054 48.104054 48.104054
+12 3 37.696154 37.696154 37.696154
+12 4 47.127487 47.127487 47.127487
+12 5 41.761226 41.761226 41.761226
+12 6 46.572524 46.572524 46.572524
+12 7 36.400549 36.400549 36.400549
+12 8 35.693137 35.693137 35.693137
+12 9 40.607881 40.607881 40.607881
+12 10 5.385165 5.385165 5.385165
+12 11 2.000000 2.000000 2.000000
+12 13 5.000000 5.000000 5.000000
+12 14 5.830952 5.830952 5.830952
+12 15 5.830952 5.830952 5.830952
+12 16 6.000000 6.000000 6.000000
+12 17 8.000000 8.000000 8.000000
+12 18 9.433981 9.433981 9.433981
+12 19 50.209561 50.209561 50.209561
+12 20 45.343136 45.343136 45.343136
+12 21 42.201896 42.201896 42.201896
+12 22 47.423623 47.423623 47.423623
+12 23 40.607881 40.607881 40.607881
+12 24 46.097722 46.097722 46.097722
+12 25 39.051248 39.051248 39.051248
+12 26 44.204072 44.204072 44.204072
+12 27 87.572827 87.572827 87.572827
+12 28 87.143560 87.143560 87.143560
+12 29 84.593144 84.593144 84.593144
+12 30 82.152298 82.152298 82.152298
+12 31 80.622577 80.622577 80.622577
+12 32 80.156098 80.156098 80.156098
+12 33 79.630396 79.630396 79.630396
+12 34 78.447435 78.447435 78.447435
+12 35 77.162167 77.162167 77.162167
+12 36 74.202426 74.202426 74.202426
+12 37 72.622311 72.622311 72.622311
+12 38 70.802542 70.802542 70.802542
+12 39 67.201190 67.201190 67.201190
+12 40 65.604878 65.604878 65.604878
+12 41 68.767725 68.767725 68.767725
+12 42 61.032778 61.032778 61.032778
+12 43 61.717096 61.717096 61.717096
+12 44 65.069194 65.069194 65.069194
+12 45 63.031738 63.031738 63.031738
+12 46 43.680659 43.680659 43.680659
+12 47 41.231056 41.231056 41.231056
+12 48 7.810250 7.810250 7.810250
+12 49 48.795492 48.795492 48.795492
+12 50 44.045431 44.045431 44.045431
+12 51 64.195015 64.195015 64.195015
+12 52 51.078371 51.078371 51.078371
+12 53 19.723083 19.723083 19.723083
+12 54 15.620499 15.620499 15.620499
+12 55 51.078371 51.078371 51.078371
+12 56 29.732137 29.732137 29.732137
+12 57 42.296572 42.296572 42.296572
+12 58 26.627054 26.627054 26.627054
+12 59 30.805844 30.805844 30.805844
+12 60 20.099751 20.099751 20.099751
+12 61 21.189620 21.189620 21.189620
+12 62 44.654227 44.654227 44.654227
+12 63 57.218878 57.218878 57.218878
+12 64 60.406953 60.406953 60.406953
+12 65 38.327536 38.327536 38.327536
+12 66 27.000000 27.000000 27.000000
+12 67 33.136083 33.136083 33.136083
+12 68 56.035703 56.035703 56.035703
+12 69 37.735925 37.735925 37.735925
+12 70 25.942244 25.942244 25.942244
+12 71 39.623226 39.623226 39.623226
+12 72 58.940648 58.940648 58.940648
+12 73 60.415230 60.415230 60.415230
+12 74 20.880613 20.880613 20.880613
+12 75 23.323808 23.323808 23.323808
+12 76 35.128336 35.128336 35.128336
+12 77 59.059292 59.059292 59.059292
+12 78 39.924930 39.924930 39.924930
+12 79 16.000000 16.000000 16.000000
+12 80 28.071338 28.071338 28.071338
+12 81 39.623226 39.623226 39.623226
+12 82 44.777226 44.777226 44.777226
+12 83 19.235384 19.235384 19.235384
+12 84 30.364453 30.364453 30.364453
+12 85 50.219518 50.219518 50.219518
+12 86 57.567352 57.567352 57.567352
+12 87 20.615528 20.615528 20.615528
+12 88 16.492423 16.492423 16.492423
+12 89 24.083189 24.083189 24.083189
+12 90 68.600292 68.600292 68.600292
+12 91 29.832868 29.832868 29.832868
+12 92 41.048752 41.048752 41.048752
+12 93 45.099889 45.099889 45.099889
+12 94 54.341513 54.341513 54.341513
+12 95 49.648766 49.648766 49.648766
+12 96 48.093659 48.093659 48.093659
+12 97 49.040799 49.040799 49.040799
+12 98 22.360680 22.360680 22.360680
+12 99 21.633308 21.633308 21.633308
+12 100 18.681542 18.681542 18.681542
+12 101 35.468296 35.468296 35.468296
+13 1 32.388269 32.388269 32.388269
+13 2 43.462628 43.462628 43.462628
+13 3 33.105891 33.105891 33.105891
+13 4 42.379240 42.379240 42.379240
+13 5 37.000000 37.000000 37.000000
+13 6 41.761226 41.761226 41.761226
+13 7 31.622777 31.622777 31.622777
+13 8 30.805844 30.805844 30.805844
+13 9 35.693137 35.693137 35.693137
+13 10 10.198039 10.198039 10.198039
+13 11 5.385165 5.385165 5.385165
+13 12 5.000000 5.000000 5.000000
+13 14 10.440307 10.440307 10.440307
+13 15 3.000000 3.000000 3.000000
+13 16 7.810250 7.810250 7.810250
+13 17 9.433981 9.433981 9.433981
+13 18 8.000000 8.000000 8.000000
+13 19 53.814496 53.814496 53.814496
+13 20 48.795492 48.795492 48.795492
+13 21 45.343136 45.343136 45.343136
+13 22 51.224994 51.224994 51.224994
+13 23 43.863424 43.863424 43.863424
+13 24 50.000000 50.000000 50.000000
+13 25 42.426407 42.426407 42.426407
+13 26 48.259714 48.259714 48.259714
+13 27 88.283634 88.283634 88.283634
+13 28 87.572827 87.572827 87.572827
+13 29 85.328776 85.328776 85.328776
+13 30 82.607506 82.607506 82.607506
+13 31 81.394103 81.394103 81.394103
+13 32 80.622577 80.622577 80.622577
+13 33 80.411442 80.411442 80.411442
+13 34 79.555012 79.555012 79.555012
+13 35 77.646635 77.646635 77.646635
+13 36 71.281134 71.281134 71.281134
+13 37 69.634761 69.634761 69.634761
+13 38 67.955868 67.955868 67.955868
+13 39 64.350602 64.350602 64.350602
+13 40 62.681736 62.681736 62.681736
+13 41 65.604878 65.604878 65.604878
+13 42 58.309519 58.309519 58.309519
+13 43 58.600341 58.600341 58.600341
+13 44 61.717096 61.717096 61.717096
+13 45 59.816386 59.816386 59.816386
+13 46 38.897301 38.897301 38.897301
+13 47 36.400549 36.400549 36.400549
+13 48 6.000000 6.000000 6.000000
+13 49 52.497619 52.497619 52.497619
+13 50 47.381431 47.381431 47.381431
+13 51 64.776539 64.776539 64.776539
+13 52 53.235327 53.235327 53.235327
+13 53 22.671568 22.671568 22.671568
+13 54 13.000000 13.000000 13.000000
+13 55 49.335586 49.335586 49.335586
+13 56 26.627054 26.627054 26.627054
+13 57 43.174066 43.174066 43.174066
+13 58 29.732137 29.732137 29.732137
+13 59 35.693137 35.693137 35.693137
+13 60 25.079872 25.079872 25.079872
+13 61 16.552945 16.552945 16.552945
+13 62 42.059482 42.059482 42.059482
+13 63 57.870545 57.870545 57.870545
+13 64 62.241465 62.241465 62.241465
+13 65 39.924930 39.924930 39.924930
+13 66 27.459060 27.459060 27.459060
+13 67 33.955854 33.955854 33.955854
+13 68 56.080300 56.080300 56.080300
+13 69 35.341194 35.341194 35.341194
+13 70 24.041631 24.041631 24.041631
+13 71 36.124784 36.124784 36.124784
+13 72 57.870545 57.870545 57.870545
+13 73 58.523500 58.523500 58.523500
+13 74 16.155494 16.155494 16.155494
+13 75 27.730849 27.730849 27.730849
+13 76 40.112342 40.112342 40.112342
+13 77 61.587336 61.587336 61.587336
+13 78 44.598206 44.598206 44.598206
+13 79 11.000000 11.000000 11.000000
+13 80 23.086793 23.086793 23.086793
+13 81 39.051248 39.051248 39.051248
+13 82 43.011626 43.011626 43.011626
+13 83 19.104973 19.104973 19.104973
+13 84 32.202484 32.202484 32.202484
+13 85 51.546096 51.546096 51.546096
+13 86 59.236813 59.236813 59.236813
+13 87 24.698178 24.698178 24.698178
+13 88 21.377558 21.377558 21.377558
+13 89 20.615528 20.615528 20.615528
+13 90 71.281134 71.281134 71.281134
+13 91 29.068884 29.068884 29.068884
+13 92 41.109610 41.109610 41.109610
+13 93 45.044423 45.044423 45.044423
+13 94 53.460266 53.460266 53.460266
+13 95 49.091751 49.091751 49.091751
+13 96 48.662100 48.662100 48.662100
+13 97 47.853944 47.853944 47.853944
+13 98 27.294688 27.294688 27.294688
+13 99 19.313208 19.313208 19.313208
+13 100 20.591260 20.591260 20.591260
+13 101 31.827661 31.827661 31.827661
+14 1 38.078866 38.078866 38.078866
+14 2 53.851648 53.851648 53.851648
+14 3 43.462628 43.462628 43.462628
+14 4 52.810984 52.810984 52.810984
+14 5 47.434165 47.434165 47.434165
+14 6 52.201533 52.201533 52.201533
+14 7 42.059482 42.059482 42.059482
+14 8 41.231056 41.231056 41.231056
+14 9 46.097722 46.097722 46.097722
+14 10 5.000000 5.000000 5.000000
+14 11 7.071068 7.071068 7.071068
+14 12 5.830952 5.830952 5.830952
+14 13 10.440307 10.440307 10.440307
+14 15 10.000000 10.000000 10.000000
+14 16 5.830952 5.830952 5.830952
+14 17 7.071068 7.071068 7.071068
+14 18 11.180340 11.180340 11.180340
+14 19 49.203658 49.203658 49.203658
+14 20 44.654227 44.654227 44.654227
+14 21 42.059482 42.059482 42.059482
+14 22 46.097722 46.097722 46.097722
+14 23 40.311289 40.311289 40.311289
+14 24 44.598206 44.598206 44.598206
+14 25 38.587563 38.587563 38.587563
+14 26 42.426407 42.426407 42.426407
+14 27 90.138782 90.138782 90.138782
+14 28 90.000000 90.000000 90.000000
+14 29 87.143560 87.143560 87.143560
+14 30 85.000000 85.000000 85.000000
+14 31 83.150466 83.150466 83.150466
+14 32 83.000000 83.000000 83.000000
+14 33 82.152298 82.152298 82.152298
+14 34 80.622577 80.622577 80.622577
+14 35 80.000000 80.000000 80.000000
+14 36 79.649231 79.649231 79.649231
+14 37 78.102497 78.102497 78.102497
+14 38 76.216796 76.216796 76.216796
+14 39 72.622311 72.622311 72.622311
+14 40 71.063352 71.063352 71.063352
+14 41 74.330344 74.330344 74.330344
+14 42 66.400301 66.400301 66.400301
+14 43 67.268120 67.268120 67.268120
+14 44 70.710678 70.710678 70.710678
+14 45 68.622154 68.622154 68.622154
+14 46 49.335586 49.335586 49.335586
+14 47 46.840154 46.840154 46.840154
+14 48 10.440307 10.440307 10.440307
+14 49 47.634021 47.634021 47.634021
+14 50 43.566042 43.566042 43.566042
+14 51 67.000000 67.000000 67.000000
+14 52 52.201533 52.201533 52.201533
+14 53 20.615528 20.615528 20.615528
+14 54 21.213203 21.213203 21.213203
+14 55 55.901699 55.901699 55.901699
+14 56 35.355339 35.355339 35.355339
+14 57 45.000000 45.000000 45.000000
+14 58 26.925824 26.925824 26.925824
+14 59 26.925824 26.925824 26.925824
+14 60 15.811388 15.811388 15.811388
+14 61 26.925824 26.925824 26.925824
+14 62 50.000000 50.000000 50.000000
+14 63 60.000000 60.000000 60.000000
+14 64 61.846584 61.846584 61.846584
+14 65 40.311289 40.311289 40.311289
+14 66 30.413813 30.413813 30.413813
+14 67 36.055513 36.055513 36.055513
+14 68 59.413803 59.413803 59.413803
+14 69 43.011626 43.011626 43.011626
+14 70 31.064449 31.064449 31.064449
+14 71 45.343136 45.343136 45.343136
+14 72 63.245553 63.245553 63.245553
+14 73 65.299311 65.299311 65.299311
+14 74 25.179357 25.179357 25.179357
+14 75 21.213203 21.213203 21.213203
+14 76 30.000000 30.000000 30.000000
+14 77 59.615434 59.615434 59.615434
+14 78 36.715120 36.715120 36.715120
+14 79 21.213203 21.213203 21.213203
+14 80 33.015148 33.015148 33.015148
+14 81 43.680659 43.680659 43.680659
+14 82 49.648766 49.648766 49.648766
+14 83 23.409400 23.409400 23.409400
+14 84 32.249031 32.249031 32.249031
+14 85 52.345009 52.345009 52.345009
+14 86 59.228372 59.228372 59.228372
+14 87 19.416488 19.416488 19.416488
+14 88 13.038405 13.038405 13.038405
+14 89 29.832868 29.832868 29.832868
+14 90 68.876701 68.876701 68.876701
+14 91 34.176015 34.176015 34.176015
+14 92 44.553339 44.553339 44.553339
+14 93 48.662100 48.662100 48.662100
+14 94 58.523500 58.523500 58.523500
+14 95 53.600373 53.600373 53.600373
+14 96 51.039201 51.039201 51.039201
+14 97 53.488316 53.488316 53.488316
+14 98 17.029386 17.029386 17.029386
+14 99 27.018512 27.018512 27.018512
+14 100 21.000000 21.000000 21.000000
+14 101 41.231056 41.231056 41.231056
+15 1 35.355339 35.355339 35.355339
+15 2 44.721360 44.721360 44.721360
+15 3 34.481879 34.481879 34.481879
+15 4 43.462628 43.462628 43.462628
+15 5 38.078866 38.078866 38.078866
+15 6 42.720019 42.720019 42.720019
+15 7 32.695565 32.695565 32.695565
+15 8 31.622777 31.622777 31.622777
+15 9 36.400549 36.400549 36.400549
+15 10 11.180340 11.180340 11.180340
+15 11 7.071068 7.071068 7.071068
+15 12 5.830952 5.830952 5.830952
+15 13 3.000000 3.000000 3.000000
+15 14 10.000000 10.000000 10.000000
+15 16 5.830952 5.830952 5.830952
+15 17 7.071068 7.071068 7.071068
+15 18 5.000000 5.000000 5.000000
+15 19 55.865911 55.865911 55.865911
+15 20 50.931326 50.931326 50.931326
+15 21 47.634021 47.634021 47.634021
+15 22 53.150729 53.150729 53.150729
+15 23 46.097722 46.097722 46.097722
+15 24 51.855569 51.855569 51.855569
+15 25 44.598206 44.598206 44.598206
+15 26 50.000000 50.000000 50.000000
+15 27 91.241438 91.241438 91.241438
+15 28 90.553851 90.553851 90.553851
+15 29 88.283634 88.283634 88.283634
+15 30 85.586214 85.586214 85.586214
+15 31 84.344532 84.344532 84.344532
+15 32 83.600239 83.600239 83.600239
+15 33 83.360662 83.360662 83.360662
+15 34 82.462113 82.462113 82.462113
+15 35 80.622577 80.622577 80.622577
+15 36 73.783467 73.783467 73.783467
+15 37 72.111026 72.111026 72.111026
+15 38 70.491134 70.491134 70.491134
+15 39 66.887966 66.887966 66.887966
+15 40 65.192024 65.192024 65.192024
+15 41 68.007353 68.007353 68.007353
+15 42 60.901560 60.901560 60.901560
+15 43 61.032778 61.032778 61.032778
+15 44 64.031242 64.031242 64.031242
+15 45 62.201286 62.201286 62.201286
+15 46 39.924930 39.924930 39.924930
+15 47 37.336309 37.336309 37.336309
+15 48 3.000000 3.000000 3.000000
+15 49 54.488531 54.488531 54.488531
+15 50 49.578221 49.578221 49.578221
+15 51 67.742158 67.742158 67.742158
+15 52 55.901699 55.901699 55.901699
+15 53 25.000000 25.000000 25.000000
+15 54 15.811388 15.811388 15.811388
+15 55 52.201533 52.201533 52.201533
+15 56 29.154759 29.154759 29.154759
+15 57 46.097722 46.097722 46.097722
+15 58 32.015621 32.015621 32.015621
+15 59 36.400549 36.400549 36.400549
+15 60 25.495098 25.495098 25.495098
+15 61 18.027756 18.027756 18.027756
+15 62 44.721360 44.721360 44.721360
+15 63 60.827625 60.827625 60.827625
+15 64 65.000000 65.000000 65.000000
+15 65 42.720019 42.720019 42.720019
+15 66 30.413813 30.413813 30.413813
+15 67 36.878178 36.878178 36.878178
+15 68 59.076222 59.076222 59.076222
+15 69 38.078866 38.078866 38.078866
+15 70 26.925824 26.925824 26.925824
+15 71 38.418745 38.418745 38.418745
+15 72 60.827625 60.827625 60.827625
+15 73 61.351447 61.351447 61.351447
+15 74 15.297059 15.297059 15.297059
+15 75 29.154759 29.154759 29.154759
+15 76 40.000000 40.000000 40.000000
+15 77 64.140471 64.140471 64.140471
+15 78 45.694639 45.694639 45.694639
+15 79 11.401754 11.401754 11.401754
+15 80 23.021729 23.021729 23.021729
+15 81 42.047592 42.047592 42.047592
+15 82 45.880279 45.880279 45.880279
+15 83 22.090722 22.090722 22.090722
+15 84 34.928498 34.928498 34.928498
+15 85 54.405882 54.405882 54.405882
+15 86 62.032250 62.032250 62.032250
+15 87 26.400758 26.400758 26.400758
+15 88 22.135944 22.135944 22.135944
+15 89 23.021729 23.021729 23.021729
+15 90 73.783467 73.783467 73.783467
+15 91 32.062439 32.062439 32.062439
+15 92 44.102154 44.102154 44.102154
+15 93 48.041649 48.041649 48.041649
+15 94 56.435804 56.435804 56.435804
+15 95 52.086467 52.086467 52.086467
+15 96 51.623638 51.623638 51.623638
+15 97 50.803543 50.803543 50.803543
+15 98 27.018512 27.018512 27.018512
+15 99 22.135944 22.135944 22.135944
+15 100 23.259407 23.259407 23.259407
+15 101 34.058773 34.058773 34.058773
+16 1 39.293765 39.293765 39.293765
+16 2 50.537115 50.537115 50.537115
+16 3 40.311289 40.311289 40.311289
+16 4 49.244289 49.244289 49.244289
+16 5 43.863424 43.863424 43.863424
+16 6 48.466483 48.466483 48.466483
+16 7 38.483763 38.483763 38.483763
+16 8 37.336309 37.336309 37.336309
+16 9 42.059482 42.059482 42.059482
+16 10 9.433981 9.433981 9.433981
+16 11 8.000000 8.000000 8.000000
+16 12 6.000000 6.000000 6.000000
+16 13 7.810250 7.810250 7.810250
+16 14 5.830952 5.830952 5.830952
+16 15 5.830952 5.830952 5.830952
+16 17 2.000000 2.000000 2.000000
+16 18 5.385165 5.385165 5.385165
+16 19 54.671748 54.671748 54.671748
+16 20 50.000000 50.000000 50.000000
+16 21 47.169906 47.169906 47.169906
+16 22 51.662365 51.662365 51.662365
+16 23 45.486262 45.486262 45.486262
+16 24 50.209561 50.209561 50.209561
+16 25 43.829214 43.829214 43.829214
+16 26 48.104054 48.104054 48.104054
+16 27 93.536089 93.536089 93.536089
+16 28 93.134312 93.134312 93.134312
+16 29 90.553851 90.553851 90.553851
+16 30 88.141931 88.141931 88.141931
+16 31 86.579443 86.579443 86.579443
+16 32 86.145226 86.145226 86.145226
+16 33 85.586214 85.586214 85.586214
+16 34 84.344532 84.344532 84.344532
+16 35 83.150466 83.150466 83.150466
+16 36 79.056942 79.056942 79.056942
+16 37 77.420927 77.420927 77.420927
+16 38 75.716577 75.716577 75.716577
+16 39 72.111026 72.111026 72.111026
+16 40 70.455660 70.455660 70.455660
+16 41 73.409809 73.409809 73.409809
+16 42 66.037868 66.037868 66.037868
+16 43 66.400301 66.400301 66.400301
+16 44 69.526973 69.526973 69.526973
+16 45 67.623960 67.623960 67.623960
+16 46 45.694639 45.694639 45.694639
+16 47 43.081318 43.081318 43.081318
+16 48 5.000000 5.000000 5.000000
+16 49 53.150729 53.150729 53.150729
+16 50 48.826222 48.826222 48.826222
+16 51 70.178344 70.178344 70.178344
+16 52 56.648036 56.648036 56.648036
+16 53 25.079872 25.079872 25.079872
+16 54 20.591260 20.591260 20.591260
+16 55 56.648036 56.648036 56.648036
+16 56 34.409301 34.409301 34.409301
+16 57 48.259714 48.259714 48.259714
+16 58 31.764760 31.764760 31.764760
+16 59 32.695565 32.695565 32.695565
+16 60 21.540659 21.540659 21.540659
+16 61 23.853721 23.853721 23.853721
+16 62 49.739320 49.739320 49.739320
+16 63 63.198101 63.198101 63.198101
+16 64 66.098411 66.098411 66.098411
+16 65 44.147480 44.147480 44.147480
+16 66 33.000000 33.000000 33.000000
+16 67 39.115214 39.115214 39.115214
+16 68 62.032250 62.032250 62.032250
+16 69 42.941821 42.941821 42.941821
+16 70 31.384710 31.384710 31.384710
+16 71 43.931765 43.931765 43.931765
+16 72 64.761099 64.761099 64.761099
+16 73 65.924199 65.924199 65.924199
+16 74 20.000000 20.000000 20.000000
+16 75 26.907248 26.907248 26.907248
+16 76 35.128336 35.128336 35.128336
+16 77 64.404969 64.404969 64.404969
+16 78 42.544095 42.544095 42.544095
+16 79 17.088007 17.088007 17.088007
+16 80 28.284271 28.284271 28.284271
+16 81 45.541190 45.541190 45.541190
+16 82 50.328918 50.328918 50.328918
+16 83 25.179357 25.179357 25.179357
+16 84 36.138622 36.138622 36.138622
+16 85 56.089215 56.089215 56.089215
+16 86 63.324561 63.324561 63.324561
+16 87 24.839485 24.839485 24.839485
+16 88 18.867962 18.867962 18.867962
+16 89 28.425341 28.425341 28.425341
+16 90 73.824115 73.824115 73.824115
+16 91 35.693137 35.693137 35.693137
+16 92 47.042534 47.042534 47.042534
+16 93 51.088159 51.088159 51.088159
+16 94 60.207973 60.207973 60.207973
+16 95 55.578773 55.578773 55.578773
+16 96 54.083269 54.083269 54.083269
+16 97 54.817880 54.817880 54.817880
+16 98 22.090722 22.090722 22.090722
+16 99 26.832816 26.832816 26.832816
+16 100 24.515301 24.515301 24.515301
+16 101 39.623226 39.623226 39.623226
+17 1 41.231056 41.231056 41.231056
+17 2 51.478151 51.478151 51.478151
+17 3 41.340053 41.340053 41.340053
+17 4 50.089919 50.089919 50.089919
+17 5 44.721360 44.721360 44.721360
+17 6 49.244289 49.244289 49.244289
+17 7 39.357337 39.357337 39.357337
+17 8 38.078866 38.078866 38.078866
+17 9 42.720019 42.720019 42.720019
+17 10 11.180340 11.180340 11.180340
+17 11 10.000000 10.000000 10.000000
+17 12 8.000000 8.000000 8.000000
+17 13 9.433981 9.433981 9.433981
+17 14 7.071068 7.071068 7.071068
+17 15 7.071068 7.071068 7.071068
+17 16 2.000000 2.000000 2.000000
+17 18 5.000000 5.000000 5.000000
+17 19 56.222771 56.222771 56.222771
+17 20 51.613952 51.613952 51.613952
+17 21 48.877398 48.877398 48.877398
+17 22 53.150729 53.150729 53.150729
+17 23 47.169906 47.169906 47.169906
+17 24 51.662365 51.662365 51.662365
+17 25 45.486262 45.486262 45.486262
+17 26 49.497475 49.497475 49.497475
+17 27 95.524866 95.524866 95.524866
+17 28 95.131488 95.131488 95.131488
+17 29 92.541882 92.541882 92.541882
+17 30 90.138782 90.138782 90.138782
+17 31 88.566359 88.566359 88.566359
+17 32 88.141931 88.141931 88.141931
+17 33 87.572827 87.572827 87.572827
+17 34 86.313383 86.313383 86.313383
+17 35 85.146932 85.146932 85.146932
+17 36 80.709355 80.709355 80.709355
+17 37 79.056942 79.056942 79.056942
+17 38 77.388630 77.388630 77.388630
+17 39 73.783467 73.783467 73.783467
+17 40 72.111026 72.111026 72.111026
+17 41 75.000000 75.000000 75.000000
+17 42 67.742158 67.742158 67.742158
+17 43 68.007353 68.007353 68.007353
+17 44 71.063352 71.063352 71.063352
+17 45 69.202601 69.202601 69.202601
+17 46 46.518813 46.518813 46.518813
+17 47 43.863424 43.863424 43.863424
+17 48 5.385165 5.385165 5.385165
+17 49 54.671748 54.671748 54.671748
+17 50 50.477718 50.477718 50.477718
+17 51 72.173402 72.173402 72.173402
+17 52 58.523500 58.523500 58.523500
+17 53 26.925824 26.925824 26.925824
+17 54 22.360680 22.360680 22.360680
+17 55 58.523500 58.523500 58.523500
+17 56 36.055513 36.055513 36.055513
+17 57 50.249378 50.249378 50.249378
+17 58 33.541020 33.541020 33.541020
+17 59 33.541020 33.541020 33.541020
+17 60 22.360680 22.360680 22.360680
+17 61 25.000000 25.000000 25.000000
+17 62 51.478151 51.478151 51.478151
+17 63 65.192024 65.192024 65.192024
+17 64 68.007353 68.007353 68.007353
+17 65 46.097722 46.097722 46.097722
+17 66 35.000000 35.000000 35.000000
+17 67 41.109610 41.109610 41.109610
+17 68 64.031242 64.031242 64.031242
+17 69 44.721360 44.721360 44.721360
+17 70 33.241540 33.241540 33.241540
+17 71 45.453273 45.453273 45.453273
+17 72 66.708320 66.708320 66.708320
+17 73 67.779053 67.779053 67.779053
+17 74 20.099751 20.099751 20.099751
+17 75 28.284271 28.284271 28.284271
+17 76 35.355339 35.355339 35.355339
+17 77 66.211781 66.211781 66.211781
+17 78 43.566042 43.566042 43.566042
+17 79 17.888544 17.888544 17.888544
+17 80 28.635642 28.635642 28.635642
+17 81 47.518417 47.518417 47.518417
+17 82 52.201533 52.201533 52.201533
+17 83 27.166155 27.166155 27.166155
+17 84 38.078866 38.078866 38.078866
+17 85 58.051701 58.051701 58.051701
+17 86 65.253352 65.253352 65.253352
+17 87 26.400758 26.400758 26.400758
+17 88 20.000000 20.000000 20.000000
+17 89 30.000000 30.000000 30.000000
+17 90 75.591005 75.591005 75.591005
+17 91 37.656341 37.656341 37.656341
+17 92 49.040799 49.040799 49.040799
+17 93 53.084838 53.084838 53.084838
+17 94 62.169124 62.169124 62.169124
+17 95 57.558666 57.558666 57.558666
+17 96 56.080300 56.080300 56.080300
+17 97 56.753854 56.753854 56.753854
+17 98 22.360680 22.360680 22.360680
+17 99 28.635642 28.635642 28.635642
+17 100 26.476405 26.476405 26.476405
+17 101 41.109610 41.109610 41.109610
+18 1 40.311289 40.311289 40.311289
+18 2 47.169906 47.169906 47.169906
+18 3 37.202150 37.202150 37.202150
+18 4 45.650849 45.650849 45.650849
+18 5 40.311289 40.311289 40.311289
+18 6 44.721360 44.721360 44.721360
+18 7 34.985711 34.985711 34.985711
+18 8 33.541020 33.541020 33.541020
+18 9 38.078866 38.078866 38.078866
+18 10 14.142136 14.142136 14.142136
+18 11 11.180340 11.180340 11.180340
+18 12 9.433981 9.433981 9.433981
+18 13 8.000000 8.000000 8.000000
+18 14 11.180340 11.180340 11.180340
+18 15 5.000000 5.000000 5.000000
+18 16 5.385165 5.385165 5.385165
+18 17 5.000000 5.000000 5.000000
+18 19 59.464275 59.464275 59.464275
+18 20 54.671748 54.671748 54.671748
+18 21 51.613952 51.613952 51.613952
+18 22 56.568542 56.568542 56.568542
+18 23 50.000000 50.000000 50.000000
+18 24 55.172457 55.172457 55.172457
+18 25 48.414874 48.414874 48.414874
+18 26 53.150729 53.150729 53.150729
+18 27 96.176920 96.176920 96.176920
+18 28 95.524866 95.524866 95.524866
+18 29 93.214806 93.214806 93.214806
+18 30 90.553851 90.553851 90.553851
+18 31 89.269256 89.269256 89.269256
+18 32 88.566359 88.566359 88.566359
+18 33 88.283634 88.283634 88.283634
+18 34 87.321246 87.321246 87.321246
+18 35 85.586214 85.586214 85.586214
+18 36 78.032045 78.032045 78.032045
+18 37 76.321688 76.321688 76.321688
+18 38 74.793048 74.793048 74.793048
+18 39 71.196910 71.196910 71.196910
+18 40 69.462220 69.462220 69.462220
+18 41 72.111026 72.111026 72.111026
+18 42 65.299311 65.299311 65.299311
+18 43 65.192024 65.192024 65.192024
+18 44 68.007353 68.007353 68.007353
+18 45 66.287254 66.287254 66.287254
+18 46 42.059482 42.059482 42.059482
+18 47 39.357337 39.357337 39.357337
+18 48 2.000000 2.000000 2.000000
+18 49 58.000000 58.000000 58.000000
+18 50 53.413481 53.413481 53.413481
+18 51 72.691127 72.691127 72.691127
+18 52 60.415230 60.415230 60.415230
+18 53 29.154759 29.154759 29.154759
+18 54 20.615528 20.615528 20.615528
+18 55 57.008771 57.008771 57.008771
+18 56 33.541020 33.541020 33.541020
+18 57 50.990195 50.990195 50.990195
+18 58 36.055513 36.055513 36.055513
+18 59 38.078866 38.078866 38.078866
+18 60 26.925824 26.925824 26.925824
+18 61 21.213203 21.213203 21.213203
+18 62 49.244289 49.244289 49.244289
+18 63 65.764732 65.764732 65.764732
+18 64 69.641941 69.641941 69.641941
+18 65 47.434165 47.434165 47.434165
+18 66 35.355339 35.355339 35.355339
+18 67 41.773197 41.773197 41.773197
+18 68 64.070274 64.070274 64.070274
+18 69 42.720019 42.720019 42.720019
+18 70 31.780497 31.780497 31.780497
+18 71 42.438190 42.438190 42.438190
+18 72 65.764732 65.764732 65.764732
+18 73 66.098411 66.098411 66.098411
+18 74 15.132746 15.132746 15.132746
+18 75 32.015621 32.015621 32.015621
+18 76 40.311289 40.311289 40.311289
+18 77 68.476273 68.476273 68.476273
+18 78 47.885280 47.885280 47.885280
+18 79 13.601471 13.601471 13.601471
+18 80 23.769729 23.769729 23.769729
+18 81 47.042534 47.042534 47.042534
+18 82 50.695167 50.695167 50.695167
+18 83 27.073973 27.073973 27.073973
+18 84 39.560081 39.560081 39.560081
+18 85 59.203040 59.203040 59.203040
+18 86 66.730802 66.730802 66.730802
+18 87 29.698485 29.698485 29.698485
+18 88 24.186773 24.186773 24.186773
+18 89 27.294688 27.294688 27.294688
+18 90 78.032045 78.032045 78.032045
+18 91 37.054015 37.054015 37.054015
+18 92 49.091751 49.091751 49.091751
+18 93 53.037722 53.037722 53.037722
+18 94 61.400326 61.400326 61.400326
+18 95 57.078893 57.078893 57.078893
+18 96 56.568542 56.568542 56.568542
+18 97 55.731499 55.731499 55.731499
+18 98 27.294688 27.294688 27.294688
+18 99 26.925824 26.925824 26.925824
+18 100 27.856777 27.856777 27.856777
+18 101 38.013156 38.013156 38.013156
+19 1 45.177428 45.177428 45.177428
+19 2 82.225300 82.225300 82.225300
+19 3 73.375745 73.375745 73.375745
+19 4 82.969874 82.969874 82.969874
+19 5 78.746428 78.746428 78.746428
+19 6 83.522452 83.522452 83.522452
+19 7 74.672619 74.672619 74.672619
+19 8 75.769387 75.769387 75.769387
+19 9 80.411442 80.411442 80.411442
+19 10 45.343136 45.343136 45.343136
+19 11 48.795492 48.795492 48.795492
+19 12 50.209561 50.209561 50.209561
+19 13 53.814496 53.814496 53.814496
+19 14 49.203658 49.203658 49.203658
+19 15 55.865911 55.865911 55.865911
+19 16 54.671748 54.671748 54.671748
+19 17 56.222771 56.222771 56.222771
+19 18 59.464275 59.464275 59.464275
+19 20 5.385165 5.385165 5.385165
+19 21 10.198039 10.198039 10.198039
+19 22 4.000000 4.000000 4.000000
+19 23 10.770330 10.770330 10.770330
+19 24 6.000000 6.000000 6.000000
+19 25 11.661904 11.661904 11.661904
+19 26 9.000000 9.000000 9.000000
+19 27 56.797887 56.797887 56.797887
+19 28 59.169249 59.169249 59.169249
+19 29 54.120237 54.120237 54.120237
+19 30 54.918121 54.918121 54.918121
+19 31 50.606324 50.606324 50.606324
+19 32 53.254108 53.254108 53.254108
+19 33 49.739320 49.739320 49.739320
+19 34 45.617979 45.617979 45.617979
+19 35 50.803543 50.803543 50.803543
+19 36 83.240615 83.240615 83.240615
+19 37 82.710338 82.710338 82.710338
+19 38 79.812280 79.812280 79.812280
+19 39 77.129761 77.129761 77.129761
+19 40 76.687678 76.687678 76.687678
+19 41 81.584312 81.584312 81.584312
+19 42 71.386273 71.386273 71.386273
+19 43 75.802375 75.802375 75.802375
+19 44 80.752709 80.752709 80.752709
+19 45 77.781746 77.781746 77.781746
+19 46 80.653580 80.653580 80.653580
+19 47 79.378838 79.378838 79.378838
+19 48 58.000000 58.000000 58.000000
+19 49 2.000000 2.000000 2.000000
+19 50 7.280110 7.280110 7.280110
+19 51 41.036569 41.036569 41.036569
+19 52 18.601075 18.601075 18.601075
+19 53 31.400637 31.400637 31.400637
+19 54 51.000000 51.000000 51.000000
+19 55 56.089215 56.089215 56.089215
+19 56 56.753854 56.753854 56.753854
+19 57 30.594117 30.594117 30.594117
+19 58 24.413111 24.413111 24.413111
+19 59 29.427878 29.427878 29.427878
+19 60 37.161808 37.161808 37.161808
+19 61 62.177166 62.177166 62.177166
+19 62 60.008333 60.008333 60.008333
+19 63 36.619667 36.619667 36.619667
+19 64 25.806976 25.806976 25.806976
+19 65 25.019992 25.019992 25.019992
+19 66 36.138622 36.138622 36.138622
+19 67 32.140317 32.140317 32.140317
+19 68 42.059482 42.059482 42.059482
+19 69 55.145263 55.145263 55.145263
+19 70 48.764741 48.764741 48.764741
+19 71 64.629715 64.629715 64.629715
+19 72 54.230987 54.230987 54.230987
+19 73 62.936476 62.936476 62.936476
+19 74 69.202601 69.202601 69.202601
+19 75 28.301943 28.301943 28.301943
+19 76 39.000000 39.000000 39.000000
+19 77 17.464249 17.464249 17.464249
+19 78 21.095023 21.095023 21.095023
+19 79 62.425956 62.425956 62.425956
+19 80 73.573093 73.573093 73.573093
+19 81 42.107007 42.107007 42.107007
+19 82 53.235327 53.235327 53.235327
+19 83 41.629317 41.629317 41.629317
+19 84 26.925824 26.925824 26.925824
+19 85 27.294688 27.294688 27.294688
+19 86 26.172505 26.172505 26.172505
+19 87 29.832868 29.832868 29.832868
+19 88 37.215588 37.215588 37.215588
+19 89 56.648036 56.648036 56.648036
+19 90 23.000000 23.000000 23.000000
+19 91 42.579338 42.579338 42.579338
+19 92 37.336309 37.336309 37.336309
+19 93 39.051248 39.051248 39.051248
+19 94 49.979996 49.979996 49.979996
+19 95 44.922155 44.922155 44.922155
+19 96 34.176015 34.176015 34.176015
+19 97 50.219518 50.219518 50.219518
+19 98 42.059482 42.059482 42.059482
+19 99 50.328918 50.328918 50.328918
+19 100 34.985711 34.985711 34.985711
+19 101 63.348244 63.348244 63.348244
+20 1 40.049969 40.049969 40.049969
+20 2 76.902536 76.902536 76.902536
+20 3 68.007353 68.007353 68.007353
+20 4 77.620873 77.620873 77.620873
+20 5 73.375745 73.375745 73.375745
+20 6 78.160092 78.160092 78.160092
+20 7 69.289249 69.289249 69.289249
+20 8 70.384657 70.384657 70.384657
+20 9 75.026662 75.026662 75.026662
+20 10 40.607881 40.607881 40.607881
+20 11 43.863424 43.863424 43.863424
+20 12 45.343136 45.343136 45.343136
+20 13 48.795492 48.795492 48.795492
+20 14 44.654227 44.654227 44.654227
+20 15 50.931326 50.931326 50.931326
+20 16 50.000000 50.000000 50.000000
+20 17 51.613952 51.613952 51.613952
+20 18 54.671748 54.671748 54.671748
+20 19 5.385165 5.385165 5.385165
+20 21 5.000000 5.000000 5.000000
+20 22 5.385165 5.385165 5.385165
+20 23 5.385165 5.385165 5.385165
+20 24 6.403124 6.403124 6.403124
+20 25 6.403124 6.403124 6.403124
+20 26 8.602325 8.602325 8.602325
+20 27 56.648036 56.648036 56.648036
+20 28 58.600341 58.600341 58.600341
+20 29 53.851648 53.851648 53.851648
+20 30 54.120237 54.120237 54.120237
+20 31 50.159745 50.159745 50.159745
+20 32 52.354560 52.354560 52.354560
+20 33 49.244289 49.244289 49.244289
+20 34 45.541190 45.541190 45.541190
+20 35 49.739320 49.739320 49.739320
+20 36 79.056942 79.056942 79.056942
+20 37 78.447435 78.447435 78.447435
+20 38 75.584390 75.584390 75.584390
+20 39 72.801099 72.801099 72.801099
+20 40 72.277244 72.277244 72.277244
+20 41 77.129761 77.129761 77.129761
+20 42 66.940272 66.940272 66.940272
+20 43 71.196910 71.196910 71.196910
+20 44 76.118329 76.118329 76.118329
+20 45 73.164199 73.164199 73.164199
+20 46 75.286121 75.286121 75.286121
+20 47 74.000000 74.000000 74.000000
+20 48 53.150729 53.150729 53.150729
+20 49 5.000000 5.000000 5.000000
+20 50 2.000000 2.000000 2.000000
+20 51 39.051248 39.051248 39.051248
+20 52 16.401219 16.401219 16.401219
+20 53 26.248809 26.248809 26.248809
+20 54 45.650849 45.650849 45.650849
+20 55 51.662365 51.662365 51.662365
+20 56 51.419841 51.419841 51.419841
+20 57 26.248809 26.248809 26.248809
+20 58 19.209373 19.209373 19.209373
+20 59 27.000000 27.000000 27.000000
+20 60 33.526109 33.526109 33.526109
+20 61 56.824291 56.824291 56.824291
+20 62 55.081757 55.081757 55.081757
+20 63 33.970576 33.970576 33.970576
+20 64 25.079872 25.079872 25.079872
+20 65 20.223748 20.223748 20.223748
+20 66 30.805844 30.805844 30.805844
+20 67 27.018512 27.018512 27.018512
+20 68 38.832976 38.832976 38.832976
+20 69 50.039984 50.039984 50.039984
+20 70 43.416587 43.416587 43.416587
+20 71 59.413803 59.413803 59.413803
+20 72 50.537115 50.537115 50.537115
+20 73 58.872744 58.872744 58.872744
+20 74 64.031242 64.031242 64.031242
+20 75 24.166092 24.166092 24.166092
+20 76 37.336309 37.336309 37.336309
+20 77 18.110770 18.110770 18.110770
+20 78 20.248457 20.248457 20.248457
+20 79 57.201399 57.201399 57.201399
+20 80 68.264193 68.264193 68.264193
+20 81 37.336309 37.336309 37.336309
+20 82 48.507731 48.507731 48.507731
+20 83 36.249138 36.249138 36.249138
+20 84 21.587033 21.587033 21.587033
+20 85 24.207437 24.207437 24.207437
+20 86 24.698178 24.698178 24.698178
+20 87 25.238859 25.238859 25.238859
+20 88 33.105891 33.105891 33.105891
+20 89 51.264022 51.264022 51.264022
+20 90 25.495098 25.495098 25.495098
+20 91 37.336309 37.336309 37.336309
+20 92 32.756679 32.756679 32.756679
+20 93 34.785054 34.785054 34.785054
+20 94 46.097722 46.097722 46.097722
+20 95 40.853396 40.853396 40.853396
+20 96 30.413813 30.413813 30.413813
+20 97 45.880279 45.880279 45.880279
+20 98 38.832976 38.832976 38.832976
+20 99 44.944410 44.944410 44.944410
+20 100 29.681644 29.681644 29.681644
+20 101 58.051701 58.051701 58.051701
+21 1 35.057096 35.057096 35.057096
+21 2 72.034714 72.034714 72.034714
+21 3 63.245553 63.245553 63.245553
+21 4 72.801099 72.801099 72.801099
+21 5 68.622154 68.622154 68.622154
+21 6 73.375745 73.375745 73.375745
+21 7 64.621978 64.621978 64.621978
+21 8 65.795137 65.795137 65.795137
+21 9 70.384657 70.384657 70.384657
+21 10 37.735925 37.735925 37.735925
+21 11 40.607881 40.607881 40.607881
+21 12 42.201896 42.201896 42.201896
+21 13 45.343136 45.343136 45.343136
+21 14 42.059482 42.059482 42.059482
+21 15 47.634021 47.634021 47.634021
+21 16 47.169906 47.169906 47.169906
+21 17 48.877398 48.877398 48.877398
+21 18 51.613952 51.613952 51.613952
+21 19 10.198039 10.198039 10.198039
+21 20 5.000000 5.000000 5.000000
+21 22 10.198039 10.198039 10.198039
+21 23 2.000000 2.000000 2.000000
+21 24 10.770330 10.770330 10.770330
+21 25 4.000000 4.000000 4.000000
+21 26 12.206556 12.206556 12.206556
+21 27 55.081757 55.081757 55.081757
+21 28 56.648036 56.648036 56.648036
+21 29 52.201533 52.201533 52.201533
+21 30 52.000000 52.000000 52.000000
+21 31 48.383882 48.383882 48.383882
+21 32 50.159745 50.159745 50.159745
+21 33 47.434165 47.434165 47.434165
+21 34 44.147480 44.147480 44.147480
+21 35 47.423623 47.423623 47.423623
+21 36 74.330344 74.330344 74.330344
+21 37 73.681748 73.681748 73.681748
+21 38 70.837843 70.837843 70.837843
+21 39 68.007353 68.007353 68.007353
+21 40 67.446275 67.446275 67.446275
+21 41 72.277244 72.277244 72.277244
+21 42 62.096699 62.096699 62.096699
+21 43 66.287254 66.287254 66.287254
+21 44 71.196910 71.196910 71.196910
+21 45 68.249542 68.249542 68.249542
+21 46 70.519501 70.519501 70.519501
+21 47 69.289249 69.289249 69.289249
+21 48 50.000000 50.000000 50.000000
+21 49 10.000000 10.000000 10.000000
+21 50 3.000000 3.000000 3.000000
+21 51 36.055513 36.055513 36.055513
+21 52 13.928388 13.928388 13.928388
+21 53 22.671568 22.671568 22.671568
+21 54 41.340053 41.340053 41.340053
+21 55 46.840154 46.840154 46.840154
+21 56 46.572524 46.572524 46.572524
+21 57 21.540659 21.540659 21.540659
+21 58 15.620499 15.620499 15.620499
+21 59 27.459060 27.459060 27.459060
+21 60 32.388269 32.388269 32.388269
+21 61 52.478567 52.478567 52.478567
+21 62 50.089919 50.089919 50.089919
+21 63 30.479501 30.479501 30.479501
+21 64 23.537205 23.537205 23.537205
+21 65 15.297059 15.297059 15.297059
+21 66 25.961510 25.961510 25.961510
+21 67 22.022716 22.022716 22.022716
+21 68 34.828150 34.828150 34.828150
+21 69 45.044423 45.044423 45.044423
+21 70 38.600518 38.600518 38.600518
+21 71 54.451814 54.451814 54.451814
+21 72 46.141088 46.141088 46.141088
+21 73 54.230987 54.230987 54.230987
+21 74 60.207973 60.207973 60.207973
+21 75 22.561028 22.561028 22.561028
+21 76 38.327536 38.327536 38.327536
+21 77 18.248288 18.248288 18.248288
+21 78 22.472205 22.472205 22.472205
+21 79 53.263496 53.263496 53.263496
+21 80 64.070274 64.070274 64.070274
+21 81 32.388269 32.388269 32.388269
+21 82 43.566042 43.566042 43.566042
+21 83 31.764760 31.764760 31.764760
+21 84 16.763055 16.763055 16.763055
+21 85 20.518285 20.518285 20.518285
+21 86 22.472205 22.472205 22.472205
+21 87 22.847319 22.847319 22.847319
+21 88 31.320920 31.320920 31.320920
+21 89 46.615448 46.615448 46.615448
+21 90 26.925824 26.925824 26.925824
+21 91 32.388269 32.388269 32.388269
+21 92 27.892651 27.892651 27.892651
+21 93 30.083218 30.083218 30.083218
+21 94 41.593269 41.593269 41.593269
+21 95 36.249138 36.249138 36.249138
+21 96 26.076810 26.076810 26.076810
+21 97 41.109610 41.109610 41.109610
+21 98 38.118237 38.118237 38.118237
+21 99 40.311289 40.311289 40.311289
+21 100 25.612497 25.612497 25.612497
+21 101 53.150729 53.150729 53.150729
+22 1 45.000000 45.000000 45.000000
+22 2 81.394103 81.394103 81.394103
+22 3 72.277244 72.277244 72.277244
+22 4 82.000000 82.000000 82.000000
+22 5 77.620873 77.620873 77.620873
+22 6 82.462113 82.462113 82.462113
+22 7 73.375745 73.375745 73.375745
+22 8 74.330344 74.330344 74.330344
+22 9 79.056942 79.056942 79.056942
+22 10 42.426407 42.426407 42.426407
+22 11 46.097722 46.097722 46.097722
+22 12 47.423623 47.423623 47.423623
+22 13 51.224994 51.224994 51.224994
+22 14 46.097722 46.097722 46.097722
+22 15 53.150729 53.150729 53.150729
+22 16 51.662365 51.662365 51.662365
+22 17 53.150729 53.150729 53.150729
+22 18 56.568542 56.568542 56.568542
+22 19 4.000000 4.000000 4.000000
+22 20 5.385165 5.385165 5.385165
+22 21 10.198039 10.198039 10.198039
+22 23 10.000000 10.000000 10.000000
+22 24 2.000000 2.000000 2.000000
+22 25 10.198039 10.198039 10.198039
+22 26 5.000000 5.000000 5.000000
+22 27 60.415230 60.415230 60.415230
+22 28 62.649820 62.649820 62.649820
+22 29 57.697487 57.697487 57.697487
+22 30 58.309519 58.309519 58.309519
+22 31 54.120237 54.120237 54.120237
+22 32 56.603887 56.603887 56.603887
+22 33 53.235327 53.235327 53.235327
+22 34 49.244289 49.244289 49.244289
+22 35 54.083269 54.083269 54.083269
+22 36 84.433406 84.433406 84.433406
+22 37 83.815273 83.815273 83.815273
+22 38 80.956779 80.956779 80.956779
+22 39 78.160092 78.160092 78.160092
+22 40 77.620873 77.620873 77.620873
+22 41 82.462113 82.462113 82.462113
+22 42 72.277244 72.277244 72.277244
+22 43 76.485293 76.485293 76.485293
+22 44 81.394103 81.394103 81.394103
+22 45 78.447435 78.447435 78.447435
+22 46 79.555012 79.555012 79.555012
+22 47 78.160092 78.160092 78.160092
+22 48 55.172457 55.172457 55.172457
+22 49 2.000000 2.000000 2.000000
+22 50 7.280110 7.280110 7.280110
+22 51 43.863424 43.863424 43.863424
+22 52 21.213203 21.213203 21.213203
+22 53 29.154759 29.154759 29.154759
+22 54 49.244289 49.244289 49.244289
+22 55 57.008771 57.008771 57.008771
+22 56 55.901699 55.901699 55.901699
+22 57 31.622777 31.622777 31.622777
+22 58 22.360680 22.360680 22.360680
+22 59 25.495098 25.495098 25.495098
+22 60 33.541020 33.541020 33.541020
+22 61 60.415230 60.415230 60.415230
+22 62 60.207973 60.207973 60.207973
+22 63 39.051248 39.051248 39.051248
+22 64 29.154759 29.154759 29.154759
+22 65 25.495098 25.495098 25.495098
+22 66 35.355339 35.355339 35.355339
+22 67 32.015621 32.015621 32.015621
+22 68 44.102154 44.102154 44.102154
+22 69 55.000000 55.000000 55.000000
+22 70 47.853944 47.853944 47.853944
+22 71 64.195015 64.195015 64.195015
+22 72 55.901699 55.901699 55.901699
+22 73 64.257295 64.257295 64.257295
+22 74 66.850580 66.850580 66.850580
+22 75 25.000000 25.000000 25.000000
+22 76 35.000000 35.000000 35.000000
+22 77 21.189620 21.189620 21.189620
+22 78 17.117243 17.117243 17.117243
+22 79 60.207973 60.207973 60.207973
+22 80 71.589105 71.589105 71.589105
+22 81 42.579338 42.579338 42.579338
+22 82 53.758720 53.758720 53.758720
+22 83 40.162171 40.162171 40.162171
+22 84 26.172505 26.172505 26.172505
+22 85 29.410882 29.410882 29.410882
+22 86 29.206164 29.206164 29.206164
+22 87 26.870058 26.870058 26.870058
+22 88 33.837849 33.837849 33.837849
+22 89 55.362442 55.362442 55.362442
+22 90 27.000000 27.000000 27.000000
+22 91 42.107007 42.107007 42.107007
+22 92 38.078866 38.078866 38.078866
+22 93 40.162171 40.162171 40.162171
+22 94 51.478151 51.478151 51.478151
+22 95 46.238512 46.238512 46.238512
+22 96 35.777088 35.777088 35.777088
+22 97 51.244512 51.244512 51.244512
+22 98 38.275318 38.275318 38.275318
+22 99 49.040799 49.040799 49.040799
+22 100 33.105891 33.105891 33.105891
+22 101 62.649820 62.649820 62.649820
+23 1 35.000000 35.000000 35.000000
+23 2 71.589105 71.589105 71.589105
+23 3 62.641839 62.641839 62.641839
+23 4 72.277244 72.277244 72.277244
+23 5 68.007353 68.007353 68.007353
+23 6 72.801099 72.801099 72.801099
+23 7 63.906181 63.906181 63.906181
+23 8 65.000000 65.000000 65.000000
+23 9 69.641941 69.641941 69.641941
+23 10 36.055513 36.055513 36.055513
+23 11 39.051248 39.051248 39.051248
+23 12 40.607881 40.607881 40.607881
+23 13 43.863424 43.863424 43.863424
+23 14 40.311289 40.311289 40.311289
+23 15 46.097722 46.097722 46.097722
+23 16 45.486262 45.486262 45.486262
+23 17 47.169906 47.169906 47.169906
+23 18 50.000000 50.000000 50.000000
+23 19 10.770330 10.770330 10.770330
+23 20 5.385165 5.385165 5.385165
+23 21 2.000000 2.000000 2.000000
+23 22 10.000000 10.000000 10.000000
+23 24 10.198039 10.198039 10.198039
+23 25 2.000000 2.000000 2.000000
+23 26 11.180340 11.180340 11.180340
+23 27 57.008771 57.008771 57.008771
+23 28 58.523500 58.523500 58.523500
+23 29 54.120237 54.120237 54.120237
+23 30 53.851648 53.851648 53.851648
+23 31 50.289164 50.289164 50.289164
+23 32 52.000000 52.000000 52.000000
+23 33 49.335586 49.335586 49.335586
+23 34 46.097722 46.097722 46.097722
+23 35 49.244289 49.244289 49.244289
+23 36 75.026662 75.026662 75.026662
+23 37 74.330344 74.330344 74.330344
+23 38 71.512237 71.512237 71.512237
+23 39 68.622154 68.622154 68.622154
+23 40 68.007353 68.007353 68.007353
+23 41 72.801099 72.801099 72.801099
+23 42 62.641839 62.641839 62.641839
+23 43 66.708320 66.708320 66.708320
+23 44 71.589105 71.589105 71.589105
+23 45 68.658576 68.658576 68.658576
+23 46 69.921384 69.921384 69.921384
+23 47 68.622154 68.622154 68.622154
+23 48 48.414874 48.414874 48.414874
+23 49 10.198039 10.198039 10.198039
+23 50 3.605551 3.605551 3.605551
+23 51 37.735925 37.735925 37.735925
+23 52 15.811388 15.811388 15.811388
+23 53 21.213203 21.213203 21.213203
+23 54 40.311289 40.311289 40.311289
+23 55 47.434165 47.434165 47.434165
+23 56 46.097722 46.097722 46.097722
+23 57 22.360680 22.360680 22.360680
+23 58 14.142136 14.142136 14.142136
+23 59 25.495098 25.495098 25.495098
+23 60 30.413813 30.413813 30.413813
+23 61 51.478151 51.478151 51.478151
+23 62 50.249378 50.249378 50.249378
+23 63 32.015621 32.015621 32.015621
+23 64 25.495098 25.495098 25.495098
+23 65 15.811388 15.811388 15.811388
+23 66 25.495098 25.495098 25.495098
+23 67 22.022716 22.022716 22.022716
+23 68 36.124784 36.124784 36.124784
+23 69 45.000000 45.000000 45.000000
+23 70 38.078866 38.078866 38.078866
+23 71 54.230987 54.230987 54.230987
+23 72 47.169906 47.169906 47.169906
+23 73 55.036352 55.036352 55.036352
+23 74 58.898217 58.898217 58.898217
+23 75 20.615528 20.615528 20.615528
+23 76 36.400549 36.400549 36.400549
+23 77 20.223748 20.223748 20.223748
+23 78 20.808652 20.808652 20.808652
+23 79 52.009614 52.009614 52.009614
+23 80 62.968246 62.968246 62.968246
+23 81 32.756679 32.756679 32.756679
+23 82 43.931765 43.931765 43.931765
+23 83 30.870698 30.870698 30.870698
+23 84 16.278821 16.278821 16.278821
+23 85 22.022716 22.022716 22.022716
+23 86 24.351591 24.351591 24.351591
+23 87 21.023796 21.023796 21.023796
+23 88 29.410882 29.410882 29.410882
+23 89 45.880279 45.880279 45.880279
+23 90 28.792360 28.792360 28.792360
+23 91 32.140317 32.140317 32.140317
+23 92 28.460499 28.460499 28.460499
+23 93 30.870698 30.870698 30.870698
+23 94 42.544095 42.544095 42.544095
+23 95 37.121422 37.121422 37.121422
+23 96 27.202941 27.202941 27.202941
+23 97 41.785165 41.785165 41.785165
+23 98 36.124784 36.124784 36.124784
+23 99 39.560081 39.560081 39.560081
+23 100 24.413111 24.413111 24.413111
+23 101 52.773099 52.773099 52.773099
+24 1 45.044423 45.044423 45.044423
+24 2 81.049368 81.049368 81.049368
+24 3 71.805292 71.805292 71.805292
+24 4 81.584312 81.584312 81.584312
+24 5 77.129761 77.129761 77.129761
+24 6 82.000000 82.000000 82.000000
+24 7 72.801099 72.801099 72.801099
+24 8 73.681748 73.681748 73.681748
+24 9 78.447435 78.447435 78.447435
+24 10 41.036569 41.036569 41.036569
+24 11 44.821870 44.821870 44.821870
+24 12 46.097722 46.097722 46.097722
+24 13 50.000000 50.000000 50.000000
+24 14 44.598206 44.598206 44.598206
+24 15 51.855569 51.855569 51.855569
+24 16 50.209561 50.209561 50.209561
+24 17 51.662365 51.662365 51.662365
+24 18 55.172457 55.172457 55.172457
+24 19 6.000000 6.000000 6.000000
+24 20 6.403124 6.403124 6.403124
+24 21 10.770330 10.770330 10.770330
+24 22 2.000000 2.000000 2.000000
+24 23 10.198039 10.198039 10.198039
+24 25 10.000000 10.000000 10.000000
+24 26 3.000000 3.000000 3.000000
+24 27 62.241465 62.241465 62.241465
+24 28 64.412732 64.412732 64.412732
+24 29 59.506302 59.506302 59.506302
+24 30 60.033324 60.033324 60.033324
+24 31 55.901699 55.901699 55.901699
+24 32 58.309519 58.309519 58.309519
+24 33 55.009090 55.009090 55.009090
+24 34 51.078371 51.078371 51.078371
+24 35 55.758407 55.758407 55.758407
+24 36 85.094066 85.094066 85.094066
+24 37 84.433406 84.433406 84.433406
+24 38 81.596569 81.596569 81.596569
+24 39 78.746428 78.746428 78.746428
+24 40 78.160092 78.160092 78.160092
+24 41 82.969874 82.969874 82.969874
+24 42 72.801099 72.801099 72.801099
+24 43 76.902536 76.902536 76.902536
+24 44 81.786307 81.786307 81.786307
+24 45 78.854296 78.854296 78.854296
+24 46 79.075913 79.075913 79.075913
+24 47 77.620873 77.620873 77.620873
+24 48 53.814496 53.814496 53.814496
+24 49 4.000000 4.000000 4.000000
+24 50 8.062258 8.062258 8.062258
+24 51 45.343136 45.343136 45.343136
+24 52 22.671568 22.671568 22.671568
+24 53 28.178006 28.178006 28.178006
+24 54 48.466483 48.466483 48.466483
+24 55 57.567352 57.567352 57.567352
+24 56 55.578773 55.578773 55.578773
+24 57 32.310989 32.310989 32.310989
+24 58 21.540659 21.540659 21.540659
+24 59 23.537205 23.537205 23.537205
+24 60 31.764760 31.764760 31.764760
+24 61 59.615434 59.615434 59.615434
+24 62 60.406953 60.406953 60.406953
+24 63 40.360872 40.360872 40.360872
+24 64 30.886890 30.886890 30.886890
+24 65 25.961510 25.961510 25.961510
+24 66 35.128336 35.128336 35.128336
+24 67 32.140317 32.140317 32.140317
+24 68 45.221676 45.221676 45.221676
+24 69 55.036352 55.036352 55.036352
+24 70 47.518417 47.518417 47.518417
+24 71 64.070274 64.070274 64.070274
+24 72 56.824291 56.824291 56.824291
+24 73 65.000000 65.000000 65.000000
+24 74 65.734314 65.734314 65.734314
+24 75 23.430749 23.430749 23.430749
+24 76 33.000000 33.000000 33.000000
+24 77 23.086793 23.086793 23.086793
+24 78 15.132746 15.132746 15.132746
+24 79 59.169249 59.169249 59.169249
+24 80 70.661163 70.661163 70.661163
+24 81 42.953463 42.953463 42.953463
+24 82 54.129474 54.129474 54.129474
+24 83 39.560081 39.560081 39.560081
+24 84 26.019224 26.019224 26.019224
+24 85 30.610456 30.610456 30.610456
+24 86 30.805844 30.805844 30.805844
+24 87 25.495098 25.495098 25.495098
+24 88 32.202484 32.202484 32.202484
+24 89 54.817880 54.817880 54.817880
+24 90 29.000000 29.000000 29.000000
+24 91 42.011903 42.011903 42.011903
+24 92 38.600518 38.600518 38.600518
+24 93 40.853396 40.853396 40.853396
+24 94 52.325902 52.325902 52.325902
+24 95 47.010637 47.010637 47.010637
+24 96 36.715120 36.715120 36.715120
+24 97 51.865210 51.865210 51.865210
+24 98 36.400549 36.400549 36.400549
+24 99 48.507731 48.507731 48.507731
+24 100 32.310989 32.310989 32.310989
+24 101 62.393910 62.393910 62.393910
+25 1 35.057096 35.057096 35.057096
+25 2 71.196910 71.196910 71.196910
+25 3 62.096699 62.096699 62.096699
+25 4 71.805292 71.805292 71.805292
+25 5 67.446275 67.446275 67.446275
+25 6 72.277244 72.277244 72.277244
+25 7 63.245553 63.245553 63.245553
+25 8 64.257295 64.257295 64.257295
+25 9 68.949257 68.949257 68.949257
+25 10 34.409301 34.409301 34.409301
+25 11 37.536649 37.536649 37.536649
+25 12 39.051248 39.051248 39.051248
+25 13 42.426407 42.426407 42.426407
+25 14 38.587563 38.587563 38.587563
+25 15 44.598206 44.598206 44.598206
+25 16 43.829214 43.829214 43.829214
+25 17 45.486262 45.486262 45.486262
+25 18 48.414874 48.414874 48.414874
+25 19 11.661904 11.661904 11.661904
+25 20 6.403124 6.403124 6.403124
+25 21 4.000000 4.000000 4.000000
+25 22 10.198039 10.198039 10.198039
+25 23 2.000000 2.000000 2.000000
+25 24 10.000000 10.000000 10.000000
+25 26 10.440307 10.440307 10.440307
+25 27 58.940648 58.940648 58.940648
+25 28 60.406953 60.406953 60.406953
+25 29 56.044625 56.044625 56.044625
+25 30 55.713553 55.713553 55.713553
+25 31 52.201533 52.201533 52.201533
+25 32 53.851648 53.851648 53.851648
+25 33 51.244512 51.244512 51.244512
+25 34 48.052055 48.052055 48.052055
+25 35 51.078371 51.078371 51.078371
+25 36 75.769387 75.769387 75.769387
+25 37 75.026662 75.026662 75.026662
+25 38 72.235725 72.235725 72.235725
+25 39 69.289249 69.289249 69.289249
+25 40 68.622154 68.622154 68.622154
+25 41 73.375745 73.375745 73.375745
+25 42 63.245553 63.245553 63.245553
+25 43 67.186308 67.186308 67.186308
+25 44 72.034714 72.034714 72.034714
+25 45 69.123079 69.123079 69.123079
+25 46 69.375788 69.375788 69.375788
+25 47 68.007353 68.007353 68.007353
+25 48 46.861498 46.861498 46.861498
+25 49 10.770330 10.770330 10.770330
+25 50 5.000000 5.000000 5.000000
+25 51 39.446166 39.446166 39.446166
+25 52 17.720045 17.720045 17.720045
+25 53 19.849433 19.849433 19.849433
+25 54 39.357337 39.357337 39.357337
+25 55 48.104054 48.104054 48.104054
+25 56 45.705580 45.705580 45.705580
+25 57 23.323808 23.323808 23.323808
+25 58 12.806248 12.806248 12.806248
+25 59 23.537205 23.537205 23.537205
+25 60 28.442925 28.442925 28.442925
+25 61 50.537115 50.537115 50.537115
+25 62 50.487622 50.487622 50.487622
+25 63 33.600595 33.600595 33.600595
+25 64 27.459060 27.459060 27.459060
+25 65 16.552945 16.552945 16.552945
+25 66 25.179357 25.179357 25.179357
+25 67 22.203603 22.203603 22.203603
+25 68 37.483330 37.483330 37.483330
+25 69 45.044423 45.044423 45.044423
+25 70 37.656341 37.656341 37.656341
+25 71 54.083269 54.083269 54.083269
+25 72 48.259714 48.259714 48.259714
+25 73 55.901699 55.901699 55.901699
+25 74 57.628118 57.628118 57.628118
+25 75 18.681542 18.681542 18.681542
+25 76 34.481879 34.481879 34.481879
+25 77 22.203603 22.203603 22.203603
+25 78 19.209373 19.209373 19.209373
+25 79 50.803543 50.803543 50.803543
+25 80 61.911227 61.911227 61.911227
+25 81 33.241540 33.241540 33.241540
+25 82 44.384682 44.384682 44.384682
+25 83 30.083218 30.083218 30.083218
+25 84 16.031220 16.031220 16.031220
+25 85 23.600847 23.600847 23.600847
+25 86 26.248809 26.248809 26.248809
+25 87 19.235384 19.235384 19.235384
+25 88 27.513633 27.513633 27.513633
+25 89 45.221676 45.221676 45.221676
+25 90 30.675723 30.675723 30.675723
+25 91 32.015621 32.015621 32.015621
+25 92 29.154759 29.154759 29.154759
+25 93 31.764760 31.764760 31.764760
+25 94 43.566042 43.566042 43.566042
+25 95 38.078866 38.078866 38.078866
+25 96 28.425341 28.425341 28.425341
+25 97 42.544095 42.544095 42.544095
+25 98 34.132096 34.132096 34.132096
+25 99 38.897301 38.897301 38.897301
+25 100 23.323808 23.323808 23.323808
+25 101 52.469038 52.469038 52.469038
+26 1 45.276926 45.276926 45.276926
+26 2 80.622577 80.622577 80.622577
+26 3 71.196910 71.196910 71.196910
+26 4 81.049368 81.049368 81.049368
+26 5 76.485293 76.485293 76.485293
+26 6 81.394103 81.394103 81.394103
+26 7 72.034714 72.034714 72.034714
+26 8 72.801099 72.801099 72.801099
+26 9 77.620873 77.620873 77.620873
+26 10 39.051248 39.051248 39.051248
+26 11 43.011626 43.011626 43.011626
+26 12 44.204072 44.204072 44.204072
+26 13 48.259714 48.259714 48.259714
+26 14 42.426407 42.426407 42.426407
+26 15 50.000000 50.000000 50.000000
+26 16 48.104054 48.104054 48.104054
+26 17 49.497475 49.497475 49.497475
+26 18 53.150729 53.150729 53.150729
+26 19 9.000000 9.000000 9.000000
+26 20 8.602325 8.602325 8.602325
+26 21 12.206556 12.206556 12.206556
+26 22 5.000000 5.000000 5.000000
+26 23 11.180340 11.180340 11.180340
+26 24 3.000000 3.000000 3.000000
+26 25 10.440307 10.440307 10.440307
+26 27 65.000000 65.000000 65.000000
+26 28 67.082039 67.082039 67.082039
+26 29 62.241465 62.241465 62.241465
+26 30 62.649820 62.649820 62.649820
+26 31 58.600341 58.600341 58.600341
+26 32 60.901560 60.901560 60.901560
+26 33 57.697487 57.697487 57.697487
+26 34 53.851648 53.851648 53.851648
+26 35 58.309519 58.309519 58.309519
+26 36 86.162637 86.162637 86.162637
+26 37 85.440037 85.440037 85.440037
+26 38 82.637764 82.637764 82.637764
+26 39 79.711982 79.711982 79.711982
+26 40 79.056942 79.056942 79.056942
+26 41 83.815273 83.815273 83.815273
+26 42 73.681748 73.681748 73.681748
+26 43 77.620873 77.620873 77.620873
+26 44 82.462113 82.462113 82.462113
+26 45 79.555012 79.555012 79.555012
+26 46 78.447435 78.447435 78.447435
+26 47 76.902536 76.902536 76.902536
+26 48 51.855569 51.855569 51.855569
+26 49 7.000000 7.000000 7.000000
+26 50 9.899495 9.899495 9.899495
+26 51 47.634021 47.634021 47.634021
+26 52 25.000000 25.000000 25.000000
+26 53 26.925824 26.925824 26.925824
+26 54 47.434165 47.434165 47.434165
+26 55 58.523500 58.523500 58.523500
+26 56 55.226805 55.226805 55.226805
+26 57 33.541020 33.541020 33.541020
+26 58 20.615528 20.615528 20.615528
+26 59 20.615528 20.615528 20.615528
+26 60 29.154759 29.154759 29.154759
+26 61 58.523500 58.523500 58.523500
+26 62 60.827625 60.827625 60.827625
+26 63 42.426407 42.426407 42.426407
+26 64 33.541020 33.541020 33.541020
+26 65 26.925824 26.925824 26.925824
+26 66 35.000000 35.000000 35.000000
+26 67 32.557641 32.557641 32.557641
+26 68 47.010637 47.010637 47.010637
+26 69 55.226805 55.226805 55.226805
+26 70 47.169906 47.169906 47.169906
+26 71 64.000000 64.000000 64.000000
+26 72 58.309519 58.309519 58.309519
+26 73 66.211781 66.211781 66.211781
+26 74 64.140471 64.140471 64.140471
+26 75 21.213203 21.213203 21.213203
+26 76 30.000000 30.000000 30.000000
+26 77 25.961510 25.961510 25.961510
+26 78 12.165525 12.165525 12.165525
+26 79 57.706152 57.706152 57.706152
+26 80 69.354164 69.354164 69.354164
+26 81 43.680659 43.680659 43.680659
+26 82 54.817880 54.817880 54.817880
+26 83 38.832976 38.832976 38.832976
+26 84 26.076810 26.076810 26.076810
+26 85 32.557641 32.557641 32.557641
+26 86 33.286634 33.286634 33.286634
+26 87 23.600847 23.600847 23.600847
+26 88 29.832868 29.832868 29.832868
+26 89 54.129474 54.129474 54.129474
+26 90 32.000000 32.000000 32.000000
+26 91 42.047592 42.047592 42.047592
+26 92 39.560081 39.560081 39.560081
+26 93 42.047592 42.047592 42.047592
+26 94 53.712196 53.712196 53.712196
+26 95 48.301139 48.301139 48.301139
+26 96 38.275318 38.275318 38.275318
+26 97 52.924474 52.924474 52.924474
+26 98 33.615473 33.615473 33.615473
+26 99 47.853944 47.853944 47.853944
+26 100 31.320920 31.320920 31.320920
+26 101 62.128898 62.128898 62.128898
+27 1 58.523500 58.523500 58.523500
+27 2 89.022469 89.022469 89.022469
+27 3 85.755466 85.755466 85.755466
+27 4 91.400219 91.400219 91.400219
+27 5 90.138782 90.138782 90.138782
+27 6 93.005376 93.005376 93.005376
+27 7 89.185201 89.185201 89.185201
+27 8 91.787799 91.787799 91.787799
+27 9 94.339811 94.339811 94.339811
+27 10 85.146932 85.146932 85.146932
+27 11 85.586214 85.586214 85.586214
+27 12 87.572827 87.572827 87.572827
+27 13 88.283634 88.283634 88.283634
+27 14 90.138782 90.138782 90.138782
+27 15 91.241438 91.241438 91.241438
+27 16 93.536089 93.536089 93.536089
+27 17 95.524866 95.524866 95.524866
+27 18 96.176920 96.176920 96.176920
+27 19 56.797887 56.797887 56.797887
+27 20 56.648036 56.648036 56.648036
+27 21 55.081757 55.081757 55.081757
+27 22 60.415230 60.415230 60.415230
+27 23 57.008771 57.008771 57.008771
+27 24 62.241465 62.241465 62.241465
+27 25 58.940648 58.940648 58.940648
+27 26 65.000000 65.000000 65.000000
+27 28 5.000000 5.000000 5.000000
+27 29 3.000000 3.000000 3.000000
+27 30 7.071068 7.071068 7.071068
+27 31 7.000000 7.000000 7.000000
+27 32 8.602325 8.602325 8.602325
+27 33 8.000000 8.000000 8.000000
+27 34 11.180340 11.180340 11.180340
+27 35 11.180340 11.180340 11.180340
+27 36 61.717096 61.717096 61.717096
+27 37 62.649820 62.649820 62.649820
+27 38 60.033324 60.033324 60.033324
+27 39 59.908263 59.908263 59.908263
+27 40 61.032778 61.032778 61.032778
+27 41 65.192024 65.192024 65.192024
+27 42 58.258047 58.258047 58.258047
+27 43 64.031242 64.031242 64.031242
+27 44 68.007353 68.007353 68.007353
+27 45 65.604878 65.604878 65.604878
+27 46 91.263355 91.263355 91.263355
+27 47 91.809586 91.809586 91.809586
+27 48 94.201911 94.201911 94.201911
+27 49 58.600341 58.600341 58.600341
+27 50 55.973208 55.973208 55.973208
+27 51 23.537205 23.537205 23.537205
+27 52 41.231056 41.231056 41.231056
+27 53 70.000000 70.000000 70.000000
+27 54 77.620873 77.620873 77.620873
+27 55 50.000000 50.000000 50.000000
+27 56 71.589105 71.589105 71.589105
+27 57 45.276926 45.276926 45.276926
+27 58 65.192024 65.192024 65.192024
+27 59 82.462113 82.462113 82.462113
+27 60 85.586214 85.586214 85.586214
+27 61 85.440037 85.440037 85.440037
+27 62 61.032778 61.032778 61.032778
+27 63 30.413813 30.413813 30.413813
+27 64 31.622777 31.622777 31.622777
+27 65 50.000000 50.000000 50.000000
+27 66 60.827625 60.827625 60.827625
+27 67 54.451814 54.451814 54.451814
+27 68 33.241540 33.241540 33.241540
+27 69 62.649820 62.649820 62.649820
+27 70 67.675697 67.675697 67.675697
+27 71 71.561163 71.561163 71.561163
+27 72 39.051248 39.051248 39.051248
+27 73 47.423623 47.423623 47.423623
+27 74 97.718985 97.718985 97.718985
+27 75 75.663730 75.663730 75.663730
+27 76 93.407708 93.407708 93.407708
+27 77 39.357337 39.357337 39.357337
+27 78 76.896034 76.896034 76.896034
+27 79 90.801982 90.801982 90.801982
+27 80 96.772930 96.772930 96.772930
+27 81 50.921508 50.921508 50.921508
+27 82 53.851648 53.851648 53.851648
+27 83 69.231496 69.231496 69.231496
+27 84 58.008620 58.008620 58.008620
+27 85 38.013156 38.013156 38.013156
+27 86 32.756679 32.756679 32.756679
+27 87 74.242845 74.242845 74.242845
+27 88 83.216585 83.216585 83.216585
+27 89 76.321688 76.321688 76.321688
+27 90 37.536649 37.536649 37.536649
+27 91 60.440053 60.440053 60.440053
+27 92 47.539457 47.539457 47.539457
+27 93 43.965896 43.965896 43.965896
+27 94 40.496913 40.496913 40.496913
+27 95 42.047592 42.047592 42.047592
+27 96 39.623226 39.623226 39.623226
+27 97 46.647615 46.647615 46.647615
+27 98 91.787799 91.787799 91.787799
+27 99 72.422372 72.422372 72.422372
+27 100 69.180922 69.180922 69.180922
+27 101 73.925638 73.925638 73.925638
+28 1 57.008771 57.008771 57.008771
+28 2 86.023253 86.023253 86.023253
+28 3 83.240615 83.240615 83.240615
+28 4 88.481637 88.481637 88.481637
+28 5 87.464278 87.464278 87.464278
+28 6 90.138782 90.138782 90.138782
+28 7 86.769810 86.769810 86.769810
+28 8 89.442719 89.442719 89.442719
+28 9 91.787799 91.787799 91.787799
+28 10 85.000000 85.000000 85.000000
+28 11 85.146932 85.146932 85.146932
+28 12 87.143560 87.143560 87.143560
+28 13 87.572827 87.572827 87.572827
+28 14 90.000000 90.000000 90.000000
+28 15 90.553851 90.553851 90.553851
+28 16 93.134312 93.134312 93.134312
+28 17 95.131488 95.131488 95.131488
+28 18 95.524866 95.524866 95.524866
+28 19 59.169249 59.169249 59.169249
+28 20 58.600341 58.600341 58.600341
+28 21 56.648036 56.648036 56.648036
+28 22 62.649820 62.649820 62.649820
+28 23 58.523500 58.523500 58.523500
+28 24 64.412732 64.412732 64.412732
+28 25 60.406953 60.406953 60.406953
+28 26 67.082039 67.082039 67.082039
+28 27 5.000000 5.000000 5.000000
+28 29 5.830952 5.830952 5.830952
+28 30 5.000000 5.000000 5.000000
+28 31 8.602325 8.602325 8.602325
+28 32 7.000000 7.000000 7.000000
+28 33 9.433981 9.433981 9.433981
+28 34 14.142136 14.142136 14.142136
+28 35 10.000000 10.000000 10.000000
+28 36 57.306195 57.306195 57.306195
+28 37 58.309519 58.309519 58.309519
+28 38 55.758407 55.758407 55.758407
+28 39 55.803226 55.803226 55.803226
+28 40 57.008771 57.008771 57.008771
+28 41 61.032778 61.032778 61.032778
+28 42 54.488531 54.488531 54.488531
+28 43 60.207973 60.207973 60.207973
+28 44 64.031242 64.031242 64.031242
+28 45 61.717096 61.717096 61.717096
+28 46 88.509886 88.509886 88.509886
+28 47 89.185201 89.185201 89.185201
+28 48 93.536089 93.536089 93.536089
+28 49 60.901560 60.901560 60.901560
+28 50 57.775427 57.775427 57.775427
+28 51 23.000000 23.000000 23.000000
+28 52 42.720019 42.720019 42.720019
+28 53 70.178344 70.178344 70.178344
+28 54 76.485293 76.485293 76.485293
+28 55 47.169906 47.169906 47.169906
+28 56 69.641941 69.641941 69.641941
+28 57 45.000000 45.000000 45.000000
+28 58 65.764732 65.764732 65.764732
+28 59 83.815273 83.815273 83.815273
+28 60 86.313383 86.313383 86.313383
+28 61 83.815273 83.815273 83.815273
+28 62 58.309519 58.309519 58.309519
+28 63 30.000000 30.000000 30.000000
+28 64 33.541020 33.541020 33.541020
+28 65 50.249378 50.249378 50.249378
+28 66 60.207973 60.207973 60.207973
+28 67 54.037024 54.037024 54.037024
+28 68 31.780497 31.780497 31.780497
+28 69 60.415230 60.415230 60.415230
+28 70 66.219333 66.219333 66.219333
+28 71 68.963759 68.963759 68.963759
+28 72 36.055513 36.055513 36.055513
+28 73 43.863424 43.863424 43.863424
+28 74 96.301610 96.301610 96.301610
+28 75 76.485293 76.485293 76.485293
+28 76 94.868330 94.868330 94.868330
+28 77 41.880783 41.880783 41.880783
+28 78 78.790862 78.790862 78.790862
+28 79 89.498603 89.498603 89.498603
+28 80 94.921020 94.921020 94.921020
+28 81 49.477268 49.477268 49.477268
+28 82 51.429563 51.429563 51.429563
+28 83 68.468971 68.468971 68.468971
+28 84 58.137767 58.137767 58.137767
+28 85 38.470768 38.470768 38.470768
+28 86 34.176015 34.176015 34.176015
+28 87 74.813100 74.813100 74.813100
+28 88 83.725743 83.725743 83.725743
+28 89 74.632433 74.632433 74.632433
+28 90 41.036569 41.036569 41.036569
+28 91 59.228372 59.228372 59.228372
+28 92 46.529560 46.529560 46.529560
+28 93 42.755117 42.755117 42.755117
+28 94 38.013156 38.013156 38.013156
+28 95 40.162171 40.162171 40.162171
+28 96 39.051248 39.051248 39.051248
+28 97 44.283180 44.283180 44.283180
+28 98 92.574294 92.574294 92.574294
+28 99 71.063352 71.063352 71.063352
+28 100 69.000000 69.000000 69.000000
+28 101 71.554175 71.554175 71.554175
+29 1 55.713553 55.713553 55.713553
+29 2 86.683332 86.683332 86.683332
+29 3 83.216585 83.216585 83.216585
+29 4 89.022469 89.022469 89.022469
+29 5 87.658428 87.658428 87.658428
+29 6 90.603532 90.603532 90.603532
+29 7 86.608314 86.608314 86.608314
+29 8 89.185201 89.185201 89.185201
+29 9 91.809586 91.809586 91.809586
+29 10 82.152298 82.152298 82.152298
+29 11 82.607506 82.607506 82.607506
+29 12 84.593144 84.593144 84.593144
+29 13 85.328776 85.328776 85.328776
+29 14 87.143560 87.143560 87.143560
+29 15 88.283634 88.283634 88.283634
+29 16 90.553851 90.553851 90.553851
+29 17 92.541882 92.541882 92.541882
+29 18 93.214806 93.214806 93.214806
+29 19 54.120237 54.120237 54.120237
+29 20 53.851648 53.851648 53.851648
+29 21 52.201533 52.201533 52.201533
+29 22 57.697487 57.697487 57.697487
+29 23 54.120237 54.120237 54.120237
+29 24 59.506302 59.506302 59.506302
+29 25 56.044625 56.044625 56.044625
+29 26 62.241465 62.241465 62.241465
+29 27 3.000000 3.000000 3.000000
+29 28 5.830952 5.830952 5.830952
+29 30 5.385165 5.385165 5.385165
+29 31 4.000000 4.000000 4.000000
+29 32 6.403124 6.403124 6.403124
+29 33 5.000000 5.000000 5.000000
+29 34 8.602325 8.602325 8.602325
+29 35 8.602325 8.602325 8.602325
+29 36 60.415230 60.415230 60.415230
+29 37 61.269895 61.269895 61.269895
+29 38 58.591808 58.591808 58.591808
+29 39 58.309519 58.309519 58.309519
+29 40 59.363288 59.363288 59.363288
+29 41 63.631753 63.631753 63.631753
+29 42 56.400355 56.400355 56.400355
+29 43 62.201286 62.201286 62.201286
+29 44 66.287254 66.287254 66.287254
+29 45 63.820060 63.820060 63.820060
+29 46 88.814413 88.814413 88.814413
+29 47 89.308454 89.308454 89.308454
+29 48 91.241438 91.241438 91.241438
+29 49 55.901699 55.901699 55.901699
+29 50 53.141321 53.141321 53.141321
+29 51 20.615528 20.615528 20.615528
+29 52 38.327536 38.327536 38.327536
+29 53 67.000000 67.000000 67.000000
+29 54 74.726167 74.726167 74.726167
+29 55 47.634021 47.634021 47.634021
+29 56 68.876701 68.876701 68.876701
+29 57 42.296572 42.296572 42.296572
+29 58 62.201286 62.201286 62.201286
+29 59 79.555012 79.555012 79.555012
+29 60 82.607506 82.607506 82.607506
+29 61 82.637764 82.637764 82.637764
+29 62 58.600341 58.600341 58.600341
+29 63 27.459060 27.459060 27.459060
+29 64 28.792360 28.792360 28.792360
+29 65 47.000000 47.000000 47.000000
+29 66 57.870545 57.870545 57.870545
+29 67 51.478151 51.478151 51.478151
+29 68 30.463092 30.463092 30.463092
+29 69 60.033324 60.033324 60.033324
+29 70 64.845971 64.845971 64.845971
+29 71 69.065187 69.065187 69.065187
+29 72 36.796739 36.796739 36.796739
+29 73 45.453273 45.453273 45.453273
+29 74 94.868330 94.868330 94.868330
+29 75 72.691127 72.691127 72.691127
+29 76 90.520716 90.520716 90.520716
+29 77 36.715120 36.715120 36.715120
+29 78 74.094534 74.094534 74.094534
+29 79 87.931792 87.931792 87.931792
+29 80 94.021274 94.021274 94.021274
+29 81 48.104054 48.104054 48.104054
+29 82 51.312766 51.312766 51.312766
+29 83 66.287254 66.287254 66.287254
+29 84 55.009090 55.009090 55.009090
+29 85 35.014283 35.014283 35.014283
+29 86 29.832868 29.832868 29.832868
+29 87 71.253070 71.253070 71.253070
+29 88 80.224684 80.224684 80.224684
+29 89 73.539105 73.539105 73.539105
+29 90 35.355339 35.355339 35.355339
+29 91 57.567352 57.567352 57.567352
+29 92 44.643029 44.643029 44.643029
+29 93 41.109610 41.109610 41.109610
+29 94 38.013156 38.013156 38.013156
+29 95 39.357337 39.357337 39.357337
+29 96 36.674242 36.674242 36.674242
+29 97 44.102154 44.102154 44.102154
+29 98 88.814413 88.814413 88.814413
+29 99 69.570109 69.570109 69.570109
+29 100 66.189123 66.189123 66.189123
+29 101 71.344236 71.344236 71.344236
+30 1 52.201533 52.201533 52.201533
+30 2 82.006097 82.006097 82.006097
+30 3 78.892332 78.892332 78.892332
+30 4 84.403791 84.403791 84.403791
+30 5 83.216585 83.216585 83.216585
+30 6 86.023253 86.023253 86.023253
+30 7 82.365041 82.365041 82.365041
+30 8 85.000000 85.000000 85.000000
+30 9 87.464278 87.464278 87.464278
+30 10 80.000000 80.000000 80.000000
+30 11 80.156098 80.156098 80.156098
+30 12 82.152298 82.152298 82.152298
+30 13 82.607506 82.607506 82.607506
+30 14 85.000000 85.000000 85.000000
+30 15 85.586214 85.586214 85.586214
+30 16 88.141931 88.141931 88.141931
+30 17 90.138782 90.138782 90.138782
+30 18 90.553851 90.553851 90.553851
+30 19 54.918121 54.918121 54.918121
+30 20 54.120237 54.120237 54.120237
+30 21 52.000000 52.000000 52.000000
+30 22 58.309519 58.309519 58.309519
+30 23 53.851648 53.851648 53.851648
+30 24 60.033324 60.033324 60.033324
+30 25 55.713553 55.713553 55.713553
+30 26 62.649820 62.649820 62.649820
+30 27 7.071068 7.071068 7.071068
+30 28 5.000000 5.000000 5.000000
+30 29 5.385165 5.385165 5.385165
+30 31 5.385165 5.385165 5.385165
+30 32 2.000000 2.000000 2.000000
+30 33 5.830952 5.830952 5.830952
+30 34 11.180340 11.180340 11.180340
+30 35 5.000000 5.000000 5.000000
+30 36 55.036352 55.036352 55.036352
+30 37 55.901699 55.901699 55.901699
+30 38 53.235327 53.235327 53.235327
+30 39 53.000000 53.000000 53.000000
+30 40 54.083269 54.083269 54.083269
+30 41 58.309519 58.309519 58.309519
+30 42 51.224994 51.224994 51.224994
+30 43 57.008771 57.008771 57.008771
+30 44 61.032778 61.032778 61.032778
+30 45 58.600341 58.600341 58.600341
+30 46 84.314886 84.314886 84.314886
+30 47 84.905830 84.905830 84.905830
+30 48 88.566359 88.566359 88.566359
+30 49 56.603887 56.603887 56.603887
+30 50 53.225934 53.225934 53.225934
+30 51 18.000000 18.000000 18.000000
+30 52 38.078866 38.078866 38.078866
+30 53 65.192024 65.192024 65.192024
+30 54 71.589105 71.589105 71.589105
+30 55 43.011626 43.011626 43.011626
+30 56 65.000000 65.000000 65.000000
+30 57 40.000000 40.000000 40.000000
+30 58 60.827625 60.827625 60.827625
+30 59 79.056942 79.056942 79.056942
+30 60 81.394103 81.394103 81.394103
+30 61 79.056942 79.056942 79.056942
+30 62 54.083269 54.083269 54.083269
+30 63 25.000000 25.000000 25.000000
+30 64 29.154759 29.154759 29.154759
+30 65 45.276926 45.276926 45.276926
+30 66 55.226805 55.226805 55.226805
+30 67 49.040799 49.040799 49.040799
+30 68 26.925824 26.925824 26.925824
+30 69 55.901699 55.901699 55.901699
+30 70 61.400326 61.400326 61.400326
+30 71 64.660653 64.660653 64.660653
+30 72 32.015621 32.015621 32.015621
+30 73 40.360872 40.360872 40.360872
+30 74 91.482239 91.482239 91.482239
+30 75 71.589105 71.589105 71.589105
+30 76 90.138782 90.138782 90.138782
+30 77 37.802116 37.802116 37.802116
+30 78 74.249579 74.249579 74.249579
+30 79 84.646323 84.646323 84.646323
+30 80 90.249654 90.249654 90.249654
+30 81 44.643029 44.643029 44.643029
+30 82 47.010637 47.010637 47.010637
+30 83 63.505905 63.505905 63.505905
+30 84 53.150729 53.150729 53.150729
+30 85 33.541020 33.541020 33.541020
+30 86 29.546573 29.546573 29.546573
+30 87 69.871310 69.871310 69.871310
+30 88 78.771822 78.771822 78.771822
+30 89 69.892775 69.892775 69.892775
+30 90 37.802116 37.802116 37.802116
+30 91 54.341513 54.341513 54.341513
+30 92 41.593269 41.593269 41.593269
+30 93 37.854986 37.854986 37.854986
+30 94 33.615473 33.615473 33.615473
+30 95 35.468296 35.468296 35.468296
+30 96 34.058773 34.058773 34.058773
+30 97 39.824616 39.824616 39.824616
+30 98 87.664132 87.664132 87.664132
+30 99 66.219333 66.219333 66.219333
+30 100 64.000000 64.000000 64.000000
+30 101 67.119297 67.119297 67.119297
+31 1 52.000000 52.000000 52.000000
+31 2 83.630138 83.630138 83.630138
+31 3 79.881162 79.881162 79.881162
+31 4 85.912746 85.912746 85.912746
+31 5 84.403791 84.403791 84.403791
+31 6 87.458562 87.458562 87.458562
+31 7 83.216585 83.216585 83.216585
+31 8 85.755466 85.755466 85.755466
+31 9 88.481637 88.481637 88.481637
+31 10 78.160092 78.160092 78.160092
+31 11 78.638413 78.638413 78.638413
+31 12 80.622577 80.622577 80.622577
+31 13 81.394103 81.394103 81.394103
+31 14 83.150466 83.150466 83.150466
+31 15 84.344532 84.344532 84.344532
+31 16 86.579443 86.579443 86.579443
+31 17 88.566359 88.566359 88.566359
+31 18 89.269256 89.269256 89.269256
+31 19 50.606324 50.606324 50.606324
+31 20 50.159745 50.159745 50.159745
+31 21 48.383882 48.383882 48.383882
+31 22 54.120237 54.120237 54.120237
+31 23 50.289164 50.289164 50.289164
+31 24 55.901699 55.901699 55.901699
+31 25 52.201533 52.201533 52.201533
+31 26 58.600341 58.600341 58.600341
+31 27 7.000000 7.000000 7.000000
+31 28 8.602325 8.602325 8.602325
+31 29 4.000000 4.000000 4.000000
+31 30 5.385165 5.385165 5.385165
+31 32 5.000000 5.000000 5.000000
+31 33 1.000000 1.000000 1.000000
+31 34 5.830952 5.830952 5.830952
+31 35 5.830952 5.830952 5.830952
+31 36 58.872744 58.872744 58.872744
+31 37 59.615434 59.615434 59.615434
+31 38 56.859476 56.859476 56.859476
+31 39 56.356011 56.356011 56.356011
+31 40 57.306195 57.306195 57.306195
+31 41 61.717096 61.717096 61.717096
+31 42 54.083269 54.083269 54.083269
+31 43 59.908263 59.908263 59.908263
+31 44 64.140471 64.140471 64.140471
+31 45 61.587336 61.587336 61.587336
+31 46 85.603738 85.603738 85.603738
+31 47 86.023253 86.023253 86.023253
+31 48 87.298339 87.298339 87.298339
+31 49 52.354560 52.354560 52.354560
+31 50 49.396356 49.396356 49.396356
+31 51 16.763055 16.763055 16.763055
+31 52 34.481879 34.481879 34.481879
+31 53 63.000000 63.000000 63.000000
+31 54 70.880181 70.880181 70.880181
+31 55 44.598206 44.598206 44.598206
+31 56 65.299311 65.299311 65.299311
+31 57 38.327536 38.327536 38.327536
+31 58 58.215118 58.215118 58.215118
+31 59 75.690158 75.690158 75.690158
+31 60 78.638413 78.638413 78.638413
+31 61 78.924014 78.924014 78.924014
+31 62 55.443665 55.443665 55.443665
+31 63 23.537205 23.537205 23.537205
+31 64 25.079872 25.079872 25.079872
+31 65 43.000000 43.000000 43.000000
+31 66 53.935146 53.935146 53.935146
+31 67 47.518417 47.518417 47.518417
+31 68 26.832816 26.832816 26.832816
+31 69 56.603887 56.603887 56.603887
+31 70 61.098281 61.098281 61.098281
+31 71 65.802736 65.802736 65.802736
+31 72 33.970576 33.970576 33.970576
+31 73 43.011626 43.011626 43.011626
+31 74 91.082380 91.082380 91.082380
+31 75 68.731361 68.731361 68.731361
+31 76 86.683332 86.683332 86.683332
+31 77 33.286634 33.286634 33.286634
+31 78 70.384657 70.384657 70.384657
+31 79 84.118963 84.118963 84.118963
+31 80 90.376988 90.376988 90.376988
+31 81 44.384682 44.384682 44.384682
+31 82 48.010416 48.010416 48.010416
+31 83 62.369865 62.369865 62.369865
+31 84 51.009803 51.009803 51.009803
+31 85 31.016125 31.016125 31.016125
+31 86 25.961510 25.961510 25.961510
+31 87 67.268120 67.268120 67.268120
+31 88 76.236474 76.236474 76.236474
+31 89 69.856997 69.856997 69.856997
+31 90 32.649655 32.649655 32.649655
+31 91 53.758720 53.758720 53.758720
+31 92 40.804412 40.804412 40.804412
+31 93 37.336309 37.336309 37.336309
+31 94 34.828150 34.828150 34.828150
+31 95 35.846897 35.846897 35.846897
+31 96 32.756679 32.756679 32.756679
+31 97 40.804412 40.804412 40.804412
+31 98 84.852814 84.852814 84.852814
+31 99 65.787537 65.787537 65.787537
+31 100 62.201286 62.201286 62.201286
+31 101 67.955868 67.955868 67.955868
+32 1 50.289164 50.289164 50.289164
+32 2 80.430094 80.430094 80.430094
+32 3 77.175126 77.175126 77.175126
+32 4 82.800966 82.800966 82.800966
+32 5 81.541401 81.541401 81.541401
+32 6 84.403791 84.403791 84.403791
+32 7 80.622577 80.622577 80.622577
+32 8 83.240615 83.240615 83.240615
+32 9 85.755466 85.755466 85.755466
+32 10 78.000000 78.000000 78.000000
+32 11 78.160092 78.160092 78.160092
+32 12 80.156098 80.156098 80.156098
+32 13 80.622577 80.622577 80.622577
+32 14 83.000000 83.000000 83.000000
+32 15 83.600239 83.600239 83.600239
+32 16 86.145226 86.145226 86.145226
+32 17 88.141931 88.141931 88.141931
+32 18 88.566359 88.566359 88.566359
+32 19 53.254108 53.254108 53.254108
+32 20 52.354560 52.354560 52.354560
+32 21 50.159745 50.159745 50.159745
+32 22 56.603887 56.603887 56.603887
+32 23 52.000000 52.000000 52.000000
+32 24 58.309519 58.309519 58.309519
+32 25 53.851648 53.851648 53.851648
+32 26 60.901560 60.901560 60.901560
+32 27 8.602325 8.602325 8.602325
+32 28 7.000000 7.000000 7.000000
+32 29 6.403124 6.403124 6.403124
+32 30 2.000000 2.000000 2.000000
+32 31 5.000000 5.000000 5.000000
+32 33 5.099020 5.099020 5.099020
+32 34 10.440307 10.440307 10.440307
+32 35 3.000000 3.000000 3.000000
+32 36 54.230987 54.230987 54.230987
+32 37 55.036352 55.036352 55.036352
+32 38 52.325902 52.325902 52.325902
+32 39 51.971146 51.971146 51.971146
+32 40 53.000000 53.000000 53.000000
+32 41 57.306195 57.306195 57.306195
+32 42 50.000000 50.000000 50.000000
+32 43 55.803226 55.803226 55.803226
+32 44 59.908263 59.908263 59.908263
+32 45 57.428216 57.428216 57.428216
+32 46 82.661962 82.661962 82.661962
+32 47 83.216585 83.216585 83.216585
+32 48 86.579443 86.579443 86.579443
+32 49 54.918121 54.918121 54.918121
+32 50 51.429563 51.429563 51.429563
+32 51 16.000000 16.000000 16.000000
+32 52 36.249138 36.249138 36.249138
+32 53 63.198101 63.198101 63.198101
+32 54 69.634761 69.634761 69.634761
+32 55 41.400483 41.400483 41.400483
+32 56 63.158531 63.158531 63.158531
+32 57 38.000000 38.000000 38.000000
+32 58 58.855756 58.855756 58.855756
+32 59 77.162167 77.162167 77.162167
+32 60 79.429214 79.429214 79.429214
+32 61 77.162167 77.162167 77.162167
+32 62 52.430907 52.430907 52.430907
+32 63 23.000000 23.000000 23.000000
+32 64 27.459060 27.459060 27.459060
+32 65 43.289722 43.289722 43.289722
+32 66 53.235327 53.235327 53.235327
+32 67 47.042534 47.042534 47.042534
+32 68 25.000000 25.000000 25.000000
+32 69 54.120237 54.120237 54.120237
+32 70 59.481089 59.481089 59.481089
+32 71 62.968246 62.968246 62.968246
+32 72 30.479501 30.479501 30.479501
+32 73 39.051248 39.051248 39.051248
+32 74 89.560036 89.560036 89.560036
+32 75 69.634761 69.634761 69.634761
+32 76 88.255311 88.255311 88.255311
+32 77 36.235342 36.235342 36.235342
+32 78 72.449983 72.449983 72.449983
+32 79 82.710338 82.710338 82.710338
+32 80 88.391176 88.391176 88.391176
+32 81 42.720019 42.720019 42.720019
+32 82 45.276926 45.276926 45.276926
+32 83 61.522354 61.522354 61.522354
+32 84 51.156622 51.156622 51.156622
+32 85 31.575307 31.575307 31.575307
+32 86 27.730849 27.730849 27.730849
+32 87 67.896981 67.896981 67.896981
+32 88 76.791927 76.791927 76.791927
+32 89 68.007353 68.007353 68.007353
+32 90 36.619667 36.619667 36.619667
+32 91 52.392748 52.392748 52.392748
+32 92 39.623226 39.623226 39.623226
+32 93 35.902646 35.902646 35.902646
+32 94 31.906112 31.906112 31.906112
+32 95 33.615473 33.615473 33.615473
+32 96 32.062439 32.062439 32.062439
+32 97 38.078866 38.078866 38.078866
+32 98 85.702975 85.702975 85.702975
+32 99 64.288413 64.288413 64.288413
+32 100 62.000000 62.000000 62.000000
+32 101 65.368188 65.368188 65.368188
+33 1 51.078371 51.078371 51.078371
+33 2 82.879430 82.879430 82.879430
+33 3 79.056942 79.056942 79.056942
+33 4 85.146932 85.146932 85.146932
+33 5 83.600239 83.600239 83.600239
+33 6 86.683332 86.683332 86.683332
+33 7 82.377181 82.377181 82.377181
+33 8 84.905830 84.905830 84.905830
+33 9 87.658428 87.658428 87.658428
+33 10 77.162167 77.162167 77.162167
+33 11 77.646635 77.646635 77.646635
+33 12 79.630396 79.630396 79.630396
+33 13 80.411442 80.411442 80.411442
+33 14 82.152298 82.152298 82.152298
+33 15 83.360662 83.360662 83.360662
+33 16 85.586214 85.586214 85.586214
+33 17 87.572827 87.572827 87.572827
+33 18 88.283634 88.283634 88.283634
+33 19 49.739320 49.739320 49.739320
+33 20 49.244289 49.244289 49.244289
+33 21 47.434165 47.434165 47.434165
+33 22 53.235327 53.235327 53.235327
+33 23 49.335586 49.335586 49.335586
+33 24 55.009090 55.009090 55.009090
+33 25 51.244512 51.244512 51.244512
+33 26 57.697487 57.697487 57.697487
+33 27 8.000000 8.000000 8.000000
+33 28 9.433981 9.433981 9.433981
+33 29 5.000000 5.000000 5.000000
+33 30 5.830952 5.830952 5.830952
+33 31 1.000000 1.000000 1.000000
+33 32 5.099020 5.099020 5.099020
+33 34 5.385165 5.385165 5.385165
+33 35 5.385165 5.385165 5.385165
+33 36 58.523500 58.523500 58.523500
+33 37 59.236813 59.236813 59.236813
+33 38 56.462377 56.462377 56.462377
+33 39 55.901699 55.901699 55.901699
+33 40 56.824291 56.824291 56.824291
+33 41 61.269895 61.269895 61.269895
+33 42 53.535035 53.535035 53.535035
+33 43 59.363288 59.363288 59.363288
+33 44 63.631753 63.631753 63.631753
+33 45 61.057350 61.057350 61.057350
+33 46 84.811556 84.811556 84.811556
+33 47 85.211502 85.211502 85.211502
+33 48 86.313383 86.313383 86.313383
+33 49 51.478151 51.478151 51.478151
+33 50 48.466483 48.466483 48.466483
+33 51 15.811388 15.811388 15.811388
+33 52 33.526109 33.526109 33.526109
+33 53 62.000000 62.000000 62.000000
+33 54 69.921384 69.921384 69.921384
+33 55 43.863424 43.863424 43.863424
+33 56 64.412732 64.412732 64.412732
+33 57 37.336309 37.336309 37.336309
+33 58 57.218878 57.218878 57.218878
+33 59 74.726167 74.726167 74.726167
+33 60 77.646635 77.646635 77.646635
+33 61 78.000000 78.000000 78.000000
+33 62 54.671748 54.671748 54.671748
+33 63 22.561028 22.561028 22.561028
+33 64 24.166092 24.166092 24.166092
+33 65 42.000000 42.000000 42.000000
+33 66 52.952809 52.952809 52.952809
+33 67 46.529560 46.529560 46.529560
+33 68 25.942244 25.942244 25.942244
+33 69 55.758407 55.758407 55.758407
+33 70 60.166436 60.166436 60.166436
+33 71 65.000000 65.000000 65.000000
+33 72 33.301652 33.301652 33.301652
+33 73 42.438190 42.438190 42.438190
+33 74 90.138782 90.138782 90.138782
+33 75 67.742158 67.742158 67.742158
+33 76 85.726309 85.726309 85.726309
+33 77 32.449961 32.449961 32.449961
+33 78 69.462220 69.462220 69.462220
+33 79 83.168504 83.168504 83.168504
+33 80 89.470666 89.470666 89.470666
+33 81 43.462628 43.462628 43.462628
+33 82 47.201695 47.201695 47.201695
+33 83 61.392182 61.392182 61.392182
+33 84 50.009999 50.009999 50.009999
+33 85 30.016662 30.016662 30.016662
+33 86 25.000000 25.000000 25.000000
+33 87 66.272166 66.272166 66.272166
+33 88 75.239617 75.239617 75.239617
+33 89 68.942005 68.942005 68.942005
+33 90 32.015621 32.015621 32.015621
+33 91 52.810984 52.810984 52.810984
+33 92 39.849718 39.849718 39.849718
+33 93 36.400549 36.400549 36.400549
+33 94 34.058773 34.058773 34.058773
+33 95 34.985711 34.985711 34.985711
+33 96 31.780497 31.780497 31.780497
+33 97 40.000000 40.000000 40.000000
+33 98 83.862983 83.862983 83.862983
+33 99 64.845971 64.845971 64.845971
+33 100 61.204575 61.204575 61.204575
+33 101 67.119297 67.119297 67.119297
+34 1 51.478151 51.478151 51.478151
+34 2 84.852814 84.852814 84.852814
+34 3 80.430094 80.430094 80.430094
+34 4 87.000000 87.000000 87.000000
+34 5 85.146932 85.146932 85.146932
+34 6 88.459030 88.459030 88.459030
+34 7 83.600239 83.600239 83.600239
+34 8 86.023253 86.023253 86.023253
+34 9 89.022469 89.022469 89.022469
+34 10 75.663730 75.663730 75.663730
+34 11 76.485293 76.485293 76.485293
+34 12 78.447435 78.447435 78.447435
+34 13 79.555012 79.555012 79.555012
+34 14 80.622577 80.622577 80.622577
+34 15 82.462113 82.462113 82.462113
+34 16 84.344532 84.344532 84.344532
+34 17 86.313383 86.313383 86.313383
+34 18 87.321246 87.321246 87.321246
+34 19 45.617979 45.617979 45.617979
+34 20 45.541190 45.541190 45.541190
+34 21 44.147480 44.147480 44.147480
+34 22 49.244289 49.244289 49.244289
+34 23 46.097722 46.097722 46.097722
+34 24 51.078371 51.078371 51.078371
+34 25 48.052055 48.052055 48.052055
+34 26 53.851648 53.851648 53.851648
+34 27 11.180340 11.180340 11.180340
+34 28 14.142136 14.142136 14.142136
+34 29 8.602325 8.602325 8.602325
+34 30 11.180340 11.180340 11.180340
+34 31 5.830952 5.830952 5.830952
+34 32 10.440307 10.440307 10.440307
+34 33 5.385165 5.385165 5.385165
+34 35 10.000000 10.000000 10.000000
+34 36 62.641839 62.641839 62.641839
+34 37 63.245553 63.245553 63.245553
+34 38 60.406953 60.406953 60.406953
+34 39 59.615434 59.615434 59.615434
+34 40 60.415230 60.415230 60.415230
+34 41 65.000000 65.000000 65.000000
+34 42 56.824291 56.824291 56.824291
+34 43 62.649820 62.649820 62.649820
+34 44 67.082039 67.082039 67.082039
+34 45 64.412732 64.412732 64.412732
+34 46 86.452299 86.452299 86.452299
+34 47 86.683332 86.683332 86.683332
+34 48 85.375641 85.375641 85.375641
+34 49 47.423623 47.423623 47.423623
+34 50 44.922155 44.922155 44.922155
+34 51 16.401219 16.401219 16.401219
+34 52 30.413813 30.413813 30.413813
+34 53 60.207973 60.207973 60.207973
+34 54 69.641941 69.641941 69.641941
+34 55 46.097722 46.097722 46.097722
+34 56 65.192024 65.192024 65.192024
+34 57 36.400549 36.400549 36.400549
+34 58 55.000000 55.000000 55.000000
+34 59 71.589105 71.589105 71.589105
+34 60 75.166482 75.166482 75.166482
+34 61 78.262379 78.262379 78.262379
+34 62 56.568542 56.568542 56.568542
+34 63 22.360680 22.360680 22.360680
+34 64 20.615528 20.615528 20.615528
+34 65 40.311289 40.311289 40.311289
+34 66 52.201533 52.201533 52.201533
+34 67 45.607017 45.607017 45.607017
+34 68 27.018512 27.018512 27.018512
+34 69 57.008771 57.008771 57.008771
+34 70 60.373835 60.373835 60.373835
+34 71 66.603303 66.603303 66.603303
+34 72 36.055513 36.055513 36.055513
+34 73 45.650849 45.650849 45.650849
+34 74 90.077744 90.077744 90.077744
+34 75 65.192024 65.192024 65.192024
+34 76 82.462113 82.462113 82.462113
+34 77 28.178006 28.178006 28.178006
+34 78 65.787537 65.787537 65.787537
+34 79 83.006024 83.006024 83.006024
+34 80 89.944427 89.944427 89.944427
+34 81 43.908997 43.908997 43.908997
+34 82 48.836462 48.836462 48.836462
+34 83 60.728906 60.728906 60.728906
+34 84 48.373546 48.373546 48.373546
+34 85 28.284271 28.284271 28.284271
+34 86 22.090722 22.090722 22.090722
+34 87 64.007812 64.007812 64.007812
+34 88 73.006849 73.006849 73.006849
+34 89 69.354164 69.354164 69.354164
+34 90 26.907248 26.907248 26.907248
+34 91 52.801515 52.801515 52.801515
+34 92 39.812058 39.812058 39.812058
+34 93 36.715120 36.715120 36.715120
+34 94 36.124784 36.124784 36.124784
+34 95 36.235342 36.235342 36.235342
+34 96 31.384710 31.384710 31.384710
+34 97 41.725292 41.725292 41.725292
+34 98 81.301906 81.301906 81.301906
+34 99 64.884513 64.884513 64.884513
+34 100 59.841457 59.841457 59.841457
+34 101 68.410526 68.410526 68.410526
+35 1 47.434165 47.434165 47.434165
+35 2 78.102497 78.102497 78.102497
+35 3 74.625733 74.625733 74.625733
+35 4 80.430094 80.430094 80.430094
+35 5 79.056942 79.056942 79.056942
+35 6 82.006097 82.006097 82.006097
+35 7 78.032045 78.032045 78.032045
+35 8 80.622577 80.622577 80.622577
+35 9 83.216585 83.216585 83.216585
+35 10 75.000000 75.000000 75.000000
+35 11 75.166482 75.166482 75.166482
+35 12 77.162167 77.162167 77.162167
+35 13 77.646635 77.646635 77.646635
+35 14 80.000000 80.000000 80.000000
+35 15 80.622577 80.622577 80.622577
+35 16 83.150466 83.150466 83.150466
+35 17 85.146932 85.146932 85.146932
+35 18 85.586214 85.586214 85.586214
+35 19 50.803543 50.803543 50.803543
+35 20 49.739320 49.739320 49.739320
+35 21 47.423623 47.423623 47.423623
+35 22 54.083269 54.083269 54.083269
+35 23 49.244289 49.244289 49.244289
+35 24 55.758407 55.758407 55.758407
+35 25 51.078371 51.078371 51.078371
+35 26 58.309519 58.309519 58.309519
+35 27 11.180340 11.180340 11.180340
+35 28 10.000000 10.000000 10.000000
+35 29 8.602325 8.602325 8.602325
+35 30 5.000000 5.000000 5.000000
+35 31 5.830952 5.830952 5.830952
+35 32 3.000000 3.000000 3.000000
+35 33 5.385165 5.385165 5.385165
+35 34 10.000000 10.000000 10.000000
+35 36 53.141321 53.141321 53.141321
+35 37 53.851648 53.851648 53.851648
+35 38 51.078371 51.078371 51.078371
+35 39 50.537115 50.537115 50.537115
+35 40 51.478151 51.478151 51.478151
+35 41 55.901699 55.901699 55.901699
+35 42 48.259714 48.259714 48.259714
+35 43 54.083269 54.083269 54.083269
+35 44 58.309519 58.309519 58.309519
+35 45 55.758407 55.758407 55.758407
+35 46 80.212219 80.212219 80.212219
+35 47 80.709355 80.709355 80.709355
+35 48 83.600239 83.600239 83.600239
+35 49 52.430907 52.430907 52.430907
+35 50 48.764741 48.764741 48.764741
+35 51 13.000000 13.000000 13.000000
+35 52 33.541020 33.541020 33.541020
+35 53 60.207973 60.207973 60.207973
+35 54 66.708320 66.708320 66.708320
+35 55 39.051248 39.051248 39.051248
+35 56 60.415230 60.415230 60.415230
+35 57 35.000000 35.000000 35.000000
+35 58 55.901699 55.901699 55.901699
+35 59 74.330344 74.330344 74.330344
+35 60 76.485293 76.485293 76.485293
+35 61 74.330344 74.330344 74.330344
+35 62 50.000000 50.000000 50.000000
+35 63 20.000000 20.000000 20.000000
+35 64 25.000000 25.000000 25.000000
+35 65 40.311289 40.311289 40.311289
+35 66 50.249378 50.249378 50.249378
+35 67 44.045431 44.045431 44.045431
+35 68 22.135944 22.135944 22.135944
+35 69 51.478151 51.478151 51.478151
+35 70 56.612719 56.612719 56.612719
+35 71 60.464866 60.464866 60.464866
+35 72 28.284271 28.284271 28.284271
+35 73 37.202150 37.202150 37.202150
+35 74 86.683332 86.683332 86.683332
+35 75 66.708320 66.708320 66.708320
+35 76 85.440037 85.440037 85.440037
+35 77 33.970576 33.970576 33.970576
+35 78 69.771054 69.771054 69.771054
+35 79 79.812280 79.812280 79.812280
+35 80 85.615419 85.615419 85.615419
+35 81 39.849718 39.849718 39.849718
+35 82 42.720019 42.720019 42.720019
+35 83 58.549125 58.549125 58.549125
+35 84 48.166378 48.166378 48.166378
+35 85 28.635642 28.635642 28.635642
+35 86 25.059928 25.059928 25.059928
+35 87 64.938432 64.938432 64.938432
+35 88 73.824115 73.824115 73.824115
+35 89 65.192024 65.192024 65.192024
+35 90 34.985711 34.985711 34.985711
+35 91 49.477268 49.477268 49.477268
+35 92 36.674242 36.674242 36.674242
+35 93 32.984845 32.984845 32.984845
+35 94 29.410882 29.410882 29.410882
+35 95 30.870698 30.870698 30.870698
+35 96 29.068884 29.068884 29.068884
+35 97 35.510562 35.510562 35.510562
+35 98 82.764727 82.764727 82.764727
+35 99 61.400326 61.400326 61.400326
+35 100 59.000000 59.000000 59.000000
+35 101 62.769419 62.769419 62.769419
+36 1 44.204072 44.204072 44.204072
+36 2 42.000000 42.000000 42.000000
+36 3 46.097722 46.097722 46.097722
+36 4 45.000000 45.000000 45.000000
+36 5 47.265209 47.265209 47.265209
+36 6 47.000000 47.000000 47.000000
+36 7 50.009999 50.009999 50.009999
+36 8 52.952809 52.952809 52.952809
+36 9 52.239832 52.239832 52.239832
+36 10 75.822160 75.822160 75.822160
+36 11 72.622311 72.622311 72.622311
+36 12 74.202426 74.202426 74.202426
+36 13 71.281134 71.281134 71.281134
+36 14 79.649231 79.649231 79.649231
+36 15 73.783467 73.783467 73.783467
+36 16 79.056942 79.056942 79.056942
+36 17 80.709355 80.709355 80.709355
+36 18 78.032045 78.032045 78.032045
+36 19 83.240615 83.240615 83.240615
+36 20 79.056942 79.056942 79.056942
+36 21 74.330344 74.330344 74.330344
+36 22 84.433406 84.433406 84.433406
+36 23 75.026662 75.026662 75.026662
+36 24 85.094066 85.094066 85.094066
+36 25 75.769387 75.769387 75.769387
+36 26 86.162637 86.162637 86.162637
+36 27 61.717096 61.717096 61.717096
+36 28 57.306195 57.306195 57.306195
+36 29 60.415230 60.415230 60.415230
+36 30 55.036352 55.036352 55.036352
+36 31 58.872744 58.872744 58.872744
+36 32 54.230987 54.230987 54.230987
+36 33 58.523500 58.523500 58.523500
+36 34 62.641839 62.641839 62.641839
+36 35 53.141321 53.141321 53.141321
+36 37 2.000000 2.000000 2.000000
+36 38 3.605551 3.605551 3.605551
+36 39 7.071068 7.071068 7.071068
+36 40 8.602325 8.602325 8.602325
+36 41 7.000000 7.000000 7.000000
+36 42 13.453624 13.453624 13.453624
+36 43 13.000000 13.000000 13.000000
+36 44 12.000000 12.000000 12.000000
+36 45 12.369317 12.369317 12.369317
+36 46 47.095647 47.095647 47.095647
+36 47 49.254441 49.254441 49.254441
+36 48 76.321688 76.321688 76.321688
+36 49 83.815273 83.815273 83.815273
+36 50 77.162167 77.162167 77.162167
+36 51 50.249378 50.249378 50.249378
+36 52 66.098411 66.098411 66.098411
+36 53 69.202601 69.202601 69.202601
+36 54 58.600341 58.600341 58.600341
+36 55 27.730849 27.730849 27.730849
+36 56 44.654227 44.654227 44.654227
+36 57 52.810984 52.810984 52.810984
+36 58 70.491134 70.491134 70.491134
+36 59 91.263355 91.263355 91.263355
+36 60 86.452299 86.452299 86.452299
+36 61 57.697487 57.697487 57.697487
+36 62 29.732137 29.732137 29.732137
+36 63 50.039984 50.039984 50.039984
+36 64 65.030762 65.030762 65.030762
+36 65 59.236813 59.236813 59.236813
+36 66 55.217751 55.217751 55.217751
+36 67 54.589376 54.589376 54.589376
+36 68 43.104524 43.104524 43.104524
+36 69 36.796739 36.796739 36.796739
+36 70 48.836462 48.836462 48.836462
+36 71 35.777088 35.777088 35.777088
+36 72 30.066593 30.066593 30.066593
+36 73 20.396078 20.396078 20.396078
+36 74 69.641941 69.641941 69.641941
+36 75 80.212219 80.212219 80.212219
+36 76 101.212647 101.212647 101.212647
+36 77 73.334848 73.334848 73.334848
+36 78 93.059121 93.059121 93.059121
+36 79 65.741920 65.741920 65.741920
+36 80 63.324561 63.324561 63.324561
+36 81 42.941821 42.941821 42.941821
+36 82 32.449961 32.449961 32.449961
+36 83 58.000000 58.000000 58.000000
+36 84 61.773781 61.773781 61.773781
+36 85 56.885851 56.885851 56.885851
+36 86 62.128898 62.128898 62.128898
+36 87 76.400262 76.400262 76.400262
+36 88 82.134037 82.134037 82.134037
+36 89 50.774009 50.774009 50.774009
+36 90 80.000000 80.000000 80.000000
+36 91 48.414874 48.414874 48.414874
+36 92 46.615448 46.615448 46.615448
+36 93 44.271887 44.271887 44.271887
+36 94 33.541020 33.541020 33.541020
+36 95 38.327536 38.327536 38.327536
+36 96 49.244289 49.244289 49.244289
+36 97 33.241540 33.241540 33.241540
+36 98 91.967386 91.967386 91.967386
+36 99 52.630789 52.630789 52.630789
+36 100 64.660653 64.660653 64.660653
+36 101 40.249224 40.249224 40.249224
+37 1 43.011626 43.011626 43.011626
+37 2 40.000000 40.000000 40.000000
+37 3 44.147480 44.147480 44.147480
+37 4 43.000000 43.000000 43.000000
+37 5 45.276926 45.276926 45.276926
+37 6 45.000000 45.000000 45.000000
+37 7 48.052055 48.052055 48.052055
+37 8 50.990195 50.990195 50.990195
+37 9 50.249378 50.249378 50.249378
+37 10 74.330344 74.330344 74.330344
+37 11 71.063352 71.063352 71.063352
+37 12 72.622311 72.622311 72.622311
+37 13 69.634761 69.634761 69.634761
+37 14 78.102497 78.102497 78.102497
+37 15 72.111026 72.111026 72.111026
+37 16 77.420927 77.420927 77.420927
+37 17 79.056942 79.056942 79.056942
+37 18 76.321688 76.321688 76.321688
+37 19 82.710338 82.710338 82.710338
+37 20 78.447435 78.447435 78.447435
+37 21 73.681748 73.681748 73.681748
+37 22 83.815273 83.815273 83.815273
+37 23 74.330344 74.330344 74.330344
+37 24 84.433406 84.433406 84.433406
+37 25 75.026662 75.026662 75.026662
+37 26 85.440037 85.440037 85.440037
+37 27 62.649820 62.649820 62.649820
+37 28 58.309519 58.309519 58.309519
+37 29 61.269895 61.269895 61.269895
+37 30 55.901699 55.901699 55.901699
+37 31 59.615434 59.615434 59.615434
+37 32 55.036352 55.036352 55.036352
+37 33 59.236813 59.236813 59.236813
+37 34 63.245553 63.245553 63.245553
+37 35 53.851648 53.851648 53.851648
+37 36 2.000000 2.000000 2.000000
+37 38 3.000000 3.000000 3.000000
+37 39 5.830952 5.830952 5.830952
+37 40 7.071068 7.071068 7.071068
+37 41 5.000000 5.000000 5.000000
+37 42 12.206556 12.206556 12.206556
+37 43 11.180340 11.180340 11.180340
+37 44 10.000000 10.000000 10.000000
+37 45 10.440307 10.440307 10.440307
+37 46 45.099889 45.099889 45.099889
+37 47 47.265209 47.265209 47.265209
+37 48 74.625733 74.625733 74.625733
+37 49 83.240615 83.240615 83.240615
+37 50 76.537572 76.537572 76.537572
+37 51 50.487622 50.487622 50.487622
+37 52 65.764732 65.764732 65.764732
+37 53 68.007353 68.007353 68.007353
+37 54 57.008771 57.008771 57.008771
+37 55 26.925824 26.925824 26.925824
+37 56 43.011626 43.011626 43.011626
+37 57 52.201533 52.201533 52.201533
+37 58 69.462220 69.462220 69.462220
+37 59 90.138782 90.138782 90.138782
+37 60 85.146932 85.146932 85.146932
+37 61 55.901699 55.901699 55.901699
+37 62 28.284271 28.284271 28.284271
+37 63 50.000000 50.000000 50.000000
+37 64 65.000000 65.000000 65.000000
+37 65 58.523500 58.523500 58.523500
+37 66 54.083269 54.083269 54.083269
+37 67 53.665631 53.665631 53.665631
+37 68 43.011626 43.011626 43.011626
+37 69 35.355339 35.355339 35.355339
+37 70 47.381431 47.381431 47.381431
+37 71 34.000000 34.000000 34.000000
+37 72 30.000000 30.000000 30.000000
+37 73 20.099751 20.099751 20.099751
+37 74 67.779053 67.779053 67.779053
+37 75 79.056942 79.056942 79.056942
+37 76 100.000000 100.000000 100.000000
+37 77 73.171033 73.171033 73.171033
+37 78 92.130342 92.130342 92.130342
+37 79 63.953108 63.953108 63.953108
+37 80 61.400326 61.400326 61.400326
+37 81 42.047592 42.047592 42.047592
+37 82 31.384710 31.384710 31.384710
+37 83 56.639209 56.639209 56.639209
+37 84 60.827625 60.827625 60.827625
+37 85 56.568542 56.568542 56.568542
+37 86 62.032250 62.032250 62.032250
+37 87 75.213031 75.213031 75.213031
+37 88 80.808415 80.808415 80.808415
+37 89 49.091751 49.091751 49.091751
+37 90 80.024996 80.024996 80.024996
+37 91 47.201695 47.201695 47.201695
+37 92 45.880279 45.880279 45.880279
+37 93 43.680659 43.680659 43.680659
+37 94 33.241540 33.241540 33.241540
+37 95 37.854986 37.854986 37.854986
+37 96 48.836462 48.836462 48.836462
+37 97 32.572995 32.572995 32.572995
+37 98 90.609050 90.609050 90.609050
+37 99 51.088159 51.088159 51.088159
+37 100 63.411355 63.411355 63.411355
+37 101 38.470768 38.470768 38.470768
+38 1 40.607881 40.607881 40.607881
+38 2 40.112342 40.112342 40.112342
+38 3 43.566042 43.566042 43.566042
+38 4 43.104524 43.104524 43.104524
+38 5 45.044423 45.044423 45.044423
+38 6 45.099889 45.099889 45.099889
+38 7 47.518417 47.518417 47.518417
+38 8 50.487622 50.487622 50.487622
+38 9 50.039984 50.039984 50.039984
+38 10 72.346389 72.346389 72.346389
+38 11 69.202601 69.202601 69.202601
+38 12 70.802542 70.802542 70.802542
+38 13 67.955868 67.955868 67.955868
+38 14 76.216796 76.216796 76.216796
+38 15 70.491134 70.491134 70.491134
+38 16 75.716577 75.716577 75.716577
+38 17 77.388630 77.388630 77.388630
+38 18 74.793048 74.793048 74.793048
+38 19 79.812280 79.812280 79.812280
+38 20 75.584390 75.584390 75.584390
+38 21 70.837843 70.837843 70.837843
+38 22 80.956779 80.956779 80.956779
+38 23 71.512237 71.512237 71.512237
+38 24 81.596569 81.596569 81.596569
+38 25 72.235725 72.235725 72.235725
+38 26 82.637764 82.637764 82.637764
+38 27 60.033324 60.033324 60.033324
+38 28 55.758407 55.758407 55.758407
+38 29 58.591808 58.591808 58.591808
+38 30 53.235327 53.235327 53.235327
+38 31 56.859476 56.859476 56.859476
+38 32 52.325902 52.325902 52.325902
+38 33 56.462377 56.462377 56.462377
+38 34 60.406953 60.406953 60.406953
+38 35 51.078371 51.078371 51.078371
+38 36 3.605551 3.605551 3.605551
+38 37 3.000000 3.000000 3.000000
+38 39 3.605551 3.605551 3.605551
+38 40 5.385165 5.385165 5.385165
+38 41 5.830952 5.830952 5.830952
+38 42 9.899495 9.899495 9.899495
+38 43 10.198039 10.198039 10.198039
+38 44 10.440307 10.440307 10.440307
+38 45 10.000000 10.000000 10.000000
+38 46 45.000000 45.000000 45.000000
+38 47 47.042534 47.042534 47.042534
+38 48 73.061618 73.061618 73.061618
+38 49 80.361682 80.361682 80.361682
+38 50 73.681748 73.681748 73.681748
+38 51 47.518417 47.518417 47.518417
+38 52 62.801274 62.801274 62.801274
+38 53 65.604878 65.604878 65.604878
+38 54 55.217751 55.217751 55.217751
+38 55 24.166092 24.166092 24.166092
+38 56 41.340053 41.340053 41.340053
+38 57 49.335586 49.335586 49.335586
+38 58 66.887966 66.887966 66.887966
+38 59 87.658428 87.658428 87.658428
+38 60 82.879430 82.879430 82.879430
+38 61 54.626001 54.626001 54.626001
+38 62 26.248809 26.248809 26.248809
+38 63 47.000000 47.000000 47.000000
+38 64 62.000000 62.000000 62.000000
+38 65 55.713553 55.713553 55.713553
+38 66 51.613952 51.613952 51.613952
+38 67 51.000000 51.000000 51.000000
+38 68 40.012498 40.012498 40.012498
+38 69 33.301652 33.301652 33.301652
+38 70 45.343136 45.343136 45.343136
+38 71 32.695565 32.695565 32.695565
+38 72 27.000000 27.000000 27.000000
+38 73 17.117243 17.117243 17.117243
+38 74 66.730802 66.730802 66.730802
+38 75 76.609399 76.609399 76.609399
+38 76 97.616597 97.616597 97.616597
+38 77 70.178344 70.178344 70.178344
+38 78 89.470666 89.470666 89.470666
+38 79 62.649820 62.649820 62.649820
+38 80 60.638272 60.638272 60.638272
+38 81 39.357337 39.357337 39.357337
+38 82 28.844410 28.844410 28.844410
+38 83 54.451814 54.451814 54.451814
+38 84 58.180753 58.180753 58.180753
+38 85 53.600373 53.600373 53.600373
+38 86 59.033889 59.033889 59.033889
+38 87 72.801099 72.801099 72.801099
+38 88 78.568442 78.568442 78.568442
+38 89 47.507894 47.507894 47.507894
+38 90 77.025970 77.025970 77.025970
+38 91 44.821870 44.821870 44.821870
+38 92 43.081318 43.081318 43.081318
+38 93 40.804412 40.804412 40.804412
+38 94 30.265492 30.265492 30.265492
+38 95 34.928498 34.928498 34.928498
+38 96 45.891176 45.891176 45.891176
+38 97 29.732137 29.732137 29.732137
+38 98 88.413800 88.413800 88.413800
+38 99 49.203658 49.203658 49.203658
+38 100 61.073726 61.073726 61.073726
+38 101 37.161808 37.161808 37.161808
+39 1 37.202150 37.202150 37.202150
+39 2 37.336309 37.336309 37.336309
+39 3 40.311289 40.311289 40.311289
+39 4 40.311289 40.311289 40.311289
+39 5 42.000000 42.000000 42.000000
+39 6 42.296572 42.296572 42.296572
+39 7 44.283180 44.283180 44.283180
+39 8 47.265209 47.265209 47.265209
+39 9 47.000000 47.000000 47.000000
+39 10 68.767725 68.767725 68.767725
+39 11 65.604878 65.604878 65.604878
+39 12 67.201190 67.201190 67.201190
+39 13 64.350602 64.350602 64.350602
+39 14 72.622311 72.622311 72.622311
+39 15 66.887966 66.887966 66.887966
+39 16 72.111026 72.111026 72.111026
+39 17 73.783467 73.783467 73.783467
+39 18 71.196910 71.196910 71.196910
+39 19 77.129761 77.129761 77.129761
+39 20 72.801099 72.801099 72.801099
+39 21 68.007353 68.007353 68.007353
+39 22 78.160092 78.160092 78.160092
+39 23 68.622154 68.622154 68.622154
+39 24 78.746428 78.746428 78.746428
+39 25 69.289249 69.289249 69.289249
+39 26 79.711982 79.711982 79.711982
+39 27 59.908263 59.908263 59.908263
+39 28 55.803226 55.803226 55.803226
+39 29 58.309519 58.309519 58.309519
+39 30 53.000000 53.000000 53.000000
+39 31 56.356011 56.356011 56.356011
+39 32 51.971146 51.971146 51.971146
+39 33 55.901699 55.901699 55.901699
+39 34 59.615434 59.615434 59.615434
+39 35 50.537115 50.537115 50.537115
+39 36 7.071068 7.071068 7.071068
+39 37 5.830952 5.830952 5.830952
+39 38 3.605551 3.605551 3.605551
+39 40 2.000000 2.000000 2.000000
+39 41 5.385165 5.385165 5.385165
+39 42 6.403124 6.403124 6.403124
+39 43 7.000000 7.000000 7.000000
+39 44 8.602325 8.602325 8.602325
+39 45 7.280110 7.280110 7.280110
+39 46 42.047592 42.047592 42.047592
+39 47 44.000000 44.000000 44.000000
+39 48 69.462220 69.462220 69.462220
+39 49 77.620873 77.620873 77.620873
+39 50 70.880181 70.880181 70.880181
+39 51 46.097722 46.097722 46.097722
+39 52 60.406953 60.406953 60.406953
+39 53 62.201286 62.201286 62.201286
+39 54 51.613952 51.613952 51.613952
+39 55 21.189620 21.189620 21.189620
+39 56 37.735925 37.735925 37.735925
+39 57 46.572524 46.572524 46.572524
+39 58 63.631753 63.631753 63.631753
+39 59 84.314886 84.314886 84.314886
+39 60 79.397733 79.397733 79.397733
+39 61 51.078371 51.078371 51.078371
+39 62 22.671568 22.671568 22.671568
+39 63 45.099889 45.099889 45.099889
+39 64 60.074953 60.074953 60.074953
+39 65 52.810984 52.810984 52.810984
+39 66 48.259714 48.259714 48.259714
+39 67 47.853944 47.853944 47.853944
+39 68 38.052595 38.052595 38.052595
+39 69 29.732137 29.732137 29.732137
+39 70 41.773197 41.773197 41.773197
+39 71 29.154759 29.154759 29.154759
+39 72 25.179357 25.179357 25.179357
+39 73 15.033296 15.033296 15.033296
+39 74 63.245553 63.245553 63.245553
+39 75 73.239334 73.239334 73.239334
+39 76 94.201911 94.201911 94.201911
+39 77 68.029405 68.029405 68.029405
+39 78 86.313383 86.313383 86.313383
+39 79 59.093147 59.093147 59.093147
+39 80 57.271284 57.271284 57.271284
+39 81 36.249138 36.249138 36.249138
+39 82 25.553865 25.553865 25.553865
+39 83 50.931326 50.931326 50.931326
+39 84 55.009090 55.009090 55.009090
+39 85 51.244512 51.244512 51.244512
+39 86 57.008771 57.008771 57.008771
+39 87 69.404611 69.404611 69.404611
+39 88 75.073298 75.073298 75.073298
+39 89 43.908997 43.908997 43.908997
+39 90 75.166482 75.166482 75.166482
+39 91 41.400483 41.400483 41.400483
+39 92 40.162171 40.162171 40.162171
+39 93 38.078866 38.078866 38.078866
+39 94 28.017851 28.017851 28.017851
+39 95 32.388269 32.388269 32.388269
+39 96 43.416587 43.416587 43.416587
+39 97 26.925824 26.925824 26.925824
+39 98 84.899941 84.899941 84.899941
+39 99 45.607017 45.607017 45.607017
+39 100 57.628118 57.628118 57.628118
+39 101 33.615473 33.615473 33.615473
+40 1 36.055513 36.055513 36.055513
+40 2 35.355339 35.355339 35.355339
+40 3 38.327536 38.327536 38.327536
+40 4 38.327536 38.327536 38.327536
+40 5 40.000000 40.000000 40.000000
+40 6 40.311289 40.311289 40.311289
+40 7 42.296572 42.296572 42.296572
+40 8 45.276926 45.276926 45.276926
+40 9 45.000000 45.000000 45.000000
+40 10 67.268120 67.268120 67.268120
+40 11 64.031242 64.031242 64.031242
+40 12 65.604878 65.604878 65.604878
+40 13 62.681736 62.681736 62.681736
+40 14 71.063352 71.063352 71.063352
+40 15 65.192024 65.192024 65.192024
+40 16 70.455660 70.455660 70.455660
+40 17 72.111026 72.111026 72.111026
+40 18 69.462220 69.462220 69.462220
+40 19 76.687678 76.687678 76.687678
+40 20 72.277244 72.277244 72.277244
+40 21 67.446275 67.446275 67.446275
+40 22 77.620873 77.620873 77.620873
+40 23 68.007353 68.007353 68.007353
+40 24 78.160092 78.160092 78.160092
+40 25 68.622154 68.622154 68.622154
+40 26 79.056942 79.056942 79.056942
+40 27 61.032778 61.032778 61.032778
+40 28 57.008771 57.008771 57.008771
+40 29 59.363288 59.363288 59.363288
+40 30 54.083269 54.083269 54.083269
+40 31 57.306195 57.306195 57.306195
+40 32 53.000000 53.000000 53.000000
+40 33 56.824291 56.824291 56.824291
+40 34 60.415230 60.415230 60.415230
+40 35 51.478151 51.478151 51.478151
+40 36 8.602325 8.602325 8.602325
+40 37 7.071068 7.071068 7.071068
+40 38 5.385165 5.385165 5.385165
+40 39 2.000000 2.000000 2.000000
+40 41 5.000000 5.000000 5.000000
+40 42 5.385165 5.385165 5.385165
+40 43 5.000000 5.000000 5.000000
+40 44 7.071068 7.071068 7.071068
+40 45 5.385165 5.385165 5.385165
+40 46 40.049969 40.049969 40.049969
+40 47 42.000000 42.000000 42.000000
+40 48 67.742158 67.742158 67.742158
+40 49 77.129761 77.129761 77.129761
+40 50 70.342022 70.342022 70.342022
+40 51 46.572524 46.572524 46.572524
+40 52 60.207973 60.207973 60.207973
+40 53 61.032778 61.032778 61.032778
+40 54 50.000000 50.000000 50.000000
+40 55 20.615528 20.615528 20.615528
+40 56 36.055513 36.055513 36.055513
+40 57 46.097722 46.097722 46.097722
+40 58 62.649820 62.649820 62.649820
+40 59 83.216585 83.216585 83.216585
+40 60 78.102497 78.102497 78.102497
+40 61 49.244289 49.244289 49.244289
+40 62 21.213203 21.213203 21.213203
+40 63 45.276926 45.276926 45.276926
+40 64 60.207973 60.207973 60.207973
+40 65 52.201533 52.201533 52.201533
+40 66 47.169906 47.169906 47.169906
+40 67 47.010637 47.010637 47.010637
+40 68 38.209946 38.209946 38.209946
+40 69 28.284271 28.284271 28.284271
+40 70 40.311289 40.311289 40.311289
+40 71 27.313001 27.313001 27.313001
+40 72 25.495098 25.495098 25.495098
+40 73 15.297059 15.297059 15.297059
+40 74 61.351447 61.351447 61.351447
+40 75 72.111026 72.111026 72.111026
+40 76 93.005376 93.005376 93.005376
+40 77 68.000000 68.000000 68.000000
+40 78 85.428333 85.428333 85.428333
+40 79 57.271284 57.271284 57.271284
+40 80 55.317267 55.317267 55.317267
+40 81 35.468296 35.468296 35.468296
+40 82 24.596748 24.596748 24.596748
+40 83 49.578221 49.578221 49.578221
+40 84 54.129474 54.129474 54.129474
+40 85 51.088159 51.088159 51.088159
+40 86 57.078893 57.078893 57.078893
+40 87 68.242216 68.242216 68.242216
+40 88 73.756356 73.756356 73.756356
+40 89 42.190046 42.190046 42.190046
+40 90 75.325958 75.325958 75.325958
+40 91 40.224371 40.224371 40.224371
+40 92 39.560081 39.560081 39.560081
+40 93 37.656341 37.656341 37.656341
+40 94 28.017851 28.017851 28.017851
+40 95 32.140317 32.140317 32.140317
+40 96 43.185646 43.185646 43.185646
+40 97 26.476405 26.476405 26.476405
+40 98 83.546394 83.546394 83.546394
+40 99 44.045431 44.045431 44.045431
+40 100 56.400355 56.400355 56.400355
+40 101 31.780497 31.780497 31.780497
+41 1 40.311289 40.311289 40.311289
+41 2 35.000000 35.000000 35.000000
+41 3 39.293765 39.293765 39.293765
+41 4 38.000000 38.000000 38.000000
+41 5 40.311289 40.311289 40.311289
+41 6 40.000000 40.000000 40.000000
+41 7 43.174066 43.174066 43.174066
+41 8 46.097722 46.097722 46.097722
+41 9 45.276926 45.276926 45.276926
+41 10 70.710678 70.710678 70.710678
+41 11 67.268120 67.268120 67.268120
+41 12 68.767725 68.767725 68.767725
+41 13 65.604878 65.604878 65.604878
+41 14 74.330344 74.330344 74.330344
+41 15 68.007353 68.007353 68.007353
+41 16 73.409809 73.409809 73.409809
+41 17 75.000000 75.000000 75.000000
+41 18 72.111026 72.111026 72.111026
+41 19 81.584312 81.584312 81.584312
+41 20 77.129761 77.129761 77.129761
+41 21 72.277244 72.277244 72.277244
+41 22 82.462113 82.462113 82.462113
+41 23 72.801099 72.801099 72.801099
+41 24 82.969874 82.969874 82.969874
+41 25 73.375745 73.375745 73.375745
+41 26 83.815273 83.815273 83.815273
+41 27 65.192024 65.192024 65.192024
+41 28 61.032778 61.032778 61.032778
+41 29 63.631753 63.631753 63.631753
+41 30 58.309519 58.309519 58.309519
+41 31 61.717096 61.717096 61.717096
+41 32 57.306195 57.306195 57.306195
+41 33 61.269895 61.269895 61.269895
+41 34 65.000000 65.000000 65.000000
+41 35 55.901699 55.901699 55.901699
+41 36 7.000000 7.000000 7.000000
+41 37 5.000000 5.000000 5.000000
+41 38 5.830952 5.830952 5.830952
+41 39 5.385165 5.385165 5.385165
+41 40 5.000000 5.000000 5.000000
+41 42 10.198039 10.198039 10.198039
+41 43 7.071068 7.071068 7.071068
+41 44 5.000000 5.000000 5.000000
+41 45 5.830952 5.830952 5.830952
+41 46 40.112342 40.112342 40.112342
+41 47 42.296572 42.296572 42.296572
+41 48 70.455660 70.455660 70.455660
+41 49 82.000000 82.000000 82.000000
+41 50 75.186435 75.186435 75.186435
+41 51 51.419841 51.419841 51.419841
+41 52 65.192024 65.192024 65.192024
+41 53 65.192024 65.192024 65.192024
+41 54 53.150729 53.150729 53.150729
+41 55 25.495098 25.495098 25.495098
+41 56 39.051248 39.051248 39.051248
+41 57 50.990195 50.990195 50.990195
+41 58 67.082039 67.082039 67.082039
+41 59 87.464278 87.464278 87.464278
+41 60 82.006097 82.006097 82.006097
+41 61 51.478151 51.478151 51.478151
+41 62 25.000000 25.000000 25.000000
+41 63 50.249378 50.249378 50.249378
+41 64 65.192024 65.192024 65.192024
+41 65 57.008771 57.008771 57.008771
+41 66 51.478151 51.478151 51.478151
+41 67 51.623638 51.623638 51.623638
+41 68 43.185646 43.185646 43.185646
+41 69 32.015621 32.015621 32.015621
+41 70 43.931765 43.931765 43.931765
+41 71 29.681644 29.681644 29.681644
+41 72 30.413813 30.413813 30.413813
+41 73 20.223748 20.223748 20.223748
+41 74 63.158531 63.158531 63.158531
+41 75 76.321688 76.321688 76.321688
+41 76 97.082439 97.082439 97.082439
+41 77 73.000000 73.000000 73.000000
+41 78 89.961103 89.961103 89.961103
+41 79 59.539903 59.539903 59.539903
+41 80 56.612719 56.612719 56.612719
+41 81 40.162171 40.162171 40.162171
+41 82 29.154759 29.154759 29.154759
+41 83 53.413481 53.413481 53.413481
+41 84 58.694122 58.694122 58.694122
+41 85 56.080300 56.080300 56.080300
+41 86 62.072538 62.072538 62.072538
+41 87 72.401657 72.401657 72.401657
+41 88 77.620873 77.620873 77.620873
+41 89 45.000000 45.000000 45.000000
+41 90 80.305666 80.305666 80.305666
+41 91 44.418465 44.418465 44.418465
+41 92 44.384682 44.384682 44.384682
+41 93 42.579338 42.579338 42.579338
+41 94 33.015148 33.015148 33.015148
+41 95 37.121422 37.121422 37.121422
+41 96 48.166378 48.166378 48.166378
+41 97 31.400637 31.400637 31.400637
+41 98 87.321246 87.321246 87.321246
+41 99 47.381431 47.381431 47.381431
+41 100 60.464866 60.464866 60.464866
+41 101 34.132096 34.132096 34.132096
+42 1 30.805844 30.805844 30.805844
+42 2 34.481879 34.481879 34.481879
+42 3 36.000000 36.000000 36.000000
+42 4 37.363083 37.363083 37.363083
+42 5 38.327536 38.327536 38.327536
+42 6 39.293765 39.293765 39.293765
+42 7 40.000000 40.000000 40.000000
+42 8 43.000000 43.000000 43.000000
+42 9 43.289722 43.289722 43.289722
+42 10 62.481997 62.481997 62.481997
+42 11 59.405387 59.405387 59.405387
+42 12 61.032778 61.032778 61.032778
+42 13 58.309519 58.309519 58.309519
+42 14 66.400301 66.400301 66.400301
+42 15 60.901560 60.901560 60.901560
+42 16 66.037868 66.037868 66.037868
+42 17 67.742158 67.742158 67.742158
+42 18 65.299311 65.299311 65.299311
+42 19 71.386273 71.386273 71.386273
+42 20 66.940272 66.940272 66.940272
+42 21 62.096699 62.096699 62.096699
+42 22 72.277244 72.277244 72.277244
+42 23 62.641839 62.641839 62.641839
+42 24 72.801099 72.801099 72.801099
+42 25 63.245553 63.245553 63.245553
+42 26 73.681748 73.681748 73.681748
+42 27 58.258047 58.258047 58.258047
+42 28 54.488531 54.488531 54.488531
+42 29 56.400355 56.400355 56.400355
+42 30 51.224994 51.224994 51.224994
+42 31 54.083269 54.083269 54.083269
+42 32 50.000000 50.000000 50.000000
+42 33 53.535035 53.535035 53.535035
+42 34 56.824291 56.824291 56.824291
+42 35 48.259714 48.259714 48.259714
+42 36 13.453624 13.453624 13.453624
+42 37 12.206556 12.206556 12.206556
+42 38 9.899495 9.899495 9.899495
+42 39 6.403124 6.403124 6.403124
+42 40 5.385165 5.385165 5.385165
+42 41 10.198039 10.198039 10.198039
+42 43 5.830952 5.830952 5.830952
+42 44 10.440307 10.440307 10.440307
+42 45 7.615773 7.615773 7.615773
+42 46 38.639358 38.639358 38.639358
+42 47 40.311289 40.311289 40.311289
+42 48 63.529521 63.529521 63.529521
+42 49 71.805292 71.805292 71.805292
+42 50 65.000000 65.000000 65.000000
+42 51 42.379240 42.379240 42.379240
+42 52 55.081757 55.081757 55.081757
+42 53 55.803226 55.803226 55.803226
+42 54 45.486262 45.486262 45.486262
+42 55 15.297059 15.297059 15.297059
+42 56 31.764760 31.764760 31.764760
+42 57 40.792156 40.792156 40.792156
+42 58 57.306195 57.306195 57.306195
+42 59 77.935871 77.935871 77.935871
+42 60 73.000000 73.000000 73.000000
+42 61 45.541190 45.541190 45.541190
+42 62 16.401219 16.401219 16.401219
+42 63 40.607881 40.607881 40.607881
+42 64 55.443665 55.443665 55.443665
+42 65 46.840154 46.840154 46.840154
+42 66 41.880783 41.880783 41.880783
+42 67 41.629317 41.629317 41.629317
+42 68 33.541020 33.541020 33.541020
+42 69 23.430749 23.430749 23.430749
+42 70 35.468296 35.468296 35.468296
+42 71 23.769729 23.769729 23.769729
+42 72 21.189620 21.189620 21.189620
+42 73 11.180340 11.180340 11.180340
+42 74 57.974132 57.974132 57.974132
+42 75 66.850580 66.850580 66.850580
+42 76 87.800911 87.800911 87.800911
+42 77 63.031738 63.031738 63.031738
+42 78 80.056230 80.056230 80.056230
+42 79 53.488316 53.488316 53.488316
+42 80 52.469038 52.469038 52.469038
+42 81 30.083218 30.083218 30.083218
+42 82 19.235384 19.235384 19.235384
+42 83 44.553339 44.553339 44.553339
+42 84 48.754487 48.754487 48.754487
+42 85 46.010868 46.010868 46.010868
+42 86 52.239832 52.239832 52.239832
+42 87 63.007936 63.007936 63.007936
+42 88 68.680419 68.680419 68.680419
+42 89 38.013156 38.013156 38.013156
+42 90 70.576200 70.576200 70.576200
+42 91 35.000000 35.000000 35.000000
+42 92 34.205263 34.205263 34.205263
+42 93 32.388269 32.388269 32.388269
+42 94 23.194827 23.194827 23.194827
+42 95 27.018512 27.018512 27.018512
+42 96 38.052595 38.052595 38.052595
+42 97 21.213203 21.213203 21.213203
+42 98 78.517514 78.517514 78.517514
+42 99 39.408121 39.408121 39.408121
+42 100 51.224994 51.224994 51.224994
+42 101 28.160256 28.160256 28.160256
+43 1 33.541020 33.541020 33.541020
+43 2 30.413813 30.413813 30.413813
+43 3 33.376639 33.376639 33.376639
+43 4 33.376639 33.376639 33.376639
+43 5 35.000000 35.000000 35.000000
+43 6 35.355339 35.355339 35.355339
+43 7 37.336309 37.336309 37.336309
+43 8 40.311289 40.311289 40.311289
+43 9 40.000000 40.000000 40.000000
+43 10 63.639610 63.639610 63.639610
+43 11 60.207973 60.207973 60.207973
+43 12 61.717096 61.717096 61.717096
+43 13 58.600341 58.600341 58.600341
+43 14 67.268120 67.268120 67.268120
+43 15 61.032778 61.032778 61.032778
+43 16 66.400301 66.400301 66.400301
+43 17 68.007353 68.007353 68.007353
+43 18 65.192024 65.192024 65.192024
+43 19 75.802375 75.802375 75.802375
+43 20 71.196910 71.196910 71.196910
+43 21 66.287254 66.287254 66.287254
+43 22 76.485293 76.485293 76.485293
+43 23 66.708320 66.708320 66.708320
+43 24 76.902536 76.902536 76.902536
+43 25 67.186308 67.186308 67.186308
+43 26 77.620873 77.620873 77.620873
+43 27 64.031242 64.031242 64.031242
+43 28 60.207973 60.207973 60.207973
+43 29 62.201286 62.201286 62.201286
+43 30 57.008771 57.008771 57.008771
+43 31 59.908263 59.908263 59.908263
+43 32 55.803226 55.803226 55.803226
+43 33 59.363288 59.363288 59.363288
+43 34 62.649820 62.649820 62.649820
+43 35 54.083269 54.083269 54.083269
+43 36 13.000000 13.000000 13.000000
+43 37 11.180340 11.180340 11.180340
+43 38 10.198039 10.198039 10.198039
+43 39 7.000000 7.000000 7.000000
+43 40 5.000000 5.000000 5.000000
+43 41 7.071068 7.071068 7.071068
+43 42 5.830952 5.830952 5.830952
+43 44 5.000000 5.000000 5.000000
+43 45 2.000000 2.000000 2.000000
+43 46 35.057096 35.057096 35.057096
+43 47 37.000000 37.000000 37.000000
+43 48 63.513778 63.513778 63.513778
+43 49 76.118329 76.118329 76.118329
+43 50 69.231496 69.231496 69.231496
+43 51 48.104054 48.104054 48.104054
+43 52 60.000000 60.000000 60.000000
+43 53 58.309519 58.309519 58.309519
+43 54 46.097722 46.097722 46.097722
+43 55 20.000000 20.000000 20.000000
+43 56 32.015621 32.015621 32.015621
+43 57 45.276926 45.276926 45.276926
+43 58 60.415230 60.415230 60.415230
+43 59 80.622577 80.622577 80.622577
+43 60 75.000000 75.000000 75.000000
+43 61 44.721360 44.721360 44.721360
+43 62 18.027756 18.027756 18.027756
+43 63 46.097722 46.097722 46.097722
+43 64 60.827625 60.827625 60.827625
+43 65 50.990195 50.990195 50.990195
+43 66 44.721360 44.721360 44.721360
+43 67 45.221676 45.221676 45.221676
+43 68 39.051248 39.051248 39.051248
+43 69 25.000000 25.000000 25.000000
+43 70 36.878178 36.878178 36.878178
+43 71 22.825424 22.825424 22.825424
+43 72 26.925824 26.925824 26.925824
+43 73 17.000000 17.000000 17.000000
+43 74 56.648036 56.648036 56.648036
+43 75 69.462220 69.462220 69.462220
+43 76 90.138782 90.138782 90.138782
+43 77 68.183576 68.183576 68.183576
+43 78 83.384651 83.384651 83.384651
+43 79 52.773099 52.773099 52.773099
+43 80 50.447993 50.447993 50.447993
+43 81 33.955854 33.955854 33.955854
+43 82 22.803509 22.803509 22.803509
+43 83 46.400431 46.400431 46.400431
+43 84 52.201533 52.201533 52.201533
+43 85 51.039201 51.039201 51.039201
+43 86 57.558666 57.558666 57.558666
+43 87 65.513357 65.513357 65.513357
+43 88 70.604532 70.604532 70.604532
+43 89 38.013156 38.013156 38.013156
+43 90 75.953933 75.953933 75.953933
+43 91 37.589892 37.589892 37.589892
+43 92 38.470768 38.470768 38.470768
+43 93 37.054015 37.054015 37.054015
+43 94 28.635642 28.635642 28.635642
+43 95 32.062439 32.062439 32.062439
+43 96 43.011626 43.011626 43.011626
+43 97 26.000000 26.000000 26.000000
+43 98 80.280757 80.280757 80.280757
+43 99 40.311289 40.311289 40.311289
+43 100 53.535035 53.535035 53.535035
+43 101 27.294688 27.294688 27.294688
+44 1 38.078866 38.078866 38.078866
+44 2 30.000000 30.000000 30.000000
+44 3 34.481879 34.481879 34.481879
+44 4 33.000000 33.000000 33.000000
+44 5 35.355339 35.355339 35.355339
+44 6 35.000000 35.000000 35.000000
+44 7 38.327536 38.327536 38.327536
+44 8 41.231056 41.231056 41.231056
+44 9 40.311289 40.311289 40.311289
+44 10 67.268120 67.268120 67.268120
+44 11 63.639610 63.639610 63.639610
+44 12 65.069194 65.069194 65.069194
+44 13 61.717096 61.717096 61.717096
+44 14 70.710678 70.710678 70.710678
+44 15 64.031242 64.031242 64.031242
+44 16 69.526973 69.526973 69.526973
+44 17 71.063352 71.063352 71.063352
+44 18 68.007353 68.007353 68.007353
+44 19 80.752709 80.752709 80.752709
+44 20 76.118329 76.118329 76.118329
+44 21 71.196910 71.196910 71.196910
+44 22 81.394103 81.394103 81.394103
+44 23 71.589105 71.589105 71.589105
+44 24 81.786307 81.786307 81.786307
+44 25 72.034714 72.034714 72.034714
+44 26 82.462113 82.462113 82.462113
+44 27 68.007353 68.007353 68.007353
+44 28 64.031242 64.031242 64.031242
+44 29 66.287254 66.287254 66.287254
+44 30 61.032778 61.032778 61.032778
+44 31 64.140471 64.140471 64.140471
+44 32 59.908263 59.908263 59.908263
+44 33 63.631753 63.631753 63.631753
+44 34 67.082039 67.082039 67.082039
+44 35 58.309519 58.309519 58.309519
+44 36 12.000000 12.000000 12.000000
+44 37 10.000000 10.000000 10.000000
+44 38 10.440307 10.440307 10.440307
+44 39 8.602325 8.602325 8.602325
+44 40 7.071068 7.071068 7.071068
+44 41 5.000000 5.000000 5.000000
+44 42 10.440307 10.440307 10.440307
+44 43 5.000000 5.000000 5.000000
+44 45 3.000000 3.000000 3.000000
+44 46 35.128336 35.128336 35.128336
+44 47 37.336309 37.336309 37.336309
+44 48 66.400301 66.400301 66.400301
+44 49 81.049368 81.049368 81.049368
+44 50 74.148500 74.148500 74.148500
+44 51 52.810984 52.810984 52.810984
+44 52 65.000000 65.000000 65.000000
+44 53 62.649820 62.649820 62.649820
+44 54 49.497475 49.497475 49.497475
+44 55 25.000000 25.000000 25.000000
+44 56 35.355339 35.355339 35.355339
+44 57 50.249378 50.249378 50.249378
+44 58 65.000000 65.000000 65.000000
+44 59 85.000000 85.000000 85.000000
+44 60 79.056942 79.056942 79.056942
+44 61 47.169906 47.169906 47.169906
+44 62 22.360680 22.360680 22.360680
+44 63 50.990195 50.990195 50.990195
+44 64 65.764732 65.764732 65.764732
+44 65 55.901699 55.901699 55.901699
+44 66 49.244289 49.244289 49.244289
+44 67 50.000000 50.000000 50.000000
+44 68 43.931765 43.931765 43.931765
+44 69 29.154759 29.154759 29.154759
+44 70 40.804412 40.804412 40.804412
+44 71 25.612497 25.612497 25.612497
+44 72 31.622777 31.622777 31.622777
+44 73 21.540659 21.540659 21.540659
+44 74 58.600341 58.600341 58.600341
+44 75 73.824115 73.824115 73.824115
+44 76 94.339811 94.339811 94.339811
+44 77 73.171033 73.171033 73.171033
+44 78 88.022724 88.022724 88.022724
+44 79 55.226805 55.226805 55.226805
+44 80 51.865210 51.865210 51.865210
+44 81 38.832976 38.832976 38.832976
+44 82 27.658633 27.658633 27.658633
+44 83 50.477718 50.477718 50.477718
+44 84 56.920998 56.920998 56.920998
+44 85 56.035703 56.035703 56.035703
+44 86 62.513998 62.513998 62.513998
+44 87 69.835521 69.835521 69.835521
+44 88 74.632433 74.632433 74.632433
+44 89 41.109610 41.109610 41.109610
+44 90 80.894994 80.894994 80.894994
+44 91 42.047592 42.047592 42.047592
+44 92 43.416587 43.416587 43.416587
+44 93 42.047592 42.047592 42.047592
+44 94 33.541020 33.541020 33.541020
+44 95 37.054015 37.054015 37.054015
+44 96 48.010416 48.010416 48.010416
+44 97 31.000000 31.000000 31.000000
+44 98 84.202138 84.202138 84.202138
+44 99 43.931765 43.931765 43.931765
+44 100 57.801384 57.801384 57.801384
+44 101 30.000000 30.000000 30.000000
+45 1 35.341194 35.341194 35.341194
+45 2 30.149627 30.149627 30.149627
+45 3 33.734256 33.734256 33.734256
+45 4 33.136083 33.136083 33.136083
+45 5 35.057096 35.057096 35.057096
+45 6 35.128336 35.128336 35.128336
+45 7 37.656341 37.656341 37.656341
+45 8 40.607881 40.607881 40.607881
+45 9 40.049969 40.049969 40.049969
+45 10 65.069194 65.069194 65.069194
+45 11 61.554854 61.554854 61.554854
+45 12 63.031738 63.031738 63.031738
+45 13 59.816386 59.816386 59.816386
+45 14 68.622154 68.622154 68.622154
+45 15 62.201286 62.201286 62.201286
+45 16 67.623960 67.623960 67.623960
+45 17 69.202601 69.202601 69.202601
+45 18 66.287254 66.287254 66.287254
+45 19 77.781746 77.781746 77.781746
+45 20 73.164199 73.164199 73.164199
+45 21 68.249542 68.249542 68.249542
+45 22 78.447435 78.447435 78.447435
+45 23 68.658576 68.658576 68.658576
+45 24 78.854296 78.854296 78.854296
+45 25 69.123079 69.123079 69.123079
+45 26 79.555012 79.555012 79.555012
+45 27 65.604878 65.604878 65.604878
+45 28 61.717096 61.717096 61.717096
+45 29 63.820060 63.820060 63.820060
+45 30 58.600341 58.600341 58.600341
+45 31 61.587336 61.587336 61.587336
+45 32 57.428216 57.428216 57.428216
+45 33 61.057350 61.057350 61.057350
+45 34 64.412732 64.412732 64.412732
+45 35 55.758407 55.758407 55.758407
+45 36 12.369317 12.369317 12.369317
+45 37 10.440307 10.440307 10.440307
+45 38 10.000000 10.000000 10.000000
+45 39 7.280110 7.280110 7.280110
+45 40 5.385165 5.385165 5.385165
+45 41 5.830952 5.830952 5.830952
+45 42 7.615773 7.615773 7.615773
+45 43 2.000000 2.000000 2.000000
+45 44 3.000000 3.000000 3.000000
+45 46 35.000000 35.000000 35.000000
+45 47 37.054015 37.054015 37.054015
+45 48 64.637450 64.637450 64.637450
+45 49 78.089692 78.089692 78.089692
+45 50 71.196910 71.196910 71.196910
+45 51 49.979996 49.979996 49.979996
+45 52 62.000000 62.000000 62.000000
+45 53 60.033324 60.033324 60.033324
+45 54 47.423623 47.423623 47.423623
+45 55 22.000000 22.000000 22.000000
+45 56 33.301652 33.301652 33.301652
+45 57 47.265209 47.265209 47.265209
+45 58 62.241465 62.241465 62.241465
+45 59 82.365041 82.365041 82.365041
+45 60 76.609399 76.609399 76.609399
+45 61 45.650849 45.650849 45.650849
+45 62 19.723083 19.723083 19.723083
+45 63 48.052055 48.052055 48.052055
+45 64 62.801274 62.801274 62.801274
+45 65 52.952809 52.952809 52.952809
+45 66 46.518813 46.518813 46.518813
+45 67 47.127487 47.127487 47.127487
+45 68 41.000000 41.000000 41.000000
+45 69 26.627054 26.627054 26.627054
+45 70 38.418745 38.418745 38.418745
+45 71 23.853721 23.853721 23.853721
+45 72 28.792360 28.792360 28.792360
+45 73 18.788294 18.788294 18.788294
+45 74 57.384667 57.384667 57.384667
+45 75 71.196910 71.196910 71.196910
+45 76 91.809586 91.809586 91.809586
+45 77 70.178344 70.178344 70.178344
+45 78 85.234969 85.234969 85.234969
+45 79 53.712196 53.712196 53.712196
+45 80 50.960769 50.960769 50.960769
+45 81 35.902646 35.902646 35.902646
+45 82 24.738634 24.738634 24.738634
+45 83 48.010416 48.010416 48.010416
+45 84 54.083269 54.083269 54.083269
+45 85 53.037722 53.037722 53.037722
+45 86 59.539903 59.539903 59.539903
+45 87 67.230945 67.230945 67.230945
+45 88 72.201108 72.201108 72.201108
+45 89 39.204592 39.204592 39.204592
+45 90 77.929455 77.929455 77.929455
+45 91 39.357337 39.357337 39.357337
+45 92 40.447497 40.447497 40.447497
+45 93 39.051248 39.051248 39.051248
+45 94 30.594117 30.594117 30.594117
+45 95 34.058773 34.058773 34.058773
+45 96 45.011110 45.011110 45.011110
+45 97 28.000000 28.000000 28.000000
+45 98 81.835200 81.835200 81.835200
+45 99 41.725292 41.725292 41.725292
+45 100 55.226805 55.226805 55.226805
+45 101 28.301943 28.301943 28.301943
+46 1 37.735925 37.735925 37.735925
+46 2 5.830952 5.830952 5.830952
+46 3 7.280110 7.280110 7.280110
+46 4 3.605551 3.605551 3.605551
+46 5 2.000000 2.000000 2.000000
+46 6 3.000000 3.000000 3.000000
+46 7 7.280110 7.280110 7.280110
+46 8 8.602325 8.602325 8.602325
+46 9 5.385165 5.385165 5.385165
+46 10 48.052055 48.052055 48.052055
+46 11 43.174066 43.174066 43.174066
+46 12 43.680659 43.680659 43.680659
+46 13 38.897301 38.897301 38.897301
+46 14 49.335586 49.335586 49.335586
+46 15 39.924930 39.924930 39.924930
+46 16 45.694639 45.694639 45.694639
+46 17 46.518813 46.518813 46.518813
+46 18 42.059482 42.059482 42.059482
+46 19 80.653580 80.653580 80.653580
+46 20 75.286121 75.286121 75.286121
+46 21 70.519501 70.519501 70.519501
+46 22 79.555012 79.555012 79.555012
+46 23 69.921384 69.921384 69.921384
+46 24 79.075913 79.075913 79.075913
+46 25 69.375788 69.375788 69.375788
+46 26 78.447435 78.447435 78.447435
+46 27 91.263355 91.263355 91.263355
+46 28 88.509886 88.509886 88.509886
+46 29 88.814413 88.814413 88.814413
+46 30 84.314886 84.314886 84.314886
+46 31 85.603738 85.603738 85.603738
+46 32 82.661962 82.661962 82.661962
+46 33 84.811556 84.811556 84.811556
+46 34 86.452299 86.452299 86.452299
+46 35 80.212219 80.212219 80.212219
+46 36 47.095647 47.095647 47.095647
+46 37 45.099889 45.099889 45.099889
+46 38 45.000000 45.000000 45.000000
+46 39 42.047592 42.047592 42.047592
+46 40 40.049969 40.049969 40.049969
+46 41 40.112342 40.112342 40.112342
+46 42 38.639358 38.639358 38.639358
+46 43 35.057096 35.057096 35.057096
+46 44 35.128336 35.128336 35.128336
+46 45 35.000000 35.000000 35.000000
+46 47 2.828427 2.828427 2.828427
+46 48 41.146081 41.146081 41.146081
+46 49 80.081209 80.081209 80.081209
+46 50 73.375745 73.375745 73.375745
+46 51 70.092796 70.092796 70.092796
+46 52 71.196910 71.196910 71.196910
+46 53 52.239832 52.239832 52.239832
+46 54 32.000000 32.000000 32.000000
+46 55 41.340053 41.340053 41.340053
+46 56 24.166092 24.166092 24.166092
+46 57 55.758407 55.758407 55.758407
+46 58 57.870545 57.870545 57.870545
+46 59 72.173402 72.173402 72.173402
+46 60 62.801274 62.801274 62.801274
+46 61 22.561028 22.561028 22.561028
+46 62 30.232433 30.232433 30.232433
+46 63 65.069194 65.069194 65.069194
+46 64 76.609399 76.609399 76.609399
+46 65 57.697487 57.697487 57.697487
+46 66 44.598206 44.598206 44.598206
+46 67 49.658836 49.658836 49.658836
+46 68 59.464275 59.464275 59.464275
+46 69 29.732137 29.732137 29.732137
+46 70 31.953091 31.953091 31.953091
+46 71 19.849433 19.849433 19.849433
+46 72 52.478567 52.478567 52.478567
+46 73 46.238512 46.238512 46.238512
+46 74 28.425341 28.425341 28.425341
+46 75 62.000000 62.000000 62.000000
+46 76 78.447435 78.447435 78.447435
+46 77 80.622577 80.622577 80.622577
+46 78 79.056942 79.056942 79.056942
+46 79 28.635642 28.635642 28.635642
+46 80 19.798990 19.798990 19.798990
+46 81 44.204072 44.204072 44.204072
+46 82 37.643060 37.643060 37.643060
+46 83 39.623226 39.623226 39.623226
+46 84 53.758720 53.758720 53.758720
+46 85 64.637450 64.637450 64.637450
+46 86 73.006849 73.006849 73.006849
+46 87 58.008620 58.008620 58.008620
+46 88 58.549125 58.549125 58.549125
+46 89 24.331050 24.331050 24.331050
+46 90 90.210864 90.210864 90.210864
+46 91 38.910153 38.910153 38.910153
+46 92 49.406477 49.406477 49.406477
+46 93 51.088159 51.088159 51.088159
+46 94 50.803543 50.803543 50.803543
+46 95 50.249378 50.249378 50.249378
+46 96 57.628118 57.628118 57.628118
+46 97 44.821870 44.821870 44.821870
+46 98 65.969690 65.969690 65.969690
+46 99 30.594117 30.594117 30.594117
+46 100 47.381431 47.381431 47.381431
+46 101 18.601075 18.601075 18.601075
+47 1 37.202150 37.202150 37.202150
+47 2 8.602325 8.602325 8.602325
+47 3 6.403124 6.403124 6.403124
+47 4 6.403124 6.403124 6.403124
+47 5 2.000000 2.000000 2.000000
+47 6 5.385165 5.385165 5.385165
+47 7 5.000000 5.000000 5.000000
+47 8 5.830952 5.830952 5.830952
+47 9 3.000000 3.000000 3.000000
+47 10 45.705580 45.705580 45.705580
+47 11 40.792156 40.792156 40.792156
+47 12 41.231056 41.231056 41.231056
+47 13 36.400549 36.400549 36.400549
+47 14 46.840154 46.840154 46.840154
+47 15 37.336309 37.336309 37.336309
+47 16 43.081318 43.081318 43.081318
+47 17 43.863424 43.863424 43.863424
+47 18 39.357337 39.357337 39.357337
+47 19 79.378838 79.378838 79.378838
+47 20 74.000000 74.000000 74.000000
+47 21 69.289249 69.289249 69.289249
+47 22 78.160092 78.160092 78.160092
+47 23 68.622154 68.622154 68.622154
+47 24 77.620873 77.620873 77.620873
+47 25 68.007353 68.007353 68.007353
+47 26 76.902536 76.902536 76.902536
+47 27 91.809586 91.809586 91.809586
+47 28 89.185201 89.185201 89.185201
+47 29 89.308454 89.308454 89.308454
+47 30 84.905830 84.905830 84.905830
+47 31 86.023253 86.023253 86.023253
+47 32 83.216585 83.216585 83.216585
+47 33 85.211502 85.211502 85.211502
+47 34 86.683332 86.683332 86.683332
+47 35 80.709355 80.709355 80.709355
+47 36 49.254441 49.254441 49.254441
+47 37 47.265209 47.265209 47.265209
+47 38 47.042534 47.042534 47.042534
+47 39 44.000000 44.000000 44.000000
+47 40 42.000000 42.000000 42.000000
+47 41 42.296572 42.296572 42.296572
+47 42 40.311289 40.311289 40.311289
+47 43 37.000000 37.000000 37.000000
+47 44 37.336309 37.336309 37.336309
+47 45 37.054015 37.054015 37.054015
+47 46 2.828427 2.828427 2.828427
+47 48 38.483763 38.483763 38.483763
+47 49 78.746428 78.746428 78.746428
+47 50 72.111026 72.111026 72.111026
+47 51 70.292247 70.292247 70.292247
+47 52 70.491134 70.491134 70.491134
+47 53 50.487622 50.487622 50.487622
+47 54 30.066593 30.066593 30.066593
+47 55 42.059482 42.059482 42.059482
+47 56 23.323808 23.323808 23.323808
+47 57 55.217751 55.217751 55.217751
+47 58 56.293872 56.293872 56.293872
+47 59 70.064256 70.064256 70.064256
+47 60 60.530984 60.530984 60.530984
+47 61 20.223748 20.223748 20.223748
+47 62 30.886890 30.886890 30.886890
+47 63 65.069194 65.069194 65.069194
+47 64 76.216796 76.216796 76.216796
+47 65 56.824291 56.824291 56.824291
+47 66 43.462628 43.462628 43.462628
+47 67 48.764741 48.764741 48.764741
+47 68 59.665736 59.665736 59.665736
+47 69 29.732137 29.732137 29.732137
+47 70 30.870698 30.870698 30.870698
+47 71 20.248457 20.248457 20.248457
+47 72 53.235327 53.235327 53.235327
+47 73 47.434165 47.434165 47.434165
+47 74 25.612497 25.612497 25.612497
+47 75 60.033324 60.033324 60.033324
+47 76 76.118329 76.118329 76.118329
+47 77 79.924965 79.924965 79.924965
+47 78 77.162167 77.162167 77.162167
+47 79 26.000000 26.000000 26.000000
+47 80 16.970563 16.970563 16.970563
+47 81 43.931765 43.931765 43.931765
+47 82 38.013156 38.013156 38.013156
+47 83 38.078866 38.078866 38.078866
+47 84 52.554733 52.554733 52.554733
+47 85 64.202804 64.202804 64.202804
+47 86 72.622311 72.622311 72.622311
+47 87 56.080300 56.080300 56.080300
+47 88 56.320511 56.320511 56.320511
+47 89 22.803509 22.803509 22.803509
+47 90 89.587946 89.587946 89.587946
+47 91 38.078866 38.078866 38.078866
+47 92 49.040799 49.040799 49.040799
+47 93 50.931326 50.931326 50.931326
+47 94 51.312766 51.312766 51.312766
+47 95 50.447993 50.447993 50.447993
+47 96 57.384667 57.384667 57.384667
+47 97 45.221676 45.221676 45.221676
+47 98 63.560994 63.560994 63.560994
+47 99 29.120440 29.120440 29.120440
+47 100 45.705580 45.705580 45.705580
+47 101 18.384776 18.384776 18.384776
+48 1 38.327536 38.327536 38.327536
+48 2 46.141088 46.141088 46.141088
+48 3 36.055513 36.055513 36.055513
+48 4 44.721360 44.721360 44.721360
+48 5 39.357337 39.357337 39.357337
+48 6 43.863424 43.863424 43.863424
+48 7 34.000000 34.000000 34.000000
+48 8 32.695565 32.695565 32.695565
+48 9 37.336309 37.336309 37.336309
+48 10 12.806248 12.806248 12.806248
+48 11 9.433981 9.433981 9.433981
+48 12 7.810250 7.810250 7.810250
+48 13 6.000000 6.000000 6.000000
+48 14 10.440307 10.440307 10.440307
+48 15 3.000000 3.000000 3.000000
+48 16 5.000000 5.000000 5.000000
+48 17 5.385165 5.385165 5.385165
+48 18 2.000000 2.000000 2.000000
+48 19 58.000000 58.000000 58.000000
+48 20 53.150729 53.150729 53.150729
+48 21 50.000000 50.000000 50.000000
+48 22 55.172457 55.172457 55.172457
+48 23 48.414874 48.414874 48.414874
+48 24 53.814496 53.814496 53.814496
+48 25 46.861498 46.861498 46.861498
+48 26 51.855569 51.855569 51.855569
+48 27 94.201911 94.201911 94.201911
+48 28 93.536089 93.536089 93.536089
+48 29 91.241438 91.241438 91.241438
+48 30 88.566359 88.566359 88.566359
+48 31 87.298339 87.298339 87.298339
+48 32 86.579443 86.579443 86.579443
+48 33 86.313383 86.313383 86.313383
+48 34 85.375641 85.375641 85.375641
+48 35 83.600239 83.600239 83.600239
+48 36 76.321688 76.321688 76.321688
+48 37 74.625733 74.625733 74.625733
+48 38 73.061618 73.061618 73.061618
+48 39 69.462220 69.462220 69.462220
+48 40 67.742158 67.742158 67.742158
+48 41 70.455660 70.455660 70.455660
+48 42 63.529521 63.529521 63.529521
+48 43 63.513778 63.513778 63.513778
+48 44 66.400301 66.400301 66.400301
+48 45 64.637450 64.637450 64.637450
+48 46 41.146081 41.146081 41.146081
+48 47 38.483763 38.483763 38.483763
+48 49 56.568542 56.568542 56.568542
+48 50 51.855569 51.855569 51.855569
+48 51 70.710678 70.710678 70.710678
+48 52 58.600341 58.600341 58.600341
+48 53 27.459060 27.459060 27.459060
+48 54 18.681542 18.681542 18.681542
+48 55 55.081757 55.081757 55.081757
+48 56 31.764760 31.764760 31.764760
+48 57 49.030603 49.030603 49.030603
+48 58 34.409301 34.409301 34.409301
+48 59 37.336309 37.336309 37.336309
+48 60 26.248809 26.248809 26.248809
+48 61 19.849433 19.849433 19.849433
+48 62 47.423623 47.423623 47.423623
+48 63 63.788714 63.788714 63.788714
+48 64 67.779053 67.779053 67.779053
+48 65 45.541190 45.541190 45.541190
+48 66 33.376639 33.376639 33.376639
+48 67 39.812058 39.812058 39.812058
+48 68 62.072538 62.072538 62.072538
+48 69 40.853396 40.853396 40.853396
+48 70 29.832868 29.832868 29.832868
+48 71 40.804412 40.804412 40.804412
+48 72 63.788714 63.788714 63.788714
+48 73 64.195015 64.195015 64.195015
+48 74 15.000000 15.000000 15.000000
+48 75 30.805844 30.805844 30.805844
+48 76 40.112342 40.112342 40.112342
+48 77 66.730802 66.730802 66.730802
+48 78 46.957428 46.957428 46.957428
+48 79 12.529964 12.529964 12.529964
+48 80 23.345235 23.345235 23.345235
+48 81 45.044423 45.044423 45.044423
+48 82 48.764741 48.764741 48.764741
+48 83 25.079872 25.079872 25.079872
+48 84 37.696154 37.696154 37.696154
+48 85 57.280014 57.280014 57.280014
+48 86 64.845971 64.845971 64.845971
+48 87 28.319605 28.319605 28.319605
+48 88 23.259407 23.259407 23.259407
+48 89 25.553865 25.553865 25.553865
+48 90 76.321688 76.321688 76.321688
+48 91 35.057096 35.057096 35.057096
+48 92 47.095647 47.095647 47.095647
+48 93 51.039201 51.039201 51.039201
+48 94 59.413803 59.413803 59.413803
+48 95 55.081757 55.081757 55.081757
+48 96 54.589376 54.589376 54.589376
+48 97 53.758720 53.758720 53.758720
+48 98 27.073973 27.073973 27.073973
+48 99 25.000000 25.000000 25.000000
+48 100 26.000000 26.000000 26.000000
+48 101 36.400549 36.400549 36.400549
+49 1 45.044423 45.044423 45.044423
+49 2 81.786307 81.786307 81.786307
+49 3 72.801099 72.801099 72.801099
+49 4 82.462113 82.462113 82.462113
+49 5 78.160092 78.160092 78.160092
+49 6 82.969874 82.969874 82.969874
+49 7 74.000000 74.000000 74.000000
+49 8 75.026662 75.026662 75.026662
+49 9 79.711982 79.711982 79.711982
+49 10 43.863424 43.863424 43.863424
+49 11 47.423623 47.423623 47.423623
+49 12 48.795492 48.795492 48.795492
+49 13 52.497619 52.497619 52.497619
+49 14 47.634021 47.634021 47.634021
+49 15 54.488531 54.488531 54.488531
+49 16 53.150729 53.150729 53.150729
+49 17 54.671748 54.671748 54.671748
+49 18 58.000000 58.000000 58.000000
+49 19 2.000000 2.000000 2.000000
+49 20 5.000000 5.000000 5.000000
+49 21 10.000000 10.000000 10.000000
+49 22 2.000000 2.000000 2.000000
+49 23 10.198039 10.198039 10.198039
+49 24 4.000000 4.000000 4.000000
+49 25 10.770330 10.770330 10.770330
+49 26 7.000000 7.000000 7.000000
+49 27 58.600341 58.600341 58.600341
+49 28 60.901560 60.901560 60.901560
+49 29 55.901699 55.901699 55.901699
+49 30 56.603887 56.603887 56.603887
+49 31 52.354560 52.354560 52.354560
+49 32 54.918121 54.918121 54.918121
+49 33 51.478151 51.478151 51.478151
+49 34 47.423623 47.423623 47.423623
+49 35 52.430907 52.430907 52.430907
+49 36 83.815273 83.815273 83.815273
+49 37 83.240615 83.240615 83.240615
+49 38 80.361682 80.361682 80.361682
+49 39 77.620873 77.620873 77.620873
+49 40 77.129761 77.129761 77.129761
+49 41 82.000000 82.000000 82.000000
+49 42 71.805292 71.805292 71.805292
+49 43 76.118329 76.118329 76.118329
+49 44 81.049368 81.049368 81.049368
+49 45 78.089692 78.089692 78.089692
+49 46 80.081209 80.081209 80.081209
+49 47 78.746428 78.746428 78.746428
+49 48 56.568542 56.568542 56.568542
+49 50 7.000000 7.000000 7.000000
+49 51 42.426407 42.426407 42.426407
+49 52 19.849433 19.849433 19.849433
+49 53 30.232433 30.232433 30.232433
+49 54 50.089919 50.089919 50.089919
+49 55 56.515485 56.515485 56.515485
+49 56 56.293872 56.293872 56.293872
+49 57 31.048349 31.048349 31.048349
+49 58 23.323808 23.323808 23.323808
+49 59 27.459060 27.459060 27.459060
+49 60 35.341194 35.341194 35.341194
+49 61 61.269895 61.269895 61.269895
+49 62 60.074953 60.074953 60.074953
+49 63 37.802116 37.802116 37.802116
+49 64 27.459060 27.459060 27.459060
+49 65 25.179357 25.179357 25.179357
+49 66 35.693137 35.693137 35.693137
+49 67 32.015621 32.015621 32.015621
+49 68 43.046487 43.046487 43.046487
+49 69 55.036352 55.036352 55.036352
+49 70 48.270074 48.270074 48.270074
+49 71 64.381674 64.381674 64.381674
+49 72 55.036352 55.036352 55.036352
+49 73 63.568860 63.568860 63.568860
+49 74 68.007353 68.007353 68.007353
+49 75 26.627054 26.627054 26.627054
+49 76 37.000000 37.000000 37.000000
+49 77 19.313208 19.313208 19.313208
+49 78 19.104973 19.104973 19.104973
+49 79 61.294372 61.294372 61.294372
+49 80 72.560320 72.560320 72.560320
+49 81 42.296572 42.296572 42.296572
+49 82 53.460266 53.460266 53.460266
+49 83 40.853396 40.853396 40.853396
+49 84 26.476405 26.476405 26.476405
+49 85 28.301943 28.301943 28.301943
+49 86 27.658633 27.658633 27.658633
+49 87 28.319605 28.319605 28.319605
+49 88 35.510562 35.510562 35.510562
+49 89 55.973208 55.973208 55.973208
+49 90 25.000000 25.000000 25.000000
+49 91 42.296572 42.296572 42.296572
+49 92 37.656341 37.656341 37.656341
+49 93 39.560081 39.560081 39.560081
+49 94 50.695167 50.695167 50.695167
+49 95 45.541190 45.541190 45.541190
+49 96 34.928498 34.928498 34.928498
+49 97 50.695167 50.695167 50.695167
+49 98 40.162171 40.162171 40.162171
+49 99 49.648766 49.648766 49.648766
+49 100 34.000000 34.000000 34.000000
+49 101 62.968246 62.968246 62.968246
+50 1 38.052595 38.052595 38.052595
+50 2 74.953319 74.953319 74.953319
+50 3 66.098411 66.098411 66.098411
+50 4 75.690158 75.690158 75.690158
+50 5 71.470274 71.470274 71.470274
+50 6 76.243032 76.243032 76.243032
+50 7 67.416615 67.416615 67.416615
+50 8 68.541958 68.541958 68.541958
+50 9 73.164199 73.164199 73.164199
+50 10 39.408121 39.408121 39.408121
+50 11 42.520583 42.520583 42.520583
+50 12 44.045431 44.045431 44.045431
+50 13 47.381431 47.381431 47.381431
+50 14 43.566042 43.566042 43.566042
+50 15 49.578221 49.578221 49.578221
+50 16 48.826222 48.826222 48.826222
+50 17 50.477718 50.477718 50.477718
+50 18 53.413481 53.413481 53.413481
+50 19 7.280110 7.280110 7.280110
+50 20 2.000000 2.000000 2.000000
+50 21 3.000000 3.000000 3.000000
+50 22 7.280110 7.280110 7.280110
+50 23 3.605551 3.605551 3.605551
+50 24 8.062258 8.062258 8.062258
+50 25 5.000000 5.000000 5.000000
+50 26 9.899495 9.899495 9.899495
+50 27 55.973208 55.973208 55.973208
+50 28 57.775427 57.775427 57.775427
+50 29 53.141321 53.141321 53.141321
+50 30 53.225934 53.225934 53.225934
+50 31 49.396356 49.396356 49.396356
+50 32 51.429563 51.429563 51.429563
+50 33 48.466483 48.466483 48.466483
+50 34 44.922155 44.922155 44.922155
+50 35 48.764741 48.764741 48.764741
+50 36 77.162167 77.162167 77.162167
+50 37 76.537572 76.537572 76.537572
+50 38 73.681748 73.681748 73.681748
+50 39 70.880181 70.880181 70.880181
+50 40 70.342022 70.342022 70.342022
+50 41 75.186435 75.186435 75.186435
+50 42 65.000000 65.000000 65.000000
+50 43 69.231496 69.231496 69.231496
+50 44 74.148500 74.148500 74.148500
+50 45 71.196910 71.196910 71.196910
+50 46 73.375745 73.375745 73.375745
+50 47 72.111026 72.111026 72.111026
+50 48 51.855569 51.855569 51.855569
+50 49 7.000000 7.000000 7.000000
+50 51 37.802116 37.802116 37.802116
+50 52 15.264338 15.264338 15.264338
+50 53 24.758837 24.758837 24.758837
+50 54 43.908997 43.908997 43.908997
+50 55 49.729267 49.729267 49.729267
+50 56 49.477268 49.477268 49.477268
+50 57 24.351591 24.351591 24.351591
+50 58 17.691806 17.691806 17.691806
+50 59 27.073973 27.073973 27.073973
+50 60 32.984845 32.984845 32.984845
+50 61 55.072679 55.072679 55.072679
+50 62 53.084838 53.084838 53.084838
+50 63 32.526912 32.526912 32.526912
+50 64 24.351591 24.351591 24.351591
+50 65 18.248288 18.248288 18.248288
+50 66 28.861739 28.861739 28.861739
+50 67 25.019992 25.019992 25.019992
+50 68 37.202150 37.202150 37.202150
+50 69 48.041649 48.041649 48.041649
+50 70 41.484937 41.484937 41.484937
+50 71 57.428216 57.428216 57.428216
+50 72 48.764741 48.764741 48.764741
+50 73 57.008771 57.008771 57.008771
+50 74 62.481997 62.481997 62.481997
+50 75 23.409400 23.409400 23.409400
+50 76 37.656341 37.656341 37.656341
+50 77 18.000000 18.000000 18.000000
+50 78 21.023796 21.023796 21.023796
+50 79 55.605755 55.605755 55.605755
+50 80 66.573268 66.573268 66.573268
+50 81 35.355339 35.355339 35.355339
+50 82 46.529560 46.529560 46.529560
+50 83 34.438351 34.438351 34.438351
+50 84 19.646883 19.646883 19.646883
+50 85 22.671568 22.671568 22.671568
+50 86 23.706539 23.706539 23.706539
+50 87 24.186773 24.186773 24.186773
+50 88 32.310989 32.310989 32.310989
+50 89 49.396356 49.396356 49.396356
+50 90 25.961510 25.961510 25.961510
+50 91 35.355339 35.355339 35.355339
+50 92 30.805844 30.805844 30.805844
+50 93 32.893768 32.893768 32.893768
+50 94 44.283180 44.283180 44.283180
+50 95 39.000000 39.000000 39.000000
+50 96 28.653098 28.653098 28.653098
+50 97 43.965896 43.965896 43.965896
+50 98 38.470768 38.470768 38.470768
+50 99 43.081318 43.081318 43.081318
+50 100 28.017851 28.017851 28.017851
+50 101 56.089215 56.089215 56.089215
+51 1 35.341194 35.341194 35.341194
+51 2 68.622154 68.622154 68.622154
+51 3 64.031242 64.031242 64.031242
+51 4 70.710678 70.710678 70.710678
+51 5 68.767725 68.767725 68.767725
+51 6 72.138755 72.138755 72.138755
+51 7 67.201190 67.201190 67.201190
+51 8 69.634761 69.634761 69.634761
+51 9 72.622311 72.622311 72.622311
+51 10 62.000000 62.000000 62.000000
+51 11 62.201286 62.201286 62.201286
+51 12 64.195015 64.195015 64.195015
+51 13 64.776539 64.776539 64.776539
+51 14 67.000000 67.000000 67.000000
+51 15 67.742158 67.742158 67.742158
+51 16 70.178344 70.178344 70.178344
+51 17 72.173402 72.173402 72.173402
+51 18 72.691127 72.691127 72.691127
+51 19 41.036569 41.036569 41.036569
+51 20 39.051248 39.051248 39.051248
+51 21 36.055513 36.055513 36.055513
+51 22 43.863424 43.863424 43.863424
+51 23 37.735925 37.735925 37.735925
+51 24 45.343136 45.343136 45.343136
+51 25 39.446166 39.446166 39.446166
+51 26 47.634021 47.634021 47.634021
+51 27 23.537205 23.537205 23.537205
+51 28 23.000000 23.000000 23.000000
+51 29 20.615528 20.615528 20.615528
+51 30 18.000000 18.000000 18.000000
+51 31 16.763055 16.763055 16.763055
+51 32 16.000000 16.000000 16.000000
+51 33 15.811388 15.811388 15.811388
+51 34 16.401219 16.401219 16.401219
+51 35 13.000000 13.000000 13.000000
+51 36 50.249378 50.249378 50.249378
+51 37 50.487622 50.487622 50.487622
+51 38 47.518417 47.518417 47.518417
+51 39 46.097722 46.097722 46.097722
+51 40 46.572524 46.572524 46.572524
+51 41 51.419841 51.419841 51.419841
+51 42 42.379240 42.379240 42.379240
+51 43 48.104054 48.104054 48.104054
+51 44 52.810984 52.810984 52.810984
+51 45 49.979996 49.979996 49.979996
+51 46 70.092796 70.092796 70.092796
+51 47 70.292247 70.292247 70.292247
+51 48 70.710678 70.710678 70.710678
+51 49 42.426407 42.426407 42.426407
+51 50 37.802116 37.802116 37.802116
+51 52 22.671568 22.671568 22.671568
+51 53 47.265209 47.265209 47.265209
+51 54 54.120237 54.120237 54.120237
+51 55 30.232433 30.232433 30.232433
+51 56 48.877398 48.877398 48.877398
+51 57 22.000000 22.000000 22.000000
+51 58 43.174066 43.174066 43.174066
+51 59 62.241465 62.241465 62.241465
+51 60 63.788714 63.788714 63.788714
+51 61 62.241465 62.241465 62.241465
+51 62 40.360872 40.360872 40.360872
+51 63 7.000000 7.000000 7.000000
+51 64 16.552945 16.552945 16.552945
+51 65 27.459060 27.459060 27.459060
+51 66 37.336309 37.336309 37.336309
+51 67 31.064449 31.064449 31.064449
+51 68 10.630146 10.630146 10.630146
+51 69 40.607881 40.607881 40.607881
+51 70 44.384682 44.384682 44.384682
+51 71 50.249378 50.249378 50.249378
+51 72 21.189620 21.189620 21.189620
+51 73 31.320920 31.320920 31.320920
+51 74 74.330344 74.330344 74.330344
+51 75 54.120237 54.120237 54.120237
+51 76 73.409809 73.409809 73.409809
+51 77 25.942244 25.942244 25.942244
+51 78 58.523500 58.523500 58.523500
+51 79 67.357256 67.357256 67.357256
+51 80 73.790243 73.790243 73.790243
+51 81 27.730849 27.730849 27.730849
+51 82 32.526912 32.526912 32.526912
+51 83 45.705580 45.705580 45.705580
+51 84 35.227830 35.227830 35.227830
+51 85 16.155494 16.155494 16.155494
+51 86 15.000000 15.000000 15.000000
+51 87 52.172790 52.172790 52.172790
+51 88 61.000000 61.000000 61.000000
+51 89 53.225934 53.225934 53.225934
+51 90 30.413813 30.413813 30.413813
+51 91 37.000000 37.000000 37.000000
+51 92 24.041631 24.041631 24.041631
+51 93 20.615528 20.615528 20.615528
+51 94 20.248457 20.248457 20.248457
+51 95 19.849433 19.849433 19.849433
+51 96 16.124515 16.124515 16.124515
+51 97 25.495098 25.495098 25.495098
+51 98 70.092796 70.092796 70.092796
+51 99 49.040799 49.040799 49.040799
+51 100 46.000000 46.000000 46.000000
+51 101 52.009614 52.009614 52.009614
+52 1 33.541020 33.541020 33.541020
+52 2 71.589105 71.589105 71.589105
+52 3 64.140471 64.140471 64.140471
+52 4 72.897188 72.897188 72.897188
+52 5 69.462220 69.462220 69.462220
+52 6 73.824115 73.824115 73.824115
+52 7 66.287254 66.287254 66.287254
+52 8 68.007353 68.007353 68.007353
+52 9 72.111026 72.111026 72.111026
+52 10 47.434165 47.434165 47.434165
+52 11 49.244289 49.244289 49.244289
+52 12 51.078371 51.078371 51.078371
+52 13 53.235327 53.235327 53.235327
+52 14 52.201533 52.201533 52.201533
+52 15 55.901699 55.901699 55.901699
+52 16 56.648036 56.648036 56.648036
+52 17 58.523500 58.523500 58.523500
+52 18 60.415230 60.415230 60.415230
+52 19 18.601075 18.601075 18.601075
+52 20 16.401219 16.401219 16.401219
+52 21 13.928388 13.928388 13.928388
+52 22 21.213203 21.213203 21.213203
+52 23 15.811388 15.811388 15.811388
+52 24 22.671568 22.671568 22.671568
+52 25 17.720045 17.720045 17.720045
+52 26 25.000000 25.000000 25.000000
+52 27 41.231056 41.231056 41.231056
+52 28 42.720019 42.720019 42.720019
+52 29 38.327536 38.327536 38.327536
+52 30 38.078866 38.078866 38.078866
+52 31 34.481879 34.481879 34.481879
+52 32 36.249138 36.249138 36.249138
+52 33 33.526109 33.526109 33.526109
+52 34 30.413813 30.413813 30.413813
+52 35 33.541020 33.541020 33.541020
+52 36 66.098411 66.098411 66.098411
+52 37 65.764732 65.764732 65.764732
+52 38 62.801274 62.801274 62.801274
+52 39 60.406953 60.406953 60.406953
+52 40 60.207973 60.207973 60.207973
+52 41 65.192024 65.192024 65.192024
+52 42 55.081757 55.081757 55.081757
+52 43 60.000000 60.000000 60.000000
+52 44 65.000000 65.000000 65.000000
+52 45 62.000000 62.000000 62.000000
+52 46 71.196910 71.196910 71.196910
+52 47 70.491134 70.491134 70.491134
+52 48 58.600341 58.600341 58.600341
+52 49 19.849433 19.849433 19.849433
+52 50 15.264338 15.264338 15.264338
+52 51 22.671568 22.671568 22.671568
+52 53 31.622777 31.622777 31.622777
+52 54 46.097722 46.097722 46.097722
+52 55 40.000000 40.000000 40.000000
+52 56 47.169906 47.169906 47.169906
+52 57 15.811388 15.811388 15.811388
+52 58 25.495098 25.495098 25.495098
+52 59 41.231056 41.231056 41.231056
+52 60 45.000000 45.000000 45.000000
+52 61 56.568542 56.568542 56.568542
+52 62 46.097722 46.097722 46.097722
+52 63 18.027756 18.027756 18.027756
+52 64 10.000000 10.000000 10.000000
+52 65 14.142136 14.142136 14.142136
+52 66 28.284271 28.284271 28.284271
+52 67 22.022716 22.022716 22.022716
+52 68 23.769729 23.769729 23.769729
+52 69 42.720019 42.720019 42.720019
+52 70 40.000000 40.000000 40.000000
+52 71 52.924474 52.924474 52.924474
+52 72 36.400549 36.400549 36.400549
+52 73 45.705580 45.705580 45.705580
+52 74 66.400301 66.400301 66.400301
+52 75 35.000000 35.000000 35.000000
+52 76 52.201533 52.201533 52.201533
+52 77 9.433981 9.433981 9.433981
+52 78 36.235342 36.235342 36.235342
+52 79 59.203040 59.203040 59.203040
+52 80 68.593003 68.593003 68.593003
+52 81 28.160256 28.160256 28.160256
+52 82 38.470768 38.470768 38.470768
+52 83 36.235342 36.235342 36.235342
+52 84 21.095023 21.095023 21.095023
+52 85 9.219544 9.219544 9.219544
+52 86 8.544004 8.544004 8.544004
+52 87 34.234486 34.234486 34.234486
+52 88 43.185646 43.185646 43.185646
+52 89 49.040799 49.040799 49.040799
+52 90 19.209373 19.209373 19.209373
+52 91 32.449961 32.449961 32.449961
+52 92 22.803509 22.803509 22.803509
+52 93 23.086793 23.086793 23.086793
+52 94 32.557641 32.557641 32.557641
+52 95 28.071338 28.071338 28.071338
+52 96 17.029386 17.029386 17.029386
+52 97 34.000000 34.000000 34.000000
+52 98 51.039201 51.039201 51.039201
+52 99 43.185646 43.185646 43.185646
+52 100 32.649655 32.649655 32.649655
+52 101 52.773099 52.773099 52.773099
+53 1 25.000000 25.000000 25.000000
+53 2 55.000000 55.000000 55.000000
+53 3 45.099889 45.099889 45.099889
+53 4 55.081757 55.081757 55.081757
+53 5 50.249378 50.249378 50.249378
+53 6 55.226805 55.226805 55.226805
+53 7 45.541190 45.541190 45.541190
+53 8 46.097722 46.097722 46.097722
+53 9 50.990195 50.990195 50.990195
+53 10 15.811388 15.811388 15.811388
+53 11 18.027756 18.027756 18.027756
+53 12 19.723083 19.723083 19.723083
+53 13 22.671568 22.671568 22.671568
+53 14 20.615528 20.615528 20.615528
+53 15 25.000000 25.000000 25.000000
+53 16 25.079872 25.079872 25.079872
+53 17 26.925824 26.925824 26.925824
+53 18 29.154759 29.154759 29.154759
+53 19 31.400637 31.400637 31.400637
+53 20 26.248809 26.248809 26.248809
+53 21 22.671568 22.671568 22.671568
+53 22 29.154759 29.154759 29.154759
+53 23 21.213203 21.213203 21.213203
+53 24 28.178006 28.178006 28.178006
+53 25 19.849433 19.849433 19.849433
+53 26 26.925824 26.925824 26.925824
+53 27 70.000000 70.000000 70.000000
+53 28 70.178344 70.178344 70.178344
+53 29 67.000000 67.000000 67.000000
+53 30 65.192024 65.192024 65.192024
+53 31 63.000000 63.000000 63.000000
+53 32 63.198101 63.198101 63.198101
+53 33 62.000000 62.000000 62.000000
+53 34 60.207973 60.207973 60.207973
+53 35 60.207973 60.207973 60.207973
+53 36 69.202601 69.202601 69.202601
+53 37 68.007353 68.007353 68.007353
+53 38 65.604878 65.604878 65.604878
+53 39 62.201286 62.201286 62.201286
+53 40 61.032778 61.032778 61.032778
+53 41 65.192024 65.192024 65.192024
+53 42 55.803226 55.803226 55.803226
+53 43 58.309519 58.309519 58.309519
+53 44 62.649820 62.649820 62.649820
+53 45 60.033324 60.033324 60.033324
+53 46 52.239832 52.239832 52.239832
+53 47 50.487622 50.487622 50.487622
+53 48 27.459060 27.459060 27.459060
+53 49 30.232433 30.232433 30.232433
+53 50 24.758837 24.758837 24.758837
+53 51 47.265209 47.265209 47.265209
+53 52 31.622777 31.622777 31.622777
+53 54 20.615528 20.615528 20.615528
+53 55 42.426407 42.426407 42.426407
+53 56 30.413813 30.413813 30.413813
+53 57 25.495098 25.495098 25.495098
+53 58 7.071068 7.071068 7.071068
+53 59 22.360680 22.360680 22.360680
+53 60 18.027756 18.027756 18.027756
+53 61 31.622777 31.622777 31.622777
+53 62 40.311289 40.311289 40.311289
+53 63 40.311289 40.311289 40.311289
+53 64 41.231056 41.231056 41.231056
+53 65 20.000000 20.000000 20.000000
+53 66 14.142136 14.142136 14.142136
+53 67 17.464249 17.464249 17.464249
+53 68 40.804412 40.804412 40.804412
+53 69 33.541020 33.541020 33.541020
+53 70 22.803509 22.803509 22.803509
+53 71 40.261644 40.261644 40.261644
+53 72 47.169906 47.169906 47.169906
+53 73 51.662365 51.662365 51.662365
+53 74 37.802116 37.802116 37.802116
+53 75 11.180340 11.180340 11.180340
+53 76 32.015621 32.015621 32.015621
+53 77 39.357337 39.357337 39.357337
+53 78 27.073973 27.073973 27.073973
+53 79 31.064449 31.064449 31.064449
+53 80 42.485292 42.485292 42.485292
+53 81 27.802878 27.802878 27.802878
+53 82 36.878178 36.878178 36.878178
+53 83 13.152946 13.152946 13.152946
+53 84 12.041595 12.041595 12.041595
+53 85 32.015621 32.015621 32.015621
+53 86 38.639358 38.639358 38.639358
+53 87 7.211103 7.211103 7.211103
+53 88 14.317821 14.317821 14.317821
+53 89 28.017851 28.017851 28.017851
+53 90 48.877398 48.877398 48.877398
+53 91 20.808652 20.808652 20.808652
+53 92 26.832816 26.832816 26.832816
+53 93 30.870698 30.870698 30.870698
+53 94 42.190046 42.190046 42.190046
+53 95 36.715120 36.715120 36.715120
+53 96 31.780497 31.780497 31.780497
+53 97 38.418745 38.418745 38.418745
+53 98 24.186773 24.186773 24.186773
+53 99 22.022716 22.022716 22.022716
+53 100 5.099020 5.099020 5.099020
+53 101 37.483330 37.483330 37.483330
+54 1 20.000000 20.000000 20.000000
+54 2 35.355339 35.355339 35.355339
+54 3 25.079872 25.079872 25.079872
+54 4 35.057096 35.057096 35.057096
+54 5 30.000000 30.000000 30.000000
+54 6 35.000000 35.000000 35.000000
+54 7 25.079872 25.079872 25.079872
+54 8 25.495098 25.495098 25.495098
+54 9 30.413813 30.413813 30.413813
+54 10 18.027756 18.027756 18.027756
+54 11 14.142136 14.142136 14.142136
+54 12 15.620499 15.620499 15.620499
+54 13 13.000000 13.000000 13.000000
+54 14 21.213203 21.213203 21.213203
+54 15 15.811388 15.811388 15.811388
+54 16 20.591260 20.591260 20.591260
+54 17 22.360680 22.360680 22.360680
+54 18 20.615528 20.615528 20.615528
+54 19 51.000000 51.000000 51.000000
+54 20 45.650849 45.650849 45.650849
+54 21 41.340053 41.340053 41.340053
+54 22 49.244289 49.244289 49.244289
+54 23 40.311289 40.311289 40.311289
+54 24 48.466483 48.466483 48.466483
+54 25 39.357337 39.357337 39.357337
+54 26 47.434165 47.434165 47.434165
+54 27 77.620873 77.620873 77.620873
+54 28 76.485293 76.485293 76.485293
+54 29 74.726167 74.726167 74.726167
+54 30 71.589105 71.589105 71.589105
+54 31 70.880181 70.880181 70.880181
+54 32 69.634761 69.634761 69.634761
+54 33 69.921384 69.921384 69.921384
+54 34 69.641941 69.641941 69.641941
+54 35 66.708320 66.708320 66.708320
+54 36 58.600341 58.600341 58.600341
+54 37 57.008771 57.008771 57.008771
+54 38 55.217751 55.217751 55.217751
+54 39 51.613952 51.613952 51.613952
+54 40 50.000000 50.000000 50.000000
+54 41 53.150729 53.150729 53.150729
+54 42 45.486262 45.486262 45.486262
+54 43 46.097722 46.097722 46.097722
+54 44 49.497475 49.497475 49.497475
+54 45 47.423623 47.423623 47.423623
+54 46 32.000000 32.000000 32.000000
+54 47 30.066593 30.066593 30.066593
+54 48 18.681542 18.681542 18.681542
+54 49 50.089919 50.089919 50.089919
+54 50 43.908997 43.908997 43.908997
+54 51 54.120237 54.120237 54.120237
+54 52 46.097722 46.097722 46.097722
+54 53 20.615528 20.615528 20.615528
+54 55 36.400549 36.400549 36.400549
+54 56 14.142136 14.142136 14.142136
+54 57 33.541020 33.541020 33.541020
+54 58 26.925824 26.925824 26.925824
+54 59 40.311289 40.311289 40.311289
+54 60 31.622777 31.622777 31.622777
+54 61 11.180340 11.180340 11.180340
+54 62 29.154759 29.154759 29.154759
+54 63 47.434165 47.434165 47.434165
+54 64 54.083269 54.083269 54.083269
+54 65 32.015621 32.015621 32.015621
+54 66 18.027756 18.027756 18.027756
+54 67 24.698178 24.698178 24.698178
+54 68 44.721360 44.721360 44.721360
+54 69 22.360680 22.360680 22.360680
+54 70 11.180340 11.180340 11.180340
+54 71 24.207437 24.207437 24.207437
+54 72 45.276926 45.276926 45.276926
+54 73 45.541190 45.541190 45.541190
+54 74 20.591260 20.591260 20.591260
+54 75 30.000000 30.000000 30.000000
+54 76 47.434165 47.434165 47.434165
+54 77 55.172457 55.172457 55.172457
+54 78 47.095647 47.095647 47.095647
+54 79 13.416408 13.416408 13.416408
+54 80 22.803509 22.803509 22.803509
+54 81 27.166155 27.166155 27.166155
+54 82 30.083218 30.083218 30.083218
+54 83 9.899495 9.899495 9.899495
+54 84 25.495098 25.495098 25.495098
+54 85 42.544095 42.544095 42.544095
+54 86 50.774009 50.774009 50.774009
+54 87 26.019224 26.019224 26.019224
+54 88 27.202941 27.202941 27.202941
+54 89 8.944272 8.944272 8.944272
+54 90 65.069194 65.069194 65.069194
+54 91 17.262677 17.262677 17.262677
+54 92 30.083218 30.083218 30.083218
+54 93 33.734256 33.734256 33.734256
+54 94 41.048752 41.048752 41.048752
+54 95 37.054015 37.054015 37.054015
+54 96 38.275318 38.275318 38.275318
+54 97 35.227830 35.227830 35.227830
+54 98 35.777088 35.777088 35.777088
+54 99 6.324555 6.324555 6.324555
+54 100 16.155494 16.155494 16.155494
+54 101 20.248457 20.248457 20.248457
+55 1 18.027756 18.027756 18.027756
+55 2 39.051248 39.051248 39.051248
+55 3 36.249138 36.249138 36.249138
+55 4 41.400483 41.400483 41.400483
+55 5 40.311289 40.311289 40.311289
+55 6 43.011626 43.011626 43.011626
+55 7 39.924930 39.924930 39.924930
+55 8 42.720019 42.720019 42.720019
+55 9 44.721360 44.721360 44.721360
+55 10 51.478151 51.478151 51.478151
+55 11 49.244289 49.244289 49.244289
+55 12 51.078371 51.078371 51.078371
+55 13 49.335586 49.335586 49.335586
+55 14 55.901699 55.901699 55.901699
+55 15 52.201533 52.201533 52.201533
+55 16 56.648036 56.648036 56.648036
+55 17 58.523500 58.523500 58.523500
+55 18 57.008771 57.008771 57.008771
+55 19 56.089215 56.089215 56.089215
+55 20 51.662365 51.662365 51.662365
+55 21 46.840154 46.840154 46.840154
+55 22 57.008771 57.008771 57.008771
+55 23 47.434165 47.434165 47.434165
+55 24 57.567352 57.567352 57.567352
+55 25 48.104054 48.104054 48.104054
+55 26 58.523500 58.523500 58.523500
+55 27 50.000000 50.000000 50.000000
+55 28 47.169906 47.169906 47.169906
+55 29 47.634021 47.634021 47.634021
+55 30 43.011626 43.011626 43.011626
+55 31 44.598206 44.598206 44.598206
+55 32 41.400483 41.400483 41.400483
+55 33 43.863424 43.863424 43.863424
+55 34 46.097722 46.097722 46.097722
+55 35 39.051248 39.051248 39.051248
+55 36 27.730849 27.730849 27.730849
+55 37 26.925824 26.925824 26.925824
+55 38 24.166092 24.166092 24.166092
+55 39 21.189620 21.189620 21.189620
+55 40 20.615528 20.615528 20.615528
+55 41 25.495098 25.495098 25.495098
+55 42 15.297059 15.297059 15.297059
+55 43 20.000000 20.000000 20.000000
+55 44 25.000000 25.000000 25.000000
+55 45 22.000000 22.000000 22.000000
+55 46 41.340053 41.340053 41.340053
+55 47 42.059482 42.059482 42.059482
+55 48 55.081757 55.081757 55.081757
+55 49 56.515485 56.515485 56.515485
+55 50 49.729267 49.729267 49.729267
+55 51 30.232433 30.232433 30.232433
+55 52 40.000000 40.000000 40.000000
+55 53 42.426407 42.426407 42.426407
+55 54 36.400549 36.400549 36.400549
+55 56 25.000000 25.000000 25.000000
+55 57 25.495098 25.495098 25.495098
+55 58 43.011626 43.011626 43.011626
+55 59 64.031242 64.031242 64.031242
+55 60 60.207973 60.207973 60.207973
+55 61 40.000000 40.000000 40.000000
+55 62 11.180340 11.180340 11.180340
+55 63 26.925824 26.925824 26.925824
+55 64 41.231056 41.231056 41.231056
+55 65 31.622777 31.622777 31.622777
+55 66 28.284271 28.284271 28.284271
+55 67 26.925824 26.925824 26.925824
+55 68 20.124612 20.124612 20.124612
+55 69 15.000000 15.000000 15.000000
+55 70 25.298221 25.298221 25.298221
+55 71 21.931712 21.931712 21.931712
+55 72 11.180340 11.180340 11.180340
+55 73 9.433981 9.433981 9.433981
+55 74 53.000000 53.000000 53.000000
+55 75 53.150729 53.150729 53.150729
+55 76 74.330344 74.330344 74.330344
+55 77 48.259714 48.259714 48.259714
+55 78 65.368188 65.368188 65.368188
+55 79 47.169906 47.169906 47.169906
+55 80 49.648766 49.648766 49.648766
+55 81 15.264338 15.264338 15.264338
+55 82 6.324555 6.324555 6.324555
+55 83 32.756679 32.756679 32.756679
+55 84 34.132096 34.132096 34.132096
+55 85 31.064449 31.064449 31.064449
+55 86 37.854986 37.854986 37.854986
+55 87 49.517674 49.517674 49.517674
+55 88 56.080300 56.080300 56.080300
+55 89 31.064449 31.064449 31.064449
+55 90 56.293872 56.293872 56.293872
+55 91 22.203603 22.203603 22.203603
+55 92 18.973666 18.973666 18.973666
+55 93 17.117243 17.117243 17.117243
+55 94 10.000000 10.000000 10.000000
+55 95 12.165525 12.165525 12.165525
+55 96 23.021729 23.021729 23.021729
+55 97 6.000000 6.000000 6.000000
+55 98 66.068147 66.068147 66.068147
+55 99 30.083218 30.083218 30.083218
+55 100 38.288379 38.288379 38.288379
+55 101 25.000000 25.000000 25.000000
+56 1 14.142136 14.142136 14.142136
+56 2 25.495098 25.495098 25.495098
+56 3 17.000000 17.000000 17.000000
+56 4 26.248809 26.248809 26.248809
+56 5 22.360680 22.360680 22.360680
+56 6 26.925824 26.925824 26.925824
+56 7 19.209373 19.209373 19.209373
+56 8 21.213203 21.213203 21.213203
+56 9 25.000000 25.000000 25.000000
+56 10 32.015621 32.015621 32.015621
+56 11 28.284271 28.284271 28.284271
+56 12 29.732137 29.732137 29.732137
+56 13 26.627054 26.627054 26.627054
+56 14 35.355339 35.355339 35.355339
+56 15 29.154759 29.154759 29.154759
+56 16 34.409301 34.409301 34.409301
+56 17 36.055513 36.055513 36.055513
+56 18 33.541020 33.541020 33.541020
+56 19 56.753854 56.753854 56.753854
+56 20 51.419841 51.419841 51.419841
+56 21 46.572524 46.572524 46.572524
+56 22 55.901699 55.901699 55.901699
+56 23 46.097722 46.097722 46.097722
+56 24 55.578773 55.578773 55.578773
+56 25 45.705580 45.705580 45.705580
+56 26 55.226805 55.226805 55.226805
+56 27 71.589105 71.589105 71.589105
+56 28 69.641941 69.641941 69.641941
+56 29 68.876701 68.876701 68.876701
+56 30 65.000000 65.000000 65.000000
+56 31 65.299311 65.299311 65.299311
+56 32 63.158531 63.158531 63.158531
+56 33 64.412732 64.412732 64.412732
+56 34 65.192024 65.192024 65.192024
+56 35 60.415230 60.415230 60.415230
+56 36 44.654227 44.654227 44.654227
+56 37 43.011626 43.011626 43.011626
+56 38 41.340053 41.340053 41.340053
+56 39 37.735925 37.735925 37.735925
+56 40 36.055513 36.055513 36.055513
+56 41 39.051248 39.051248 39.051248
+56 42 31.764760 31.764760 31.764760
+56 43 32.015621 32.015621 32.015621
+56 44 35.355339 35.355339 35.355339
+56 45 33.301652 33.301652 33.301652
+56 46 24.166092 24.166092 24.166092
+56 47 23.323808 23.323808 23.323808
+56 48 31.764760 31.764760 31.764760
+56 49 56.293872 56.293872 56.293872
+56 50 49.477268 49.477268 49.477268
+56 51 48.877398 48.877398 48.877398
+56 52 47.169906 47.169906 47.169906
+56 53 30.413813 30.413813 30.413813
+56 54 14.142136 14.142136 14.142136
+56 55 25.000000 25.000000 25.000000
+56 57 32.015621 32.015621 32.015621
+56 58 35.000000 35.000000 35.000000
+56 59 52.201533 52.201533 52.201533
+56 60 44.721360 44.721360 44.721360
+56 61 15.000000 15.000000 15.000000
+56 62 15.811388 15.811388 15.811388
+56 63 43.011626 43.011626 43.011626
+56 64 53.150729 53.150729 53.150729
+56 65 33.541020 33.541020 33.541020
+56 66 20.615528 20.615528 20.615528
+56 67 25.495098 25.495098 25.495098
+56 68 38.470768 38.470768 38.470768
+56 69 10.000000 10.000000 10.000000
+56 70 8.062258 8.062258 8.062258
+56 71 10.295630 10.295630 10.295630
+56 72 35.355339 35.355339 35.355339
+56 73 33.376639 33.376639 33.376639
+56 74 28.000000 28.000000 28.000000
+56 75 41.231056 41.231056 41.231056
+56 76 60.415230 60.415230 60.415230
+56 77 56.603887 56.603887 56.603887
+56 78 57.428216 57.428216 57.428216
+56 79 22.360680 22.360680 22.360680
+56 80 25.298221 25.298221 25.298221
+56 81 21.400935 21.400935 21.400935
+56 82 19.104973 19.104973 19.104973
+56 83 17.262677 17.262677 17.262677
+56 84 29.832868 29.832868 29.832868
+56 85 41.109610 41.109610 41.109610
+56 86 49.578221 49.578221 49.578221
+56 87 37.107951 37.107951 37.107951
+56 88 40.249224 40.249224 40.249224
+56 89 6.324555 6.324555 6.324555
+56 90 66.287254 66.287254 66.287254
+56 91 14.764823 14.764823 14.764823
+56 92 26.172505 26.172505 26.172505
+56 93 28.600699 28.600699 28.600699
+56 94 32.015621 32.015621 32.015621
+56 95 29.546573 29.546573 29.546573
+56 96 34.713110 34.713110 34.713110
+56 97 25.709920 25.709920 25.709920
+56 98 49.396356 49.396356 49.396356
+56 99 8.944272 8.944272 8.944272
+56 100 25.317978 25.317978 25.317978
+56 101 7.071068 7.071068 7.071068
+57 1 18.027756 18.027756 18.027756
+57 2 55.901699 55.901699 55.901699
+57 3 48.826222 48.826222 48.826222
+57 4 57.306195 57.306195 57.306195
+57 5 54.083269 54.083269 54.083269
+57 6 58.309519 58.309519 58.309519
+57 7 51.224994 51.224994 51.224994
+57 8 53.150729 53.150729 53.150729
+57 9 57.008771 57.008771 57.008771
+57 10 40.000000 40.000000 40.000000
+57 11 40.311289 40.311289 40.311289
+57 12 42.296572 42.296572 42.296572
+57 13 43.174066 43.174066 43.174066
+57 14 45.000000 45.000000 45.000000
+57 15 46.097722 46.097722 46.097722
+57 16 48.259714 48.259714 48.259714
+57 17 50.249378 50.249378 50.249378
+57 18 50.990195 50.990195 50.990195
+57 19 30.594117 30.594117 30.594117
+57 20 26.248809 26.248809 26.248809
+57 21 21.540659 21.540659 21.540659
+57 22 31.622777 31.622777 31.622777
+57 23 22.360680 22.360680 22.360680
+57 24 32.310989 32.310989 32.310989
+57 25 23.323808 23.323808 23.323808
+57 26 33.541020 33.541020 33.541020
+57 27 45.276926 45.276926 45.276926
+57 28 45.000000 45.000000 45.000000
+57 29 42.296572 42.296572 42.296572
+57 30 40.000000 40.000000 40.000000
+57 31 38.327536 38.327536 38.327536
+57 32 38.000000 38.000000 38.000000
+57 33 37.336309 37.336309 37.336309
+57 34 36.400549 36.400549 36.400549
+57 35 35.000000 35.000000 35.000000
+57 36 52.810984 52.810984 52.810984
+57 37 52.201533 52.201533 52.201533
+57 38 49.335586 49.335586 49.335586
+57 39 46.572524 46.572524 46.572524
+57 40 46.097722 46.097722 46.097722
+57 41 50.990195 50.990195 50.990195
+57 42 40.792156 40.792156 40.792156
+57 43 45.276926 45.276926 45.276926
+57 44 50.249378 50.249378 50.249378
+57 45 47.265209 47.265209 47.265209
+57 46 55.758407 55.758407 55.758407
+57 47 55.217751 55.217751 55.217751
+57 48 49.030603 49.030603 49.030603
+57 49 31.048349 31.048349 31.048349
+57 50 24.351591 24.351591 24.351591
+57 51 22.000000 22.000000 22.000000
+57 52 15.811388 15.811388 15.811388
+57 53 25.495098 25.495098 25.495098
+57 54 33.541020 33.541020 33.541020
+57 55 25.495098 25.495098 25.495098
+57 56 32.015621 32.015621 32.015621
+57 58 22.360680 22.360680 22.360680
+57 59 43.011626 43.011626 43.011626
+57 60 42.720019 42.720019 42.720019
+57 61 43.011626 43.011626 43.011626
+57 62 30.413813 30.413813 30.413813
+57 63 15.000000 15.000000 15.000000
+57 64 21.213203 21.213203 21.213203
+57 65 7.071068 7.071068 7.071068
+57 66 15.811388 15.811388 15.811388
+57 67 9.219544 9.219544 9.219544
+57 68 15.652476 15.652476 15.652476
+57 69 26.925824 26.925824 26.925824
+57 70 25.495098 25.495098 25.495098
+57 71 37.161808 37.161808 37.161808
+57 72 25.000000 25.000000 25.000000
+57 73 32.695565 32.695565 32.695565
+57 74 54.120237 54.120237 54.120237
+57 75 33.541020 33.541020 33.541020
+57 76 54.083269 54.083269 54.083269
+57 77 25.079872 25.079872 25.079872
+57 78 41.868843 41.868843 41.868843
+57 79 46.957428 46.957428 46.957428
+57 80 55.000000 55.000000 55.000000
+57 81 12.369317 12.369317 12.369317
+57 82 23.021729 23.021729 23.021729
+57 83 24.351591 24.351591 24.351591
+57 84 13.601471 13.601471 13.601471
+57 85 9.219544 9.219544 9.219544
+57 86 17.691806 17.691806 17.691806
+57 87 31.016125 31.016125 31.016125
+57 88 39.560081 39.560081 39.560081
+57 89 34.713110 34.713110 34.713110
+57 90 34.481879 34.481879 34.481879
+57 91 17.691806 17.691806 17.691806
+57 92 7.071068 7.071068 7.071068
+57 93 8.544004 8.544004 8.544004
+57 94 20.248457 20.248457 20.248457
+57 95 14.764823 14.764823 14.764823
+57 96 6.324555 6.324555 6.324555
+57 97 19.646883 19.646883 19.646883
+57 98 49.040799 49.040799 49.040799
+57 99 29.410882 29.410882 29.410882
+57 100 24.000000 24.000000 24.000000
+57 101 37.215588 37.215588 37.215588
+58 1 26.925824 26.925824 26.925824
+58 2 60.207973 60.207973 60.207973
+58 3 50.635956 50.635956 50.635956
+58 4 60.530984 60.530984 60.530984
+58 5 55.901699 55.901699 55.901699
+58 6 60.827625 60.827625 60.827625
+58 7 51.419841 51.419841 51.419841
+58 8 52.201533 52.201533 52.201533
+58 9 57.008771 57.008771 57.008771
+58 10 22.360680 22.360680 22.360680
+58 11 25.000000 25.000000 25.000000
+58 12 26.627054 26.627054 26.627054
+58 13 29.732137 29.732137 29.732137
+58 14 26.925824 26.925824 26.925824
+58 15 32.015621 32.015621 32.015621
+58 16 31.764760 31.764760 31.764760
+58 17 33.541020 33.541020 33.541020
+58 18 36.055513 36.055513 36.055513
+58 19 24.413111 24.413111 24.413111
+58 20 19.209373 19.209373 19.209373
+58 21 15.620499 15.620499 15.620499
+58 22 22.360680 22.360680 22.360680
+58 23 14.142136 14.142136 14.142136
+58 24 21.540659 21.540659 21.540659
+58 25 12.806248 12.806248 12.806248
+58 26 20.615528 20.615528 20.615528
+58 27 65.192024 65.192024 65.192024
+58 28 65.764732 65.764732 65.764732
+58 29 62.201286 62.201286 62.201286
+58 30 60.827625 60.827625 60.827625
+58 31 58.215118 58.215118 58.215118
+58 32 58.855756 58.855756 58.855756
+58 33 57.218878 57.218878 57.218878
+58 34 55.000000 55.000000 55.000000
+58 35 55.901699 55.901699 55.901699
+58 36 70.491134 70.491134 70.491134
+58 37 69.462220 69.462220 69.462220
+58 38 66.887966 66.887966 66.887966
+58 39 63.631753 63.631753 63.631753
+58 40 62.649820 62.649820 62.649820
+58 41 67.082039 67.082039 67.082039
+58 42 57.306195 57.306195 57.306195
+58 43 60.415230 60.415230 60.415230
+58 44 65.000000 65.000000 65.000000
+58 45 62.241465 62.241465 62.241465
+58 46 57.870545 57.870545 57.870545
+58 47 56.293872 56.293872 56.293872
+58 48 34.409301 34.409301 34.409301
+58 49 23.323808 23.323808 23.323808
+58 50 17.691806 17.691806 17.691806
+58 51 43.174066 43.174066 43.174066
+58 52 25.495098 25.495098 25.495098
+58 53 7.071068 7.071068 7.071068
+58 54 26.925824 26.925824 26.925824
+58 55 43.011626 43.011626 43.011626
+58 56 35.000000 35.000000 35.000000
+58 57 22.360680 22.360680 22.360680
+58 59 21.213203 21.213203 21.213203
+58 60 20.615528 20.615528 20.615528
+58 61 38.078866 38.078866 38.078866
+58 62 42.720019 42.720019 42.720019
+58 63 36.400549 36.400549 36.400549
+58 64 35.355339 35.355339 35.355339
+58 65 15.811388 15.811388 15.811388
+58 66 15.811388 15.811388 15.811388
+58 67 16.278821 16.278821 16.278821
+58 68 38.013156 38.013156 38.013156
+58 69 36.400549 36.400549 36.400549
+58 70 27.018512 27.018512 27.018512
+58 71 44.283180 44.283180 44.283180
+58 72 46.097722 46.097722 46.097722
+58 73 51.855569 51.855569 51.855569
+58 74 44.821870 44.821870 44.821870
+58 75 11.180340 11.180340 11.180340
+58 76 32.015621 32.015621 32.015621
+58 77 32.695565 32.695565 32.695565
+58 78 23.086793 23.086793 23.086793
+58 79 38.013156 38.013156 38.013156
+58 80 49.244289 49.244289 49.244289
+58 81 27.802878 27.802878 27.802878
+58 82 38.078866 38.078866 38.078866
+58 83 18.248288 18.248288 18.248288
+58 84 9.219544 9.219544 9.219544
+58 85 27.294688 27.294688 27.294688
+58 86 33.060551 33.060551 33.060551
+58 87 9.055385 9.055385 9.055385
+58 88 18.027756 18.027756 18.027756
+58 89 33.541020 33.541020 33.541020
+58 90 42.059482 42.059482 42.059482
+58 91 23.086793 23.086793 23.086793
+58 92 25.495098 25.495098 25.495098
+58 93 29.206164 29.206164 29.206164
+58 94 41.109610 41.109610 41.109610
+58 95 35.468296 35.468296 35.468296
+58 96 28.635642 28.635642 28.635642
+58 97 38.288379 38.288379 38.288379
+58 98 26.925824 26.925824 26.925824
+58 99 27.294688 27.294688 27.294688
+58 100 10.770330 10.770330 10.770330
+58 101 42.011903 42.011903 42.011903
+59 1 47.169906 47.169906 47.169906
+59 2 75.663730 75.663730 75.663730
+59 3 65.375837 65.375837 65.375837
+59 4 75.325958 75.325958 75.325958
+59 5 70.178344 70.178344 70.178344
+59 6 75.166482 75.166482 75.166482
+59 7 65.069194 65.069194 65.069194
+59 8 65.000000 65.000000 65.000000
+59 9 70.000000 70.000000 70.000000
+59 10 25.495098 25.495098 25.495098
+59 11 30.413813 30.413813 30.413813
+59 12 30.805844 30.805844 30.805844
+59 13 35.693137 35.693137 35.693137
+59 14 26.925824 26.925824 26.925824
+59 15 36.400549 36.400549 36.400549
+59 16 32.695565 32.695565 32.695565
+59 17 33.541020 33.541020 33.541020
+59 18 38.078866 38.078866 38.078866
+59 19 29.427878 29.427878 29.427878
+59 20 27.000000 27.000000 27.000000
+59 21 27.459060 27.459060 27.459060
+59 22 25.495098 25.495098 25.495098
+59 23 25.495098 25.495098 25.495098
+59 24 23.537205 23.537205 23.537205
+59 25 23.537205 23.537205 23.537205
+59 26 20.615528 20.615528 20.615528
+59 27 82.462113 82.462113 82.462113
+59 28 83.815273 83.815273 83.815273
+59 29 79.555012 79.555012 79.555012
+59 30 79.056942 79.056942 79.056942
+59 31 75.690158 75.690158 75.690158
+59 32 77.162167 77.162167 77.162167
+59 33 74.726167 74.726167 74.726167
+59 34 71.589105 71.589105 71.589105
+59 35 74.330344 74.330344 74.330344
+59 36 91.263355 91.263355 91.263355
+59 37 90.138782 90.138782 90.138782
+59 38 87.658428 87.658428 87.658428
+59 39 84.314886 84.314886 84.314886
+59 40 83.216585 83.216585 83.216585
+59 41 87.464278 87.464278 87.464278
+59 42 77.935871 77.935871 77.935871
+59 43 80.622577 80.622577 80.622577
+59 44 85.000000 85.000000 85.000000
+59 45 82.365041 82.365041 82.365041
+59 46 72.173402 72.173402 72.173402
+59 47 70.064256 70.064256 70.064256
+59 48 37.336309 37.336309 37.336309
+59 49 27.459060 27.459060 27.459060
+59 50 27.073973 27.073973 27.073973
+59 51 62.241465 62.241465 62.241465
+59 52 41.231056 41.231056 41.231056
+59 53 22.360680 22.360680 22.360680
+59 54 40.311289 40.311289 40.311289
+59 55 64.031242 64.031242 64.031242
+59 56 52.201533 52.201533 52.201533
+59 57 43.011626 43.011626 43.011626
+59 58 21.213203 21.213203 21.213203
+59 60 11.180340 11.180340 11.180340
+59 61 50.000000 50.000000 50.000000
+59 62 62.649820 62.649820 62.649820
+59 63 55.901699 55.901699 55.901699
+59 64 50.990195 50.990195 50.990195
+59 65 36.055513 36.055513 36.055513
+59 66 36.055513 36.055513 36.055513
+59 67 37.483330 37.483330 37.483330
+59 68 58.523500 58.523500 58.523500
+59 69 55.901699 55.901699 55.901699
+59 70 44.944410 44.944410 44.944410
+59 71 62.297673 62.297673 62.297673
+59 72 67.268120 67.268120 67.268120
+59 73 73.000000 73.000000 73.000000
+59 74 51.662365 51.662365 51.662365
+59 75 11.180340 11.180340 11.180340
+59 76 11.180340 11.180340 11.180340
+59 77 45.044423 45.044423 45.044423
+59 78 10.630146 10.630146 10.630146
+59 79 46.529560 46.529560 46.529560
+59 80 58.694122 58.694122 58.694122
+59 81 48.918299 48.918299 48.918299
+59 82 58.821765 58.821765 58.821765
+59 83 35.114100 35.114100 35.114100
+59 84 30.413813 30.413813 30.413813
+59 85 46.097722 46.097722 46.097722
+59 86 49.729267 49.729267 49.729267
+59 87 15.231546 15.231546 15.231546
+59 88 14.317821 14.317821 14.317821
+59 89 48.836462 48.836462 48.836462
+59 90 52.239832 52.239832 52.239832
+59 91 43.046487 43.046487 43.046487
+59 92 46.690470 46.690470 46.690470
+59 93 50.328918 50.328918 50.328918
+59 94 62.289646 62.289646 62.289646
+59 95 56.639209 56.639209 56.639209
+59 96 49.091751 49.091751 49.091751
+59 97 59.464275 59.464275 59.464275
+59 98 13.601471 13.601471 13.601471
+59 99 43.416587 43.416587 43.416587
+59 100 27.313001 27.313001 27.313001
+59 101 59.203040 59.203040 59.203040
+60 1 42.426407 42.426407 42.426407
+60 2 66.708320 66.708320 66.708320
+60 3 56.293872 56.293872 56.293872
+60 4 66.098411 66.098411 66.098411
+60 5 60.827625 60.827625 60.827625
+60 6 65.764732 65.764732 65.764732
+60 7 55.578773 55.578773 55.578773
+60 8 55.226805 55.226805 55.226805
+60 9 60.207973 60.207973 60.207973
+60 10 15.000000 15.000000 15.000000
+60 11 20.000000 20.000000 20.000000
+60 12 20.099751 20.099751 20.099751
+60 13 25.079872 25.079872 25.079872
+60 14 15.811388 15.811388 15.811388
+60 15 25.495098 25.495098 25.495098
+60 16 21.540659 21.540659 21.540659
+60 17 22.360680 22.360680 22.360680
+60 18 26.925824 26.925824 26.925824
+60 19 37.161808 37.161808 37.161808
+60 20 33.526109 33.526109 33.526109
+60 21 32.388269 32.388269 32.388269
+60 22 33.541020 33.541020 33.541020
+60 23 30.413813 30.413813 30.413813
+60 24 31.764760 31.764760 31.764760
+60 25 28.442925 28.442925 28.442925
+60 26 29.154759 29.154759 29.154759
+60 27 85.586214 85.586214 85.586214
+60 28 86.313383 86.313383 86.313383
+60 29 82.607506 82.607506 82.607506
+60 30 81.394103 81.394103 81.394103
+60 31 78.638413 78.638413 78.638413
+60 32 79.429214 79.429214 79.429214
+60 33 77.646635 77.646635 77.646635
+60 34 75.166482 75.166482 75.166482
+60 35 76.485293 76.485293 76.485293
+60 36 86.452299 86.452299 86.452299
+60 37 85.146932 85.146932 85.146932
+60 38 82.879430 82.879430 82.879430
+60 39 79.397733 79.397733 79.397733
+60 40 78.102497 78.102497 78.102497
+60 41 82.006097 82.006097 82.006097
+60 42 73.000000 73.000000 73.000000
+60 43 75.000000 75.000000 75.000000
+60 44 79.056942 79.056942 79.056942
+60 45 76.609399 76.609399 76.609399
+60 46 62.801274 62.801274 62.801274
+60 47 60.530984 60.530984 60.530984
+60 48 26.248809 26.248809 26.248809
+60 49 35.341194 35.341194 35.341194
+60 50 32.984845 32.984845 32.984845
+60 51 63.788714 63.788714 63.788714
+60 52 45.000000 45.000000 45.000000
+60 53 18.027756 18.027756 18.027756
+60 54 31.622777 31.622777 31.622777
+60 55 60.207973 60.207973 60.207973
+60 56 44.721360 44.721360 44.721360
+60 57 42.720019 42.720019 42.720019
+60 58 20.615528 20.615528 20.615528
+60 59 11.180340 11.180340 11.180340
+60 61 40.311289 40.311289 40.311289
+60 62 57.008771 57.008771 57.008771
+60 63 57.008771 57.008771 57.008771
+60 64 55.000000 55.000000 55.000000
+60 65 36.400549 36.400549 36.400549
+60 66 32.015621 32.015621 32.015621
+60 67 35.355339 35.355339 35.355339
+60 68 58.309519 58.309519 58.309519
+60 69 50.000000 50.000000 50.000000
+60 70 38.275318 38.275318 38.275318
+60 71 55.009090 55.009090 55.009090
+60 72 65.192024 65.192024 65.192024
+60 73 69.526973 69.526973 69.526973
+60 74 40.792156 40.792156 40.792156
+60 75 10.000000 10.000000 10.000000
+60 76 15.811388 15.811388 15.811388
+60 77 50.635956 50.635956 50.635956
+60 78 21.400935 21.400935 21.400935
+60 79 36.055513 36.055513 36.055513
+60 80 48.166378 48.166378 48.166378
+60 81 45.803930 45.803930 45.803930
+60 82 54.451814 54.451814 54.451814
+60 83 28.600699 28.600699 28.600699
+60 84 29.154759 29.154759 29.154759
+60 85 47.853944 47.853944 47.853944
+60 86 53.084838 53.084838 53.084838
+60 87 11.704700 11.704700 11.704700
+60 88 4.472136 4.472136 4.472136
+60 89 40.496913 40.496913 40.496913
+60 90 58.940648 58.940648 58.940648
+60 91 38.183766 38.183766 38.183766
+60 92 44.777226 44.777226 44.777226
+60 93 48.764741 48.764741 48.764741
+60 94 60.207973 60.207973 60.207973
+60 95 54.708317 54.708317 54.708317
+60 96 49.040799 49.040799 49.040799
+60 97 56.400355 56.400355 56.400355
+60 98 6.324555 6.324555 6.324555
+60 99 35.777088 35.777088 35.777088
+60 100 21.931712 21.931712 21.931712
+60 101 51.478151 51.478151 51.478151
+61 1 26.925824 26.925824 26.925824
+61 2 26.925824 26.925824 26.925824
+61 3 16.552945 16.552945 16.552945
+61 4 25.961510 25.961510 25.961510
+61 5 20.615528 20.615528 20.615528
+61 6 25.495098 25.495098 25.495098
+61 7 15.297059 15.297059 15.297059
+61 8 15.000000 15.000000 15.000000
+61 9 20.000000 20.000000 20.000000
+61 10 25.495098 25.495098 25.495098
+61 11 20.615528 20.615528 20.615528
+61 12 21.189620 21.189620 21.189620
+61 13 16.552945 16.552945 16.552945
+61 14 26.925824 26.925824 26.925824
+61 15 18.027756 18.027756 18.027756
+61 16 23.853721 23.853721 23.853721
+61 17 25.000000 25.000000 25.000000
+61 18 21.213203 21.213203 21.213203
+61 19 62.177166 62.177166 62.177166
+61 20 56.824291 56.824291 56.824291
+61 21 52.478567 52.478567 52.478567
+61 22 60.415230 60.415230 60.415230
+61 23 51.478151 51.478151 51.478151
+61 24 59.615434 59.615434 59.615434
+61 25 50.537115 50.537115 50.537115
+61 26 58.523500 58.523500 58.523500
+61 27 85.440037 85.440037 85.440037
+61 28 83.815273 83.815273 83.815273
+61 29 82.637764 82.637764 82.637764
+61 30 79.056942 79.056942 79.056942
+61 31 78.924014 78.924014 78.924014
+61 32 77.162167 77.162167 77.162167
+61 33 78.000000 78.000000 78.000000
+61 34 78.262379 78.262379 78.262379
+61 35 74.330344 74.330344 74.330344
+61 36 57.697487 57.697487 57.697487
+61 37 55.901699 55.901699 55.901699
+61 38 54.626001 54.626001 54.626001
+61 39 51.078371 51.078371 51.078371
+61 40 49.244289 49.244289 49.244289
+61 41 51.478151 51.478151 51.478151
+61 42 45.541190 45.541190 45.541190
+61 43 44.721360 44.721360 44.721360
+61 44 47.169906 47.169906 47.169906
+61 45 45.650849 45.650849 45.650849
+61 46 22.561028 22.561028 22.561028
+61 47 20.223748 20.223748 20.223748
+61 48 19.849433 19.849433 19.849433
+61 49 61.269895 61.269895 61.269895
+61 50 55.072679 55.072679 55.072679
+61 51 62.241465 62.241465 62.241465
+61 52 56.568542 56.568542 56.568542
+61 53 31.622777 31.622777 31.622777
+61 54 11.180340 11.180340 11.180340
+61 55 40.000000 40.000000 40.000000
+61 56 15.000000 15.000000 15.000000
+61 57 43.011626 43.011626 43.011626
+61 58 38.078866 38.078866 38.078866
+61 59 50.000000 50.000000 50.000000
+61 60 40.311289 40.311289 40.311289
+61 62 30.413813 30.413813 30.413813
+61 63 55.901699 55.901699 55.901699
+61 64 64.031242 64.031242 64.031242
+61 65 42.426407 42.426407 42.426407
+61 66 28.284271 28.284271 28.284271
+61 67 34.713110 34.713110 34.713110
+61 68 52.201533 52.201533 52.201533
+61 69 25.000000 25.000000 25.000000
+61 70 17.888544 17.888544 17.888544
+61 71 21.931712 21.931712 21.931712
+61 72 50.249378 50.249378 50.249378
+61 73 48.259714 48.259714 48.259714
+61 74 13.000000 13.000000 13.000000
+61 75 40.311289 40.311289 40.311289
+61 76 55.901699 55.901699 55.901699
+61 77 65.795137 65.795137 65.795137
+61 78 57.558666 57.558666 57.558666
+61 79 8.062258 8.062258 8.062258
+61 80 12.041595 12.041595 12.041595
+61 81 34.539832 34.539832 34.539832
+61 82 34.058773 34.058773 34.058773
+61 83 20.808652 20.808652 20.808652
+61 84 36.400549 36.400549 36.400549
+61 85 52.201533 52.201533 52.201533
+61 86 60.605280 60.605280 60.605280
+61 87 36.496575 36.496575 36.496575
+61 88 36.124784 36.124784 36.124784
+61 89 9.219544 9.219544 9.219544
+61 90 75.690158 75.690158 75.690158
+61 91 25.553865 25.553865 25.553865
+61 92 38.470768 38.470768 38.470768
+61 93 41.629317 41.629317 41.629317
+61 94 46.690470 46.690470 46.690470
+61 95 43.680659 43.680659 43.680659
+61 96 47.010637 47.010637 47.010637
+61 97 40.447497 40.447497 40.447497
+61 98 43.416587 43.416587 43.416587
+61 99 13.601471 13.601471 13.601471
+61 100 27.313001 27.313001 27.313001
+61 101 17.464249 17.464249 17.464249
+62 1 15.811388 15.811388 15.811388
+62 2 28.284271 28.284271 28.284271
+62 3 25.079872 25.079872 25.079872
+62 4 30.479501 30.479501 30.479501
+62 5 29.154759 29.154759 29.154759
+62 6 32.015621 32.015621 32.015621
+62 7 28.792360 28.792360 28.792360
+62 8 31.622777 31.622777 31.622777
+62 9 33.541020 33.541020 33.541020
+62 10 46.097722 46.097722 46.097722
+62 11 43.011626 43.011626 43.011626
+62 12 44.654227 44.654227 44.654227
+62 13 42.059482 42.059482 42.059482
+62 14 50.000000 50.000000 50.000000
+62 15 44.721360 44.721360 44.721360
+62 16 49.739320 49.739320 49.739320
+62 17 51.478151 51.478151 51.478151
+62 18 49.244289 49.244289 49.244289
+62 19 60.008333 60.008333 60.008333
+62 20 55.081757 55.081757 55.081757
+62 21 50.089919 50.089919 50.089919
+62 22 60.207973 60.207973 60.207973
+62 23 50.249378 50.249378 50.249378
+62 24 60.406953 60.406953 60.406953
+62 25 50.487622 50.487622 50.487622
+62 26 60.827625 60.827625 60.827625
+62 27 61.032778 61.032778 61.032778
+62 28 58.309519 58.309519 58.309519
+62 29 58.600341 58.600341 58.600341
+62 30 54.083269 54.083269 54.083269
+62 31 55.443665 55.443665 55.443665
+62 32 52.430907 52.430907 52.430907
+62 33 54.671748 54.671748 54.671748
+62 34 56.568542 56.568542 56.568542
+62 35 50.000000 50.000000 50.000000
+62 36 29.732137 29.732137 29.732137
+62 37 28.284271 28.284271 28.284271
+62 38 26.248809 26.248809 26.248809
+62 39 22.671568 22.671568 22.671568
+62 40 21.213203 21.213203 21.213203
+62 41 25.000000 25.000000 25.000000
+62 42 16.401219 16.401219 16.401219
+62 43 18.027756 18.027756 18.027756
+62 44 22.360680 22.360680 22.360680
+62 45 19.723083 19.723083 19.723083
+62 46 30.232433 30.232433 30.232433
+62 47 30.886890 30.886890 30.886890
+62 48 47.423623 47.423623 47.423623
+62 49 60.074953 60.074953 60.074953
+62 50 53.084838 53.084838 53.084838
+62 51 40.360872 40.360872 40.360872
+62 52 46.097722 46.097722 46.097722
+62 53 40.311289 40.311289 40.311289
+62 54 29.154759 29.154759 29.154759
+62 55 11.180340 11.180340 11.180340
+62 56 15.811388 15.811388 15.811388
+62 57 30.413813 30.413813 30.413813
+62 58 42.720019 42.720019 42.720019
+62 59 62.649820 62.649820 62.649820
+62 60 57.008771 57.008771 57.008771
+62 61 30.413813 30.413813 30.413813
+62 63 36.055513 36.055513 36.055513
+62 64 49.244289 49.244289 49.244289
+62 65 35.000000 35.000000 35.000000
+62 66 26.925824 26.925824 26.925824
+62 67 28.284271 28.284271 28.284271
+62 68 29.832868 29.832868 29.832868
+62 69 7.071068 7.071068 7.071068
+62 70 19.104973 19.104973 19.104973
+62 71 10.770330 10.770330 10.770330
+62 72 22.360680 22.360680 22.360680
+62 73 18.000000 18.000000 18.000000
+62 74 43.289722 43.289722 43.289722
+62 75 51.478151 51.478151 51.478151
+62 76 72.111026 72.111026 72.111026
+62 77 55.081757 55.081757 55.081757
+62 78 65.787537 65.787537 65.787537
+62 79 38.078866 38.078866 38.078866
+62 80 39.115214 39.115214 39.115214
+62 81 18.110770 18.110770 18.110770
+62 82 8.062258 8.062258 8.062258
+62 83 28.425341 28.425341 28.425341
+62 84 34.928498 34.928498 34.928498
+62 85 37.947332 37.947332 37.947332
+62 86 45.694639 45.694639 45.694639
+62 87 47.507894 47.507894 47.507894
+62 88 52.630789 52.630789 52.630789
+62 89 22.135944 22.135944 22.135944
+62 90 63.906181 63.906181 63.906181
+62 91 19.697716 19.697716 19.697716
+62 92 23.345235 23.345235 23.345235
+62 93 23.409400 23.409400 23.409400
+62 94 20.615528 20.615528 20.615528
+62 95 20.808652 20.808652 20.808652
+62 96 30.083218 30.083218 30.083218
+62 97 14.866069 14.866069 14.866069
+62 98 62.369865 62.369865 62.369865
+62 99 23.021729 23.021729 23.021729
+62 100 35.510562 35.510562 35.510562
+62 101 14.142136 14.142136 14.142136
+63 1 29.154759 29.154759 29.154759
+63 2 64.031242 64.031242 64.031242
+63 3 58.728187 58.728187 58.728187
+63 4 65.946948 65.946948 65.946948
+63 5 63.639610 63.639610 63.639610
+63 6 67.268120 67.268120 67.268120
+63 7 61.717096 61.717096 61.717096
+63 8 64.031242 64.031242 64.031242
+63 9 67.268120 67.268120 67.268120
+63 10 55.000000 55.000000 55.000000
+63 11 55.226805 55.226805 55.226805
+63 12 57.218878 57.218878 57.218878
+63 13 57.870545 57.870545 57.870545
+63 14 60.000000 60.000000 60.000000
+63 15 60.827625 60.827625 60.827625
+63 16 63.198101 63.198101 63.198101
+63 17 65.192024 65.192024 65.192024
+63 18 65.764732 65.764732 65.764732
+63 19 36.619667 36.619667 36.619667
+63 20 33.970576 33.970576 33.970576
+63 21 30.479501 30.479501 30.479501
+63 22 39.051248 39.051248 39.051248
+63 23 32.015621 32.015621 32.015621
+63 24 40.360872 40.360872 40.360872
+63 25 33.600595 33.600595 33.600595
+63 26 42.426407 42.426407 42.426407
+63 27 30.413813 30.413813 30.413813
+63 28 30.000000 30.000000 30.000000
+63 29 27.459060 27.459060 27.459060
+63 30 25.000000 25.000000 25.000000
+63 31 23.537205 23.537205 23.537205
+63 32 23.000000 23.000000 23.000000
+63 33 22.561028 22.561028 22.561028
+63 34 22.360680 22.360680 22.360680
+63 35 20.000000 20.000000 20.000000
+63 36 50.039984 50.039984 50.039984
+63 37 50.000000 50.000000 50.000000
+63 38 47.000000 47.000000 47.000000
+63 39 45.099889 45.099889 45.099889
+63 40 45.276926 45.276926 45.276926
+63 41 50.249378 50.249378 50.249378
+63 42 40.607881 40.607881 40.607881
+63 43 46.097722 46.097722 46.097722
+63 44 50.990195 50.990195 50.990195
+63 45 48.052055 48.052055 48.052055
+63 46 65.069194 65.069194 65.069194
+63 47 65.069194 65.069194 65.069194
+63 48 63.788714 63.788714 63.788714
+63 49 37.802116 37.802116 37.802116
+63 50 32.526912 32.526912 32.526912
+63 51 7.000000 7.000000 7.000000
+63 52 18.027756 18.027756 18.027756
+63 53 40.311289 40.311289 40.311289
+63 54 47.434165 47.434165 47.434165
+63 55 26.925824 26.925824 26.925824
+63 56 43.011626 43.011626 43.011626
+63 57 15.000000 15.000000 15.000000
+63 58 36.400549 36.400549 36.400549
+63 59 55.901699 55.901699 55.901699
+63 60 57.008771 57.008771 57.008771
+63 61 55.901699 55.901699 55.901699
+63 62 36.055513 36.055513 36.055513
+63 64 15.000000 15.000000 15.000000
+63 65 20.615528 20.615528 20.615528
+63 66 30.413813 30.413813 30.413813
+63 67 24.083189 24.083189 24.083189
+63 68 7.071068 7.071068 7.071068
+63 69 35.355339 35.355339 35.355339
+63 70 38.013156 38.013156 38.013156
+63 71 45.343136 45.343136 45.343136
+63 72 20.000000 20.000000 20.000000
+63 73 30.066593 30.066593 30.066593
+63 74 67.779053 67.779053 67.779053
+63 75 47.434165 47.434165 47.434165
+63 76 67.082039 67.082039 67.082039
+63 77 23.537205 23.537205 23.537205
+63 78 52.801515 52.801515 52.801515
+63 79 60.745370 60.745370 60.745370
+63 80 67.601775 67.601775 67.601775
+63 81 21.633308 21.633308 21.633308
+63 82 28.017851 28.017851 28.017851
+63 83 38.832976 38.832976 38.832976
+63 84 28.284271 28.284271 28.284271
+63 85 10.000000 10.000000 10.000000
+63 86 12.165525 12.165525 12.165525
+63 87 45.354162 45.354162 45.354162
+63 88 54.129474 54.129474 54.129474
+63 89 47.010637 47.010637 47.010637
+63 90 30.066593 30.066593 30.066593
+63 91 30.463092 30.463092 30.463092
+63 92 17.464249 17.464249 17.464249
+63 93 14.422205 14.422205 14.422205
+63 94 17.464249 17.464249 17.464249
+63 95 15.264338 15.264338 15.264338
+63 96 9.219544 9.219544 9.219544
+63 97 21.470911 21.470911 21.470911
+63 98 63.324561 63.324561 63.324561
+63 99 42.544095 42.544095 42.544095
+63 100 39.000000 39.000000 39.000000
+63 101 46.690470 46.690470 46.690470
+64 1 39.051248 39.051248 39.051248
+64 2 76.321688 76.321688 76.321688
+64 3 69.814039 69.814039 69.814039
+64 4 77.935871 77.935871 77.935871
+64 5 75.000000 75.000000 75.000000
+64 6 79.056942 79.056942 79.056942
+64 7 72.346389 72.346389 72.346389
+64 8 74.330344 74.330344 74.330344
+64 9 78.102497 78.102497 78.102497
+64 10 57.008771 57.008771 57.008771
+64 11 58.523500 58.523500 58.523500
+64 12 60.406953 60.406953 60.406953
+64 13 62.241465 62.241465 62.241465
+64 14 61.846584 61.846584 61.846584
+64 15 65.000000 65.000000 65.000000
+64 16 66.098411 66.098411 66.098411
+64 17 68.007353 68.007353 68.007353
+64 18 69.641941 69.641941 69.641941
+64 19 25.806976 25.806976 25.806976
+64 20 25.079872 25.079872 25.079872
+64 21 23.537205 23.537205 23.537205
+64 22 29.154759 29.154759 29.154759
+64 23 25.495098 25.495098 25.495098
+64 24 30.886890 30.886890 30.886890
+64 25 27.459060 27.459060 27.459060
+64 26 33.541020 33.541020 33.541020
+64 27 31.622777 31.622777 31.622777
+64 28 33.541020 33.541020 33.541020
+64 29 28.792360 28.792360 28.792360
+64 30 29.154759 29.154759 29.154759
+64 31 25.079872 25.079872 25.079872
+64 32 27.459060 27.459060 27.459060
+64 33 24.166092 24.166092 24.166092
+64 34 20.615528 20.615528 20.615528
+64 35 25.000000 25.000000 25.000000
+64 36 65.030762 65.030762 65.030762
+64 37 65.000000 65.000000 65.000000
+64 38 62.000000 62.000000 62.000000
+64 39 60.074953 60.074953 60.074953
+64 40 60.207973 60.207973 60.207973
+64 41 65.192024 65.192024 65.192024
+64 42 55.443665 55.443665 55.443665
+64 43 60.827625 60.827625 60.827625
+64 44 65.764732 65.764732 65.764732
+64 45 62.801274 62.801274 62.801274
+64 46 76.609399 76.609399 76.609399
+64 47 76.216796 76.216796 76.216796
+64 48 67.779053 67.779053 67.779053
+64 49 27.459060 27.459060 27.459060
+64 50 24.351591 24.351591 24.351591
+64 51 16.552945 16.552945 16.552945
+64 52 10.000000 10.000000 10.000000
+64 53 41.231056 41.231056 41.231056
+64 54 54.083269 54.083269 54.083269
+64 55 41.231056 41.231056 41.231056
+64 56 53.150729 53.150729 53.150729
+64 57 21.213203 21.213203 21.213203
+64 58 35.355339 35.355339 35.355339
+64 59 50.990195 50.990195 50.990195
+64 60 55.000000 55.000000 55.000000
+64 61 64.031242 64.031242 64.031242
+64 62 49.244289 49.244289 49.244289
+64 63 15.000000 15.000000 15.000000
+64 65 22.360680 22.360680 22.360680
+64 66 36.055513 36.055513 36.055513
+64 67 29.410882 29.410882 29.410882
+64 68 22.022716 22.022716 22.022716
+64 69 47.169906 47.169906 47.169906
+64 70 46.690470 46.690470 46.690470
+64 71 57.454330 57.454330 57.454330
+64 72 35.000000 35.000000 35.000000
+64 73 45.044423 45.044423 45.044423
+64 74 74.625733 74.625733 74.625733
+64 75 45.000000 45.000000 45.000000
+64 76 61.846584 61.846584 61.846584
+64 77 9.433981 9.433981 9.433981
+64 78 45.310043 45.310043 45.310043
+64 79 67.416615 67.416615 67.416615
+64 80 76.059187 76.059187 76.059187
+64 81 32.449961 32.449961 32.449961
+64 82 41.231056 41.231056 41.231056
+64 83 44.418465 44.418465 44.418465
+64 84 30.083218 30.083218 30.083218
+64 85 12.041595 12.041595 12.041595
+64 86 3.605551 3.605551 3.605551
+64 87 44.181444 44.181444 44.181444
+64 88 53.150729 53.150729 53.150729
+64 89 55.901699 55.901699 55.901699
+64 90 15.132746 15.132746 15.132746
+64 91 38.897301 38.897301 38.897301
+64 92 27.202941 27.202941 27.202941
+64 93 25.942244 25.942244 25.942244
+64 94 32.249031 32.249031 32.249031
+64 95 29.120440 29.120440 29.120440
+64 96 19.235384 19.235384 19.235384
+64 97 35.440090 35.440090 35.440090
+64 98 61.032778 61.032778 61.032778
+64 99 50.447993 50.447993 50.447993
+64 100 41.785165 41.785165 41.785165
+64 101 58.008620 58.008620 58.008620
+65 1 20.615528 20.615528 20.615528
+65 2 58.523500 58.523500 58.523500
+65 3 50.537115 50.537115 50.537115
+65 4 59.615434 59.615434 59.615434
+65 5 55.901699 55.901699 55.901699
+65 6 60.415230 60.415230 60.415230
+65 7 52.478567 52.478567 52.478567
+65 8 54.083269 54.083269 54.083269
+65 9 58.309519 58.309519 58.309519
+65 10 35.355339 35.355339 35.355339
+65 11 36.400549 36.400549 36.400549
+65 12 38.327536 38.327536 38.327536
+65 13 39.924930 39.924930 39.924930
+65 14 40.311289 40.311289 40.311289
+65 15 42.720019 42.720019 42.720019
+65 16 44.147480 44.147480 44.147480
+65 17 46.097722 46.097722 46.097722
+65 18 47.434165 47.434165 47.434165
+65 19 25.019992 25.019992 25.019992
+65 20 20.223748 20.223748 20.223748
+65 21 15.297059 15.297059 15.297059
+65 22 25.495098 25.495098 25.495098
+65 23 15.811388 15.811388 15.811388
+65 24 25.961510 25.961510 25.961510
+65 25 16.552945 16.552945 16.552945
+65 26 26.925824 26.925824 26.925824
+65 27 50.000000 50.000000 50.000000
+65 28 50.249378 50.249378 50.249378
+65 29 47.000000 47.000000 47.000000
+65 30 45.276926 45.276926 45.276926
+65 31 43.000000 43.000000 43.000000
+65 32 43.289722 43.289722 43.289722
+65 33 42.000000 42.000000 42.000000
+65 34 40.311289 40.311289 40.311289
+65 35 40.311289 40.311289 40.311289
+65 36 59.236813 59.236813 59.236813
+65 37 58.523500 58.523500 58.523500
+65 38 55.713553 55.713553 55.713553
+65 39 52.810984 52.810984 52.810984
+65 40 52.201533 52.201533 52.201533
+65 41 57.008771 57.008771 57.008771
+65 42 46.840154 46.840154 46.840154
+65 43 50.990195 50.990195 50.990195
+65 44 55.901699 55.901699 55.901699
+65 45 52.952809 52.952809 52.952809
+65 46 57.697487 57.697487 57.697487
+65 47 56.824291 56.824291 56.824291
+65 48 45.541190 45.541190 45.541190
+65 49 25.179357 25.179357 25.179357
+65 50 18.248288 18.248288 18.248288
+65 51 27.459060 27.459060 27.459060
+65 52 14.142136 14.142136 14.142136
+65 53 20.000000 20.000000 20.000000
+65 54 32.015621 32.015621 32.015621
+65 55 31.622777 31.622777 31.622777
+65 56 33.541020 33.541020 33.541020
+65 57 7.071068 7.071068 7.071068
+65 58 15.811388 15.811388 15.811388
+65 59 36.055513 36.055513 36.055513
+65 60 36.400549 36.400549 36.400549
+65 61 42.426407 42.426407 42.426407
+65 62 35.000000 35.000000 35.000000
+65 63 20.615528 20.615528 20.615528
+65 64 22.360680 22.360680 22.360680
+65 66 14.142136 14.142136 14.142136
+65 67 8.062258 8.062258 8.062258
+65 68 22.472205 22.472205 22.472205
+65 69 30.413813 30.413813 30.413813
+65 70 26.076810 26.076810 26.076810
+65 71 40.261644 40.261644 40.261644
+65 72 32.015621 32.015621 32.015621
+65 73 39.357337 39.357337 39.357337
+65 74 52.430907 52.430907 52.430907
+65 75 26.925824 26.925824 26.925824
+65 76 47.169906 47.169906 47.169906
+65 77 23.430749 23.430749 23.430749
+65 78 34.828150 34.828150 34.828150
+65 79 45.221676 45.221676 45.221676
+65 80 54.451814 54.451814 54.451814
+65 81 17.117243 17.117243 17.117243
+65 82 28.284271 28.284271 28.284271
+65 83 22.203603 22.203603 22.203603
+65 84 8.062258 8.062258 8.062258
+65 85 12.041595 12.041595 12.041595
+65 86 19.313208 19.313208 19.313208
+65 87 24.738634 24.738634 24.738634
+65 88 33.541020 33.541020 33.541020
+65 89 35.000000 35.000000 35.000000
+65 90 33.301652 33.301652 33.301652
+65 91 18.788294 18.788294 18.788294
+65 92 12.649111 12.649111 12.649111
+65 93 15.264338 15.264338 15.264338
+65 94 27.202941 27.202941 27.202941
+65 95 21.633308 21.633308 21.633308
+65 96 13.038405 13.038405 13.038405
+65 97 26.000000 26.000000 26.000000
+65 98 42.720019 42.720019 42.720019
+65 99 29.068884 29.068884 29.068884
+65 100 19.646883 19.646883 19.646883
+65 101 39.560081 39.560081 39.560081
+66 1 11.180340 11.180340 11.180340
+66 2 46.097722 46.097722 46.097722
+66 3 37.336309 37.336309 37.336309
+66 4 46.840154 46.840154 46.840154
+66 5 42.720019 42.720019 42.720019
+66 6 47.434165 47.434165 47.434165
+66 7 38.910153 38.910153 38.910153
+66 8 40.311289 40.311289 40.311289
+66 9 44.721360 44.721360 44.721360
+66 10 25.495098 25.495098 25.495098
+66 11 25.000000 25.000000 25.000000
+66 12 27.000000 27.000000 27.000000
+66 13 27.459060 27.459060 27.459060
+66 14 30.413813 30.413813 30.413813
+66 15 30.413813 30.413813 30.413813
+66 16 33.000000 33.000000 33.000000
+66 17 35.000000 35.000000 35.000000
+66 18 35.355339 35.355339 35.355339
+66 19 36.138622 36.138622 36.138622
+66 20 30.805844 30.805844 30.805844
+66 21 25.961510 25.961510 25.961510
+66 22 35.355339 35.355339 35.355339
+66 23 25.495098 25.495098 25.495098
+66 24 35.128336 35.128336 35.128336
+66 25 25.179357 25.179357 25.179357
+66 26 35.000000 35.000000 35.000000
+66 27 60.827625 60.827625 60.827625
+66 28 60.207973 60.207973 60.207973
+66 29 57.870545 57.870545 57.870545
+66 30 55.226805 55.226805 55.226805
+66 31 53.935146 53.935146 53.935146
+66 32 53.235327 53.235327 53.235327
+66 33 52.952809 52.952809 52.952809
+66 34 52.201533 52.201533 52.201533
+66 35 50.249378 50.249378 50.249378
+66 36 55.217751 55.217751 55.217751
+66 37 54.083269 54.083269 54.083269
+66 38 51.613952 51.613952 51.613952
+66 39 48.259714 48.259714 48.259714
+66 40 47.169906 47.169906 47.169906
+66 41 51.478151 51.478151 51.478151
+66 42 41.880783 41.880783 41.880783
+66 43 44.721360 44.721360 44.721360
+66 44 49.244289 49.244289 49.244289
+66 45 46.518813 46.518813 46.518813
+66 46 44.598206 44.598206 44.598206
+66 47 43.462628 43.462628 43.462628
+66 48 33.376639 33.376639 33.376639
+66 49 35.693137 35.693137 35.693137
+66 50 28.861739 28.861739 28.861739
+66 51 37.336309 37.336309 37.336309
+66 52 28.284271 28.284271 28.284271
+66 53 14.142136 14.142136 14.142136
+66 54 18.027756 18.027756 18.027756
+66 55 28.284271 28.284271 28.284271
+66 56 20.615528 20.615528 20.615528
+66 57 15.811388 15.811388 15.811388
+66 58 15.811388 15.811388 15.811388
+66 59 36.055513 36.055513 36.055513
+66 60 32.015621 32.015621 32.015621
+66 61 28.284271 28.284271 28.284271
+66 62 26.925824 26.925824 26.925824
+66 63 30.413813 30.413813 30.413813
+66 64 36.055513 36.055513 36.055513
+66 65 14.142136 14.142136 14.142136
+66 67 6.708204 6.708204 6.708204
+66 68 29.068884 29.068884 29.068884
+66 69 20.615528 20.615528 20.615528
+66 70 12.649111 12.649111 12.649111
+66 71 29.000000 29.000000 29.000000
+66 72 33.541020 33.541020 33.541020
+66 73 37.536649 37.536649 37.536649
+66 74 38.587563 38.587563 38.587563
+66 75 25.000000 25.000000 25.000000
+66 76 46.097722 46.097722 46.097722
+66 77 37.536649 37.536649 37.536649
+66 78 38.897301 38.897301 38.897301
+66 79 31.384710 31.384710 31.384710
+66 80 40.311289 40.311289 40.311289
+66 81 13.892444 13.892444 13.892444
+66 82 22.803509 22.803509 22.803509
+66 83 8.544004 8.544004 8.544004
+66 84 9.219544 9.219544 9.219544
+66 85 24.596748 24.596748 24.596748
+66 86 32.756679 32.756679 32.756679
+66 87 21.260292 21.260292 21.260292
+66 88 28.017851 28.017851 28.017851
+66 89 21.095023 21.095023 21.095023
+66 90 47.423623 47.423623 47.423623
+66 91 7.280110 7.280110 7.280110
+66 92 14.142136 14.142136 14.142136
+66 93 18.248288 18.248288 18.248288
+66 94 28.635642 28.635642 28.635642
+66 95 23.409400 23.409400 23.409400
+66 96 21.213203 21.213203 21.213203
+66 97 24.413111 24.413111 24.413111
+66 98 38.013156 38.013156 38.013156
+66 99 15.000000 15.000000 15.000000
+66 100 10.295630 10.295630 10.295630
+66 101 27.294688 27.294688 27.294688
+67 1 13.038405 13.038405 13.038405
+67 2 50.596443 50.596443 50.596443
+67 3 42.485292 42.485292 42.485292
+67 4 51.623638 51.623638 51.623638
+67 5 47.853944 47.853944 47.853944
+67 6 52.392748 52.392748 52.392748
+67 7 44.418465 44.418465 44.418465
+67 8 46.043458 46.043458 46.043458
+67 9 50.249378 50.249378 50.249378
+67 10 31.064449 31.064449 31.064449
+67 11 31.144823 31.144823 31.144823
+67 12 33.136083 33.136083 33.136083
+67 13 33.955854 33.955854 33.955854
+67 14 36.055513 36.055513 36.055513
+67 15 36.878178 36.878178 36.878178
+67 16 39.115214 39.115214 39.115214
+67 17 41.109610 41.109610 41.109610
+67 18 41.773197 41.773197 41.773197
+67 19 32.140317 32.140317 32.140317
+67 20 27.018512 27.018512 27.018512
+67 21 22.022716 22.022716 22.022716
+67 22 32.015621 32.015621 32.015621
+67 23 22.022716 22.022716 22.022716
+67 24 32.140317 32.140317 32.140317
+67 25 22.203603 22.203603 22.203603
+67 26 32.557641 32.557641 32.557641
+67 27 54.451814 54.451814 54.451814
+67 28 54.037024 54.037024 54.037024
+67 29 51.478151 51.478151 51.478151
+67 30 49.040799 49.040799 49.040799
+67 31 47.518417 47.518417 47.518417
+67 32 47.042534 47.042534 47.042534
+67 33 46.529560 46.529560 46.529560
+67 34 45.607017 45.607017 45.607017
+67 35 44.045431 44.045431 44.045431
+67 36 54.589376 54.589376 54.589376
+67 37 53.665631 53.665631 53.665631
+67 38 51.000000 51.000000 51.000000
+67 39 47.853944 47.853944 47.853944
+67 40 47.010637 47.010637 47.010637
+67 41 51.623638 51.623638 51.623638
+67 42 41.629317 41.629317 41.629317
+67 43 45.221676 45.221676 45.221676
+67 44 50.000000 50.000000 50.000000
+67 45 47.127487 47.127487 47.127487
+67 46 49.658836 49.658836 49.658836
+67 47 48.764741 48.764741 48.764741
+67 48 39.812058 39.812058 39.812058
+67 49 32.015621 32.015621 32.015621
+67 50 25.019992 25.019992 25.019992
+67 51 31.064449 31.064449 31.064449
+67 52 22.022716 22.022716 22.022716
+67 53 17.464249 17.464249 17.464249
+67 54 24.698178 24.698178 24.698178
+67 55 26.925824 26.925824 26.925824
+67 56 25.495098 25.495098 25.495098
+67 57 9.219544 9.219544 9.219544
+67 58 16.278821 16.278821 16.278821
+67 59 37.483330 37.483330 37.483330
+67 60 35.355339 35.355339 35.355339
+67 61 34.713110 34.713110 34.713110
+67 62 28.284271 28.284271 28.284271
+67 63 24.083189 24.083189 24.083189
+67 64 29.410882 29.410882 29.410882
+67 65 8.062258 8.062258 8.062258
+67 66 6.708204 6.708204 6.708204
+67 68 23.537205 23.537205 23.537205
+67 69 23.021729 23.021729 23.021729
+67 70 18.027756 18.027756 18.027756
+67 71 32.557641 32.557641 32.557641
+67 72 30.000000 30.000000 30.000000
+67 73 35.608988 35.608988 35.608988
+67 74 45.276926 45.276926 45.276926
+67 75 27.018512 27.018512 27.018512
+67 76 48.166378 48.166378 48.166378
+67 77 31.400637 31.400637 31.400637
+67 78 38.470768 38.470768 38.470768
+67 79 38.078866 38.078866 38.078866
+67 80 46.754679 46.754679 46.754679
+67 81 11.661904 11.661904 11.661904
+67 82 22.472205 22.472205 22.472205
+67 83 15.231546 15.231546 15.231546
+67 84 7.211103 7.211103 7.211103
+67 85 17.888544 17.888544 17.888544
+67 86 26.076810 26.076810 26.076810
+67 87 23.853721 23.853721 23.853721
+67 88 31.780497 31.780497 31.780497
+67 89 27.018512 27.018512 27.018512
+67 90 41.231056 41.231056 41.231056
+67 91 10.770330 10.770330 10.770330
+67 92 9.433981 9.433981 9.433981
+67 93 13.416408 13.416408 13.416408
+67 94 25.000000 25.000000 25.000000
+67 95 19.416488 19.416488 19.416488
+67 96 15.000000 15.000000 15.000000
+67 97 22.022716 22.022716 22.022716
+67 98 41.593269 41.593269 41.593269
+67 99 21.213203 21.213203 21.213203
+67 100 15.132746 15.132746 15.132746
+67 101 31.622777 31.622777 31.622777
+68 1 25.298221 25.298221 25.298221
+68 2 58.051701 58.051701 58.051701
+68 3 53.413481 53.413481 53.413481
+68 4 60.108236 60.108236 60.108236
+68 5 58.137767 58.137767 58.137767
+68 6 61.522354 61.522354 61.522354
+68 7 56.612719 56.612719 56.612719
+68 8 59.076222 59.076222 59.076222
+68 9 62.008064 62.008064 62.008064
+68 10 54.451814 54.451814 54.451814
+68 11 54.037024 54.037024 54.037024
+68 12 56.035703 56.035703 56.035703
+68 13 56.080300 56.080300 56.080300
+68 14 59.413803 59.413803 59.413803
+68 15 59.076222 59.076222 59.076222
+68 16 62.032250 62.032250 62.032250
+68 17 64.031242 64.031242 64.031242
+68 18 64.070274 64.070274 64.070274
+68 19 42.059482 42.059482 42.059482
+68 20 38.832976 38.832976 38.832976
+68 21 34.828150 34.828150 34.828150
+68 22 44.102154 44.102154 44.102154
+68 23 36.124784 36.124784 36.124784
+68 24 45.221676 45.221676 45.221676
+68 25 37.483330 37.483330 37.483330
+68 26 47.010637 47.010637 47.010637
+68 27 33.241540 33.241540 33.241540
+68 28 31.780497 31.780497 31.780497
+68 29 30.463092 30.463092 30.463092
+68 30 26.925824 26.925824 26.925824
+68 31 26.832816 26.832816 26.832816
+68 32 25.000000 25.000000 25.000000
+68 33 25.942244 25.942244 25.942244
+68 34 27.018512 27.018512 27.018512
+68 35 22.135944 22.135944 22.135944
+68 36 43.104524 43.104524 43.104524
+68 37 43.011626 43.011626 43.011626
+68 38 40.012498 40.012498 40.012498
+68 39 38.052595 38.052595 38.052595
+68 40 38.209946 38.209946 38.209946
+68 41 43.185646 43.185646 43.185646
+68 42 33.541020 33.541020 33.541020
+68 43 39.051248 39.051248 39.051248
+68 44 43.931765 43.931765 43.931765
+68 45 41.000000 41.000000 41.000000
+68 46 59.464275 59.464275 59.464275
+68 47 59.665736 59.665736 59.665736
+68 48 62.072538 62.072538 62.072538
+68 49 43.046487 43.046487 43.046487
+68 50 37.202150 37.202150 37.202150
+68 51 10.630146 10.630146 10.630146
+68 52 23.769729 23.769729 23.769729
+68 53 40.804412 40.804412 40.804412
+68 54 44.721360 44.721360 44.721360
+68 55 20.124612 20.124612 20.124612
+68 56 38.470768 38.470768 38.470768
+68 57 15.652476 15.652476 15.652476
+68 58 38.013156 38.013156 38.013156
+68 59 58.523500 58.523500 58.523500
+68 60 58.309519 58.309519 58.309519
+68 61 52.201533 52.201533 52.201533
+68 62 29.832868 29.832868 29.832868
+68 63 7.071068 7.071068 7.071068
+68 64 22.022716 22.022716 22.022716
+68 65 22.472205 22.472205 22.472205
+68 66 29.068884 29.068884 29.068884
+68 67 23.537205 23.537205 23.537205
+68 69 30.000000 30.000000 30.000000
+68 70 34.481879 34.481879 34.481879
+68 71 39.623226 39.623226 39.623226
+68 72 13.038405 13.038405 13.038405
+68 73 23.021729 23.021729 23.021729
+68 74 64.560050 64.560050 64.560050
+68 75 49.193496 49.193496 49.193496
+68 76 69.641941 69.641941 69.641941
+68 77 30.265492 30.265492 30.265492
+68 78 56.586217 56.586217 56.586217
+68 79 57.723479 57.723479 57.723479
+68 80 63.560994 63.560994 63.560994
+68 81 17.720045 17.720045 17.720045
+68 82 21.931712 21.931712 21.931712
+68 83 37.013511 37.013511 37.013511
+68 84 29.154759 29.154759 29.154759
+68 85 14.764823 14.764823 14.764823
+68 86 19.026298 19.026298 19.026298
+68 87 46.615448 46.615448 46.615448
+68 88 55.027266 55.027266 55.027266
+68 89 43.081318 43.081318 43.081318
+68 90 37.121422 37.121422 37.121422
+68 91 27.459060 27.459060 27.459060
+68 92 15.000000 15.000000 15.000000
+68 93 11.045361 11.045361 11.045361
+68 94 10.440307 10.440307 10.440307
+68 95 9.219544 9.219544 9.219544
+68 96 9.433981 9.433981 9.433981
+68 97 15.000000 15.000000 15.000000
+68 98 64.621978 64.621978 64.621978
+68 99 39.293765 39.293765 39.293765
+68 100 38.639358 38.639358 38.639358
+68 101 41.400483 41.400483 41.400483
+69 1 10.000000 10.000000 10.000000
+69 2 29.154759 29.154759 29.154759
+69 3 23.430749 23.430749 23.430749
+69 4 30.805844 30.805844 30.805844
+69 5 28.284271 28.284271 28.284271
+69 6 32.015621 32.015621 32.015621
+69 7 26.627054 26.627054 26.627054
+69 8 29.154759 29.154759 29.154759
+69 9 32.015621 32.015621 32.015621
+69 10 39.051248 39.051248 39.051248
+69 11 36.055513 36.055513 36.055513
+69 12 37.735925 37.735925 37.735925
+69 13 35.341194 35.341194 35.341194
+69 14 43.011626 43.011626 43.011626
+69 15 38.078866 38.078866 38.078866
+69 16 42.941821 42.941821 42.941821
+69 17 44.721360 44.721360 44.721360
+69 18 42.720019 42.720019 42.720019
+69 19 55.145263 55.145263 55.145263
+69 20 50.039984 50.039984 50.039984
+69 21 45.044423 45.044423 45.044423
+69 22 55.000000 55.000000 55.000000
+69 23 45.000000 45.000000 45.000000
+69 24 55.036352 55.036352 55.036352
+69 25 45.044423 45.044423 45.044423
+69 26 55.226805 55.226805 55.226805
+69 27 62.649820 62.649820 62.649820
+69 28 60.415230 60.415230 60.415230
+69 29 60.033324 60.033324 60.033324
+69 30 55.901699 55.901699 55.901699
+69 31 56.603887 56.603887 56.603887
+69 32 54.120237 54.120237 54.120237
+69 33 55.758407 55.758407 55.758407
+69 34 57.008771 57.008771 57.008771
+69 35 51.478151 51.478151 51.478151
+69 36 36.796739 36.796739 36.796739
+69 37 35.355339 35.355339 35.355339
+69 38 33.301652 33.301652 33.301652
+69 39 29.732137 29.732137 29.732137
+69 40 28.284271 28.284271 28.284271
+69 41 32.015621 32.015621 32.015621
+69 42 23.430749 23.430749 23.430749
+69 43 25.000000 25.000000 25.000000
+69 44 29.154759 29.154759 29.154759
+69 45 26.627054 26.627054 26.627054
+69 46 29.732137 29.732137 29.732137
+69 47 29.732137 29.732137 29.732137
+69 48 40.853396 40.853396 40.853396
+69 49 55.036352 55.036352 55.036352
+69 50 48.041649 48.041649 48.041649
+69 51 40.607881 40.607881 40.607881
+69 52 42.720019 42.720019 42.720019
+69 53 33.541020 33.541020 33.541020
+69 54 22.360680 22.360680 22.360680
+69 55 15.000000 15.000000 15.000000
+69 56 10.000000 10.000000 10.000000
+69 57 26.925824 26.925824 26.925824
+69 58 36.400549 36.400549 36.400549
+69 59 55.901699 55.901699 55.901699
+69 60 50.000000 50.000000 50.000000
+69 61 25.000000 25.000000 25.000000
+69 62 7.071068 7.071068 7.071068
+69 63 35.355339 35.355339 35.355339
+69 64 47.169906 47.169906 47.169906
+69 65 30.413813 30.413813 30.413813
+69 66 20.615528 20.615528 20.615528
+69 67 23.021729 23.021729 23.021729
+69 68 30.000000 30.000000 30.000000
+69 70 12.041595 12.041595 12.041595
+69 71 10.295630 10.295630 10.295630
+69 72 25.495098 25.495098 25.495098
+69 73 23.537205 23.537205 23.537205
+69 74 38.000000 38.000000 38.000000
+69 75 44.721360 44.721360 44.721360
+69 76 65.192024 65.192024 65.192024
+69 77 52.000000 52.000000 52.000000
+69 78 59.481089 59.481089 59.481089
+69 79 32.249031 32.249031 32.249031
+69 80 34.928498 34.928498 34.928498
+69 81 14.764823 14.764823 14.764823
+69 82 9.219544 9.219544 9.219544
+69 83 21.400935 21.400935 21.400935
+69 84 29.154759 29.154759 29.154759
+69 85 35.355339 35.355339 35.355339
+69 86 43.566042 43.566042 43.566042
+69 87 40.706265 40.706265 40.706265
+69 88 45.607017 45.607017 45.607017
+69 89 16.124515 16.124515 16.124515
+69 90 61.269895 61.269895 61.269895
+69 91 13.341664 13.341664 13.341664
+69 92 20.124612 20.124612 20.124612
+69 93 21.400935 21.400935 21.400935
+69 94 22.472205 22.472205 22.472205
+69 95 20.808652 20.808652 20.808652
+69 96 28.017851 28.017851 28.017851
+69 97 16.155494 16.155494 16.155494
+69 98 55.317267 55.317267 55.317267
+69 99 16.124515 16.124515 16.124515
+69 100 28.653098 28.653098 28.653098
+69 101 11.401754 11.401754 11.401754
+70 1 9.219544 9.219544 9.219544
+70 2 33.541020 33.541020 33.541020
+70 3 24.698178 24.698178 24.698178
+70 4 34.205263 34.205263 34.205263
+70 5 30.083218 30.083218 30.083218
+70 6 34.785054 34.785054 34.785054
+70 7 26.419690 26.419690 26.419690
+70 8 28.017851 28.017851 28.017851
+70 9 32.249031 32.249031 32.249031
+70 10 27.018512 27.018512 27.018512
+70 11 24.186773 24.186773 24.186773
+70 12 25.942244 25.942244 25.942244
+70 13 24.041631 24.041631 24.041631
+70 14 31.064449 31.064449 31.064449
+70 15 26.925824 26.925824 26.925824
+70 16 31.384710 31.384710 31.384710
+70 17 33.241540 33.241540 33.241540
+70 18 31.780497 31.780497 31.780497
+70 19 48.764741 48.764741 48.764741
+70 20 43.416587 43.416587 43.416587
+70 21 38.600518 38.600518 38.600518
+70 22 47.853944 47.853944 47.853944
+70 23 38.078866 38.078866 38.078866
+70 24 47.518417 47.518417 47.518417
+70 25 37.656341 37.656341 37.656341
+70 26 47.169906 47.169906 47.169906
+70 27 67.675697 67.675697 67.675697
+70 28 66.219333 66.219333 66.219333
+70 29 64.845971 64.845971 64.845971
+70 30 61.400326 61.400326 61.400326
+70 31 61.098281 61.098281 61.098281
+70 32 59.481089 59.481089 59.481089
+70 33 60.166436 60.166436 60.166436
+70 34 60.373835 60.373835 60.373835
+70 35 56.612719 56.612719 56.612719
+70 36 48.836462 48.836462 48.836462
+70 37 47.381431 47.381431 47.381431
+70 38 45.343136 45.343136 45.343136
+70 39 41.773197 41.773197 41.773197
+70 40 40.311289 40.311289 40.311289
+70 41 43.931765 43.931765 43.931765
+70 42 35.468296 35.468296 35.468296
+70 43 36.878178 36.878178 36.878178
+70 44 40.804412 40.804412 40.804412
+70 45 38.418745 38.418745 38.418745
+70 46 31.953091 31.953091 31.953091
+70 47 30.870698 30.870698 30.870698
+70 48 29.832868 29.832868 29.832868
+70 49 48.270074 48.270074 48.270074
+70 50 41.484937 41.484937 41.484937
+70 51 44.384682 44.384682 44.384682
+70 52 40.000000 40.000000 40.000000
+70 53 22.803509 22.803509 22.803509
+70 54 11.180340 11.180340 11.180340
+70 55 25.298221 25.298221 25.298221
+70 56 8.062258 8.062258 8.062258
+70 57 25.495098 25.495098 25.495098
+70 58 27.018512 27.018512 27.018512
+70 59 44.944410 44.944410 44.944410
+70 60 38.275318 38.275318 38.275318
+70 61 17.888544 17.888544 17.888544
+70 62 19.104973 19.104973 19.104973
+70 63 38.013156 38.013156 38.013156
+70 64 46.690470 46.690470 46.690470
+70 65 26.076810 26.076810 26.076810
+70 66 12.649111 12.649111 12.649111
+70 67 18.027756 18.027756 18.027756
+70 68 34.481879 34.481879 34.481879
+70 69 12.041595 12.041595 12.041595
+70 71 17.464249 17.464249 17.464249
+70 72 34.132096 34.132096 34.132096
+70 73 34.539832 34.539832 34.539832
+70 74 30.083218 30.083218 30.083218
+70 75 33.837849 33.837849 33.837849
+70 76 53.712196 53.712196 53.712196
+70 77 49.406477 49.406477 49.406477
+70 78 49.648766 49.648766 49.648766
+70 79 23.345235 23.345235 23.345235
+70 80 29.681644 29.681644 29.681644
+70 81 16.763055 16.763055 16.763055
+70 82 18.973666 18.973666 18.973666
+70 83 9.848858 9.848858 9.848858
+70 84 21.840330 21.840330 21.840330
+70 85 34.713110 34.713110 34.713110
+70 86 43.185646 43.185646 43.185646
+70 87 29.732137 29.732137 29.732137
+70 88 33.837849 33.837849 33.837849
+70 89 9.219544 9.219544 9.219544
+70 90 59.203040 59.203040 59.203040
+70 91 7.810250 7.810250 7.810250
+70 92 20.591260 20.591260 20.591260
+70 93 23.769729 23.769729 23.769729
+70 94 30.000000 30.000000 30.000000
+70 95 26.305893 26.305893 26.305893
+70 96 29.154759 29.154759 29.154759
+70 97 24.083189 24.083189 24.083189
+70 98 43.416587 43.416587 43.416587
+70 99 5.000000 5.000000 5.000000
+70 100 17.720045 17.720045 17.720045
+70 101 15.000000 15.000000 15.000000
+71 1 19.646883 19.646883 19.646883
+71 2 18.867962 18.867962 18.867962
+71 3 14.317821 14.317821 14.317821
+71 4 20.615528 20.615528 20.615528
+71 5 18.601075 18.601075 18.601075
+71 6 21.931712 21.931712 21.931712
+71 7 18.027756 18.027756 18.027756
+71 8 20.880613 20.880613 20.880613
+71 9 22.825424 22.825424 22.825424
+71 10 42.201896 42.201896 42.201896
+71 11 38.288379 38.288379 38.288379
+71 12 39.623226 39.623226 39.623226
+71 13 36.124784 36.124784 36.124784
+71 14 45.343136 45.343136 45.343136
+71 15 38.418745 38.418745 38.418745
+71 16 43.931765 43.931765 43.931765
+71 17 45.453273 45.453273 45.453273
+71 18 42.438190 42.438190 42.438190
+71 19 64.629715 64.629715 64.629715
+71 20 59.413803 59.413803 59.413803
+71 21 54.451814 54.451814 54.451814
+71 22 64.195015 64.195015 64.195015
+71 23 54.230987 54.230987 54.230987
+71 24 64.070274 64.070274 64.070274
+71 25 54.083269 54.083269 54.083269
+71 26 64.000000 64.000000 64.000000
+71 27 71.561163 71.561163 71.561163
+71 28 68.963759 68.963759 68.963759
+71 29 69.065187 69.065187 69.065187
+71 30 64.660653 64.660653 64.660653
+71 31 65.802736 65.802736 65.802736
+71 32 62.968246 62.968246 62.968246
+71 33 65.000000 65.000000 65.000000
+71 34 66.603303 66.603303 66.603303
+71 35 60.464866 60.464866 60.464866
+71 36 35.777088 35.777088 35.777088
+71 37 34.000000 34.000000 34.000000
+71 38 32.695565 32.695565 32.695565
+71 39 29.154759 29.154759 29.154759
+71 40 27.313001 27.313001 27.313001
+71 41 29.681644 29.681644 29.681644
+71 42 23.769729 23.769729 23.769729
+71 43 22.825424 22.825424 22.825424
+71 44 25.612497 25.612497 25.612497
+71 45 23.853721 23.853721 23.853721
+71 46 19.849433 19.849433 19.849433
+71 47 20.248457 20.248457 20.248457
+71 48 40.804412 40.804412 40.804412
+71 49 64.381674 64.381674 64.381674
+71 50 57.428216 57.428216 57.428216
+71 51 50.249378 50.249378 50.249378
+71 52 52.924474 52.924474 52.924474
+71 53 40.261644 40.261644 40.261644
+71 54 24.207437 24.207437 24.207437
+71 55 21.931712 21.931712 21.931712
+71 56 10.295630 10.295630 10.295630
+71 57 37.161808 37.161808 37.161808
+71 58 44.283180 44.283180 44.283180
+71 59 62.297673 62.297673 62.297673
+71 60 55.009090 55.009090 55.009090
+71 61 21.931712 21.931712 21.931712
+71 62 10.770330 10.770330 10.770330
+71 63 45.343136 45.343136 45.343136
+71 64 57.454330 57.454330 57.454330
+71 65 40.261644 40.261644 40.261644
+71 66 29.000000 29.000000 29.000000
+71 67 32.557641 32.557641 32.557641
+71 68 39.623226 39.623226 39.623226
+71 69 10.295630 10.295630 10.295630
+71 70 17.464249 17.464249 17.464249
+71 72 33.105891 33.105891 33.105891
+71 73 28.284271 28.284271 28.284271
+71 74 34.205263 34.205263 34.205263
+71 75 51.244512 51.244512 51.244512
+71 76 70.682388 70.682388 70.682388
+71 77 62.241465 62.241465 62.241465
+71 78 67.082039 67.082039 67.082039
+71 79 29.966648 29.966648 29.966648
+71 80 29.017236 29.017236 29.017236
+71 81 25.059928 25.059928 25.059928
+71 82 17.804494 17.804494 17.804494
+71 83 27.202941 27.202941 27.202941
+71 84 38.052595 38.052595 38.052595
+71 85 45.650849 45.650849 45.650849
+71 86 53.851648 53.851648 53.851648
+71 87 47.127487 47.127487 47.127487
+71 88 50.537115 50.537115 50.537115
+71 89 15.556349 15.556349 15.556349
+71 90 71.554175 71.554175 71.554175
+71 91 22.090722 22.090722 22.090722
+71 92 30.413813 30.413813 30.413813
+71 93 31.622777 31.622777 31.622777
+71 94 31.064449 31.064449 31.064449
+71 95 30.413813 30.413813 30.413813
+71 96 38.275318 38.275318 38.275318
+71 97 25.000000 25.000000 25.000000
+71 98 59.682493 59.682493 59.682493
+71 99 19.235384 19.235384 19.235384
+71 100 35.171011 35.171011 35.171011
+71 101 4.472136 4.472136 4.472136
+72 1 25.495098 25.495098 25.495098
+72 2 50.000000 50.000000 50.000000
+72 3 47.423623 47.423623 47.423623
+72 4 52.430907 52.430907 52.430907
+72 5 51.478151 51.478151 51.478151
+72 6 54.083269 54.083269 54.083269
+72 7 51.078371 51.078371 51.078371
+72 8 53.851648 53.851648 53.851648
+72 9 55.901699 55.901699 55.901699
+72 10 58.523500 58.523500 58.523500
+72 11 57.008771 57.008771 57.008771
+72 12 58.940648 58.940648 58.940648
+72 13 57.870545 57.870545 57.870545
+72 14 63.245553 63.245553 63.245553
+72 15 60.827625 60.827625 60.827625
+72 16 64.761099 64.761099 64.761099
+72 17 66.708320 66.708320 66.708320
+72 18 65.764732 65.764732 65.764732
+72 19 54.230987 54.230987 54.230987
+72 20 50.537115 50.537115 50.537115
+72 21 46.141088 46.141088 46.141088
+72 22 55.901699 55.901699 55.901699
+72 23 47.169906 47.169906 47.169906
+72 24 56.824291 56.824291 56.824291
+72 25 48.259714 48.259714 48.259714
+72 26 58.309519 58.309519 58.309519
+72 27 39.051248 39.051248 39.051248
+72 28 36.055513 36.055513 36.055513
+72 29 36.796739 36.796739 36.796739
+72 30 32.015621 32.015621 32.015621
+72 31 33.970576 33.970576 33.970576
+72 32 30.479501 30.479501 30.479501
+72 33 33.301652 33.301652 33.301652
+72 34 36.055513 36.055513 36.055513
+72 35 28.284271 28.284271 28.284271
+72 36 30.066593 30.066593 30.066593
+72 37 30.000000 30.000000 30.000000
+72 38 27.000000 27.000000 27.000000
+72 39 25.179357 25.179357 25.179357
+72 40 25.495098 25.495098 25.495098
+72 41 30.413813 30.413813 30.413813
+72 42 21.189620 21.189620 21.189620
+72 43 26.925824 26.925824 26.925824
+72 44 31.622777 31.622777 31.622777
+72 45 28.792360 28.792360 28.792360
+72 46 52.478567 52.478567 52.478567
+72 47 53.235327 53.235327 53.235327
+72 48 63.788714 63.788714 63.788714
+72 49 55.036352 55.036352 55.036352
+72 50 48.764741 48.764741 48.764741
+72 51 21.189620 21.189620 21.189620
+72 52 36.400549 36.400549 36.400549
+72 53 47.169906 47.169906 47.169906
+72 54 45.276926 45.276926 45.276926
+72 55 11.180340 11.180340 11.180340
+72 56 35.355339 35.355339 35.355339
+72 57 25.000000 25.000000 25.000000
+72 58 46.097722 46.097722 46.097722
+72 59 67.268120 67.268120 67.268120
+72 60 65.192024 65.192024 65.192024
+72 61 50.249378 50.249378 50.249378
+72 62 22.360680 22.360680 22.360680
+72 63 20.000000 20.000000 20.000000
+72 64 35.000000 35.000000 35.000000
+72 65 32.015621 32.015621 32.015621
+72 66 33.541020 33.541020 33.541020
+72 67 30.000000 30.000000 30.000000
+72 68 13.038405 13.038405 13.038405
+72 69 25.495098 25.495098 25.495098
+72 70 34.132096 34.132096 34.132096
+72 71 33.105891 33.105891 33.105891
+72 73 10.198039 10.198039 10.198039
+72 74 63.198101 63.198101 63.198101
+72 75 57.008771 57.008771 57.008771
+72 76 78.102497 78.102497 78.102497
+72 77 43.289722 43.289722 43.289722
+72 78 66.843100 66.843100 66.843100
+72 79 57.008771 57.008771 57.008771
+72 80 60.415230 60.415230 60.415230
+72 81 19.697716 19.697716 19.697716
+72 82 16.278821 16.278821 16.278821
+72 83 39.849718 39.849718 39.849718
+72 84 36.878178 36.878178 36.878178
+72 85 27.202941 27.202941 27.202941
+72 86 32.062439 32.062439 32.062439
+72 87 53.823787 53.823787 53.823787
+72 88 61.400326 61.400326 61.400326
+72 89 41.109610 41.109610 41.109610
+72 90 50.039984 50.039984 50.039984
+72 91 29.120440 29.120440 29.120440
+72 92 20.615528 20.615528 20.615528
+72 93 16.970563 16.970563 16.970563
+72 94 5.000000 5.000000 5.000000
+72 95 10.630146 10.630146 10.630146
+72 96 20.124612 20.124612 20.124612
+72 97 10.049876 10.049876 10.049876
+72 98 71.344236 71.344236 71.344236
+72 99 39.115214 39.115214 39.115214
+72 100 43.829214 43.829214 43.829214
+72 101 36.055513 36.055513 36.055513
+73 1 27.459060 27.459060 27.459060
+73 2 42.941821 42.941821 42.941821
+73 3 42.201896 42.201896 42.201896
+73 4 45.617979 45.617979 45.617979
+73 5 45.541190 45.541190 45.541190
+73 6 47.423623 47.423623 47.423623
+73 7 46.097722 46.097722 46.097722
+73 8 49.030603 49.030603 49.030603
+73 9 50.289164 50.289164 50.289164
+73 10 60.901560 60.901560 60.901560
+73 11 58.600341 58.600341 58.600341
+73 12 60.415230 60.415230 60.415230
+73 13 58.523500 58.523500 58.523500
+73 14 65.299311 65.299311 65.299311
+73 15 61.351447 61.351447 61.351447
+73 16 65.924199 65.924199 65.924199
+73 17 67.779053 67.779053 67.779053
+73 18 66.098411 66.098411 66.098411
+73 19 62.936476 62.936476 62.936476
+73 20 58.872744 58.872744 58.872744
+73 21 54.230987 54.230987 54.230987
+73 22 64.257295 64.257295 64.257295
+73 23 55.036352 55.036352 55.036352
+73 24 65.000000 65.000000 65.000000
+73 25 55.901699 55.901699 55.901699
+73 26 66.211781 66.211781 66.211781
+73 27 47.423623 47.423623 47.423623
+73 28 43.863424 43.863424 43.863424
+73 29 45.453273 45.453273 45.453273
+73 30 40.360872 40.360872 40.360872
+73 31 43.011626 43.011626 43.011626
+73 32 39.051248 39.051248 39.051248
+73 33 42.438190 42.438190 42.438190
+73 34 45.650849 45.650849 45.650849
+73 35 37.202150 37.202150 37.202150
+73 36 20.396078 20.396078 20.396078
+73 37 20.099751 20.099751 20.099751
+73 38 17.117243 17.117243 17.117243
+73 39 15.033296 15.033296 15.033296
+73 40 15.297059 15.297059 15.297059
+73 41 20.223748 20.223748 20.223748
+73 42 11.180340 11.180340 11.180340
+73 43 17.000000 17.000000 17.000000
+73 44 21.540659 21.540659 21.540659
+73 45 18.788294 18.788294 18.788294
+73 46 46.238512 46.238512 46.238512
+73 47 47.434165 47.434165 47.434165
+73 48 64.195015 64.195015 64.195015
+73 49 63.568860 63.568860 63.568860
+73 50 57.008771 57.008771 57.008771
+73 51 31.320920 31.320920 31.320920
+73 52 45.705580 45.705580 45.705580
+73 53 51.662365 51.662365 51.662365
+73 54 45.541190 45.541190 45.541190
+73 55 9.433981 9.433981 9.433981
+73 56 33.376639 33.376639 33.376639
+73 57 32.695565 32.695565 32.695565
+73 58 51.855569 51.855569 51.855569
+73 59 73.000000 73.000000 73.000000
+73 60 69.526973 69.526973 69.526973
+73 61 48.259714 48.259714 48.259714
+73 62 18.000000 18.000000 18.000000
+73 63 30.066593 30.066593 30.066593
+73 64 45.044423 45.044423 45.044423
+73 65 39.357337 39.357337 39.357337
+73 66 37.536649 37.536649 37.536649
+73 67 35.608988 35.608988 35.608988
+73 68 23.021729 23.021729 23.021729
+73 69 23.537205 23.537205 23.537205
+73 70 34.539832 34.539832 34.539832
+73 71 28.284271 28.284271 28.284271
+73 72 10.198039 10.198039 10.198039
+73 74 61.204575 61.204575 61.204575
+73 75 62.241465 62.241465 62.241465
+73 76 83.450584 83.450584 83.450584
+73 77 53.084838 53.084838 53.084838
+73 78 73.783467 73.783467 73.783467
+73 79 55.731499 55.731499 55.731499
+73 80 57.078893 57.078893 57.078893
+73 81 24.083189 24.083189 24.083189
+73 82 15.652476 15.652476 15.652476
+73 83 42.190046 42.190046 42.190046
+73 84 42.801869 42.801869 42.801869
+73 85 36.496575 36.496575 36.496575
+73 86 42.000000 42.000000 42.000000
+73 87 58.694122 58.694122 58.694122
+73 88 65.436993 65.436993 65.436993
+73 89 39.623226 39.623226 39.623226
+73 90 60.133186 60.133186 60.133186
+73 91 31.622777 31.622777 31.622777
+73 92 26.925824 26.925824 26.925824
+73 93 24.166092 24.166092 24.166092
+73 94 13.152946 13.152946 13.152946
+73 95 18.027756 18.027756 18.027756
+73 96 28.861739 28.861739 28.861739
+73 97 13.601471 13.601471 13.601471
+73 98 75.432089 75.432089 75.432089
+73 99 39.217343 39.217343 39.217343
+73 100 47.634021 47.634021 47.634021
+73 101 32.062439 32.062439 32.062439
+74 1 39.293765 39.293765 39.293765
+74 2 33.970576 33.970576 33.970576
+74 3 25.000000 25.000000 25.000000
+74 4 32.015621 32.015621 32.015621
+74 5 26.907248 26.907248 26.907248
+74 6 30.805844 30.805844 30.805844
+74 7 21.931712 21.931712 21.931712
+74 8 19.849433 19.849433 19.849433
+74 9 23.853721 23.853721 23.853721
+74 10 26.248809 26.248809 26.248809
+74 11 21.540659 21.540659 21.540659
+74 12 20.880613 20.880613 20.880613
+74 13 16.155494 16.155494 16.155494
+74 14 25.179357 25.179357 25.179357
+74 15 15.297059 15.297059 15.297059
+74 16 20.000000 20.000000 20.000000
+74 17 20.099751 20.099751 20.099751
+74 18 15.132746 15.132746 15.132746
+74 19 69.202601 69.202601 69.202601
+74 20 64.031242 64.031242 64.031242
+74 21 60.207973 60.207973 60.207973
+74 22 66.850580 66.850580 66.850580
+74 23 58.898217 58.898217 58.898217
+74 24 65.734314 65.734314 65.734314
+74 25 57.628118 57.628118 57.628118
+74 26 64.140471 64.140471 64.140471
+74 27 97.718985 97.718985 97.718985
+74 28 96.301610 96.301610 96.301610
+74 29 94.868330 94.868330 94.868330
+74 30 91.482239 91.482239 91.482239
+74 31 91.082380 91.082380 91.082380
+74 32 89.560036 89.560036 89.560036
+74 33 90.138782 90.138782 90.138782
+74 34 90.077744 90.077744 90.077744
+74 35 86.683332 86.683332 86.683332
+74 36 69.641941 69.641941 69.641941
+74 37 67.779053 67.779053 67.779053
+74 38 66.730802 66.730802 66.730802
+74 39 63.245553 63.245553 63.245553
+74 40 61.351447 61.351447 61.351447
+74 41 63.158531 63.158531 63.158531
+74 42 57.974132 57.974132 57.974132
+74 43 56.648036 56.648036 56.648036
+74 44 58.600341 58.600341 58.600341
+74 45 57.384667 57.384667 57.384667
+74 46 28.425341 28.425341 28.425341
+74 47 25.612497 25.612497 25.612497
+74 48 15.000000 15.000000 15.000000
+74 49 68.007353 68.007353 68.007353
+74 50 62.481997 62.481997 62.481997
+74 51 74.330344 74.330344 74.330344
+74 52 66.400301 66.400301 66.400301
+74 53 37.802116 37.802116 37.802116
+74 54 20.591260 20.591260 20.591260
+74 55 53.000000 53.000000 53.000000
+74 56 28.000000 28.000000 28.000000
+74 57 54.120237 54.120237 54.120237
+74 58 44.821870 44.821870 44.821870
+74 59 51.662365 51.662365 51.662365
+74 60 40.792156 40.792156 40.792156
+74 61 13.000000 13.000000 13.000000
+74 62 43.289722 43.289722 43.289722
+74 63 67.779053 67.779053 67.779053
+74 64 74.625733 74.625733 74.625733
+74 65 52.430907 52.430907 52.430907
+74 66 38.587563 38.587563 38.587563
+74 67 45.276926 45.276926 45.276926
+74 68 64.560050 64.560050 64.560050
+74 69 38.000000 38.000000 38.000000
+74 70 30.083218 30.083218 30.083218
+74 71 34.205263 34.205263 34.205263
+74 72 63.198101 63.198101 63.198101
+74 73 61.204575 61.204575 61.204575
+74 75 43.863424 43.863424 43.863424
+74 76 55.081757 55.081757 55.081757
+74 77 75.286121 75.286121 75.286121
+74 78 60.745370 60.745370 60.745370
+74 79 7.211103 7.211103 7.211103
+74 80 8.944272 8.944272 8.944272
+74 81 46.840154 46.840154 46.840154
+74 82 47.042534 47.042534 47.042534
+74 83 30.232433 30.232433 30.232433
+74 84 45.453273 45.453273 45.453273
+74 85 63.134776 63.134776 63.134776
+74 86 71.344236 71.344236 71.344236
+74 87 40.706265 40.706265 40.706265
+74 88 37.363083 37.363083 37.363083
+74 89 22.090722 22.090722 22.090722
+74 90 85.146932 85.146932 85.146932
+74 91 37.336309 37.336309 37.336309
+74 92 50.328918 50.328918 50.328918
+74 93 53.758720 53.758720 53.758720
+74 94 59.539903 59.539903 59.539903
+74 95 56.293872 56.293872 56.293872
+74 96 58.694122 58.694122 58.694122
+74 97 53.338541 53.338541 53.338541
+74 98 42.047592 42.047592 42.047592
+74 99 25.298221 25.298221 25.298221
+74 100 34.655447 34.655447 34.655447
+74 101 29.832868 29.832868 29.832868
+75 1 36.055513 36.055513 36.055513
+75 2 65.192024 65.192024 65.192024
+75 3 55.036352 55.036352 55.036352
+75 4 65.030762 65.030762 65.030762
+75 5 60.000000 60.000000 60.000000
+75 6 65.000000 65.000000 65.000000
+75 7 55.036352 55.036352 55.036352
+75 8 55.226805 55.226805 55.226805
+75 9 60.207973 60.207973 60.207973
+75 10 18.027756 18.027756 18.027756
+75 11 22.360680 22.360680 22.360680
+75 12 23.323808 23.323808 23.323808
+75 13 27.730849 27.730849 27.730849
+75 14 21.213203 21.213203 21.213203
+75 15 29.154759 29.154759 29.154759
+75 16 26.907248 26.907248 26.907248
+75 17 28.284271 28.284271 28.284271
+75 18 32.015621 32.015621 32.015621
+75 19 28.301943 28.301943 28.301943
+75 20 24.166092 24.166092 24.166092
+75 21 22.561028 22.561028 22.561028
+75 22 25.000000 25.000000 25.000000
+75 23 20.615528 20.615528 20.615528
+75 24 23.430749 23.430749 23.430749
+75 25 18.681542 18.681542 18.681542
+75 26 21.213203 21.213203 21.213203
+75 27 75.663730 75.663730 75.663730
+75 28 76.485293 76.485293 76.485293
+75 29 72.691127 72.691127 72.691127
+75 30 71.589105 71.589105 71.589105
+75 31 68.731361 68.731361 68.731361
+75 32 69.634761 69.634761 69.634761
+75 33 67.742158 67.742158 67.742158
+75 34 65.192024 65.192024 65.192024
+75 35 66.708320 66.708320 66.708320
+75 36 80.212219 80.212219 80.212219
+75 37 79.056942 79.056942 79.056942
+75 38 76.609399 76.609399 76.609399
+75 39 73.239334 73.239334 73.239334
+75 40 72.111026 72.111026 72.111026
+75 41 76.321688 76.321688 76.321688
+75 42 66.850580 66.850580 66.850580
+75 43 69.462220 69.462220 69.462220
+75 44 73.824115 73.824115 73.824115
+75 45 71.196910 71.196910 71.196910
+75 46 62.000000 62.000000 62.000000
+75 47 60.033324 60.033324 60.033324
+75 48 30.805844 30.805844 30.805844
+75 49 26.627054 26.627054 26.627054
+75 50 23.409400 23.409400 23.409400
+75 51 54.120237 54.120237 54.120237
+75 52 35.000000 35.000000 35.000000
+75 53 11.180340 11.180340 11.180340
+75 54 30.000000 30.000000 30.000000
+75 55 53.150729 53.150729 53.150729
+75 56 41.231056 41.231056 41.231056
+75 57 33.541020 33.541020 33.541020
+75 58 11.180340 11.180340 11.180340
+75 59 11.180340 11.180340 11.180340
+75 60 10.000000 10.000000 10.000000
+75 61 40.311289 40.311289 40.311289
+75 62 51.478151 51.478151 51.478151
+75 63 47.434165 47.434165 47.434165
+75 64 45.000000 45.000000 45.000000
+75 65 26.925824 26.925824 26.925824
+75 66 25.000000 25.000000 25.000000
+75 67 27.018512 27.018512 27.018512
+75 68 49.193496 49.193496 49.193496
+75 69 44.721360 44.721360 44.721360
+75 70 33.837849 33.837849 33.837849
+75 71 51.244512 51.244512 51.244512
+75 72 57.008771 57.008771 57.008771
+75 73 62.241465 62.241465 62.241465
+75 74 43.863424 43.863424 43.863424
+75 76 21.213203 21.213203 21.213203
+75 77 40.792156 40.792156 40.792156
+75 78 17.262677 17.262677 17.262677
+75 79 37.947332 37.947332 37.947332
+75 80 50.000000 50.000000 50.000000
+75 81 38.183766 38.183766 38.183766
+75 82 47.801674 47.801674 47.801674
+75 83 24.041631 24.041631 24.041631
+75 84 20.248457 20.248457 20.248457
+75 85 38.078866 38.078866 38.078866
+75 86 43.104524 43.104524 43.104524
+75 87 4.123106 4.123106 4.123106
+75 88 8.944272 8.944272 8.944272
+75 89 38.209946 38.209946 38.209946
+75 90 49.335586 49.335586 49.335586
+75 91 31.906112 31.906112 31.906112
+75 92 36.400549 36.400549 36.400549
+75 93 40.224371 40.224371 40.224371
+75 94 52.009614 52.009614 52.009614
+75 95 46.400431 46.400431 46.400431
+75 96 39.812058 39.812058 39.812058
+75 97 48.795492 48.795492 48.795492
+75 98 16.124515 16.124515 16.124515
+75 99 32.557641 32.557641 32.557641
+75 100 16.155494 16.155494 16.155494
+75 101 48.270074 48.270074 48.270074
+76 1 57.008771 57.008771 57.008771
+76 2 82.462113 82.462113 82.462113
+76 3 72.034714 72.034714 72.034714
+76 4 81.786307 81.786307 81.786307
+76 5 76.485293 76.485293 76.485293
+76 6 81.394103 81.394103 81.394103
+76 7 71.196910 71.196910 71.196910
+76 8 70.710678 70.710678 70.710678
+76 9 75.663730 75.663730 75.663730
+76 10 30.413813 30.413813 30.413813
+76 11 35.355339 35.355339 35.355339
+76 12 35.128336 35.128336 35.128336
+76 13 40.112342 40.112342 40.112342
+76 14 30.000000 30.000000 30.000000
+76 15 40.000000 40.000000 40.000000
+76 16 35.128336 35.128336 35.128336
+76 17 35.355339 35.355339 35.355339
+76 18 40.311289 40.311289 40.311289
+76 19 39.000000 39.000000 39.000000
+76 20 37.336309 37.336309 37.336309
+76 21 38.327536 38.327536 38.327536
+76 22 35.000000 35.000000 35.000000
+76 23 36.400549 36.400549 36.400549
+76 24 33.000000 33.000000 33.000000
+76 25 34.481879 34.481879 34.481879
+76 26 30.000000 30.000000 30.000000
+76 27 93.407708 93.407708 93.407708
+76 28 94.868330 94.868330 94.868330
+76 29 90.520716 90.520716 90.520716
+76 30 90.138782 90.138782 90.138782
+76 31 86.683332 86.683332 86.683332
+76 32 88.255311 88.255311 88.255311
+76 33 85.726309 85.726309 85.726309
+76 34 82.462113 82.462113 82.462113
+76 35 85.440037 85.440037 85.440037
+76 36 101.212647 101.212647 101.212647
+76 37 100.000000 100.000000 100.000000
+76 38 97.616597 97.616597 97.616597
+76 39 94.201911 94.201911 94.201911
+76 40 93.005376 93.005376 93.005376
+76 41 97.082439 97.082439 97.082439
+76 42 87.800911 87.800911 87.800911
+76 43 90.138782 90.138782 90.138782
+76 44 94.339811 94.339811 94.339811
+76 45 91.809586 91.809586 91.809586
+76 46 78.447435 78.447435 78.447435
+76 47 76.118329 76.118329 76.118329
+76 48 40.112342 40.112342 40.112342
+76 49 37.000000 37.000000 37.000000
+76 50 37.656341 37.656341 37.656341
+76 51 73.409809 73.409809 73.409809
+76 52 52.201533 52.201533 52.201533
+76 53 32.015621 32.015621 32.015621
+76 54 47.434165 47.434165 47.434165
+76 55 74.330344 74.330344 74.330344
+76 56 60.415230 60.415230 60.415230
+76 57 54.083269 54.083269 54.083269
+76 58 32.015621 32.015621 32.015621
+76 59 11.180340 11.180340 11.180340
+76 60 15.811388 15.811388 15.811388
+76 61 55.901699 55.901699 55.901699
+76 62 72.111026 72.111026 72.111026
+76 63 67.082039 67.082039 67.082039
+76 64 61.846584 61.846584 61.846584
+76 65 47.169906 47.169906 47.169906
+76 66 46.097722 46.097722 46.097722
+76 67 48.166378 48.166378 48.166378
+76 68 69.641941 69.641941 69.641941
+76 69 65.192024 65.192024 65.192024
+76 70 53.712196 53.712196 53.712196
+76 71 70.682388 70.682388 70.682388
+76 72 78.102497 78.102497 78.102497
+76 73 83.450584 83.450584 83.450584
+76 74 55.081757 55.081757 55.081757
+76 75 21.213203 21.213203 21.213203
+76 77 55.443665 55.443665 55.443665
+76 78 18.110770 18.110770 18.110770
+76 79 51.088159 51.088159 51.088159
+76 80 63.007936 63.007936 63.007936
+76 81 59.396970 59.396970 59.396970
+76 82 68.883960 68.883960 68.883960
+76 83 43.908997 43.908997 43.908997
+76 84 41.231056 41.231056 41.231056
+76 85 57.271284 57.271284 57.271284
+76 86 60.728906 60.728906 60.728906
+76 87 24.839485 24.839485 24.839485
+76 88 20.248457 20.248457 20.248457
+76 89 56.302753 56.302753 56.302753
+76 90 62.000000 62.000000 62.000000
+76 91 52.801515 52.801515 52.801515
+76 92 57.489129 57.489129 57.489129
+76 93 61.220911 61.220911 61.220911
+76 94 73.109507 73.109507 73.109507
+76 95 67.475922 67.475922 67.475922
+76 96 60.207973 60.207973 60.207973
+76 97 70.007142 70.007142 70.007142
+76 98 13.038405 13.038405 13.038405
+76 99 51.478151 51.478151 51.478151
+76 100 36.619667 36.619667 36.619667
+76 101 67.230945 67.230945 67.230945
+77 1 42.941821 42.941821 42.941821
+77 2 80.956779 80.956779 80.956779
+77 3 73.573093 73.573093 73.573093
+77 4 82.298238 82.298238 82.298238
+77 5 78.892332 78.892332 78.892332
+77 6 83.240615 83.240615 83.240615
+77 7 75.716577 75.716577 75.716577
+77 8 77.420927 77.420927 77.420927
+77 9 81.541401 81.541401 81.541401
+77 10 55.036352 55.036352 55.036352
+77 11 57.306195 57.306195 57.306195
+77 12 59.059292 59.059292 59.059292
+77 13 61.587336 61.587336 61.587336
+77 14 59.615434 59.615434 59.615434
+77 15 64.140471 64.140471 64.140471
+77 16 64.404969 64.404969 64.404969
+77 17 66.211781 66.211781 66.211781
+77 18 68.476273 68.476273 68.476273
+77 19 17.464249 17.464249 17.464249
+77 20 18.110770 18.110770 18.110770
+77 21 18.248288 18.248288 18.248288
+77 22 21.189620 21.189620 21.189620
+77 23 20.223748 20.223748 20.223748
+77 24 23.086793 23.086793 23.086793
+77 25 22.203603 22.203603 22.203603
+77 26 25.961510 25.961510 25.961510
+77 27 39.357337 39.357337 39.357337
+77 28 41.880783 41.880783 41.880783
+77 29 36.715120 36.715120 36.715120
+77 30 37.802116 37.802116 37.802116
+77 31 33.286634 33.286634 33.286634
+77 32 36.235342 36.235342 36.235342
+77 33 32.449961 32.449961 32.449961
+77 34 28.178006 28.178006 28.178006
+77 35 33.970576 33.970576 33.970576
+77 36 73.334848 73.334848 73.334848
+77 37 73.171033 73.171033 73.171033
+77 38 70.178344 70.178344 70.178344
+77 39 68.029405 68.029405 68.029405
+77 40 68.000000 68.000000 68.000000
+77 41 73.000000 73.000000 73.000000
+77 42 63.031738 63.031738 63.031738
+77 43 68.183576 68.183576 68.183576
+77 44 73.171033 73.171033 73.171033
+77 45 70.178344 70.178344 70.178344
+77 46 80.622577 80.622577 80.622577
+77 47 79.924965 79.924965 79.924965
+77 48 66.730802 66.730802 66.730802
+77 49 19.313208 19.313208 19.313208
+77 50 18.000000 18.000000 18.000000
+77 51 25.942244 25.942244 25.942244
+77 52 9.433981 9.433981 9.433981
+77 53 39.357337 39.357337 39.357337
+77 54 55.172457 55.172457 55.172457
+77 55 48.259714 48.259714 48.259714
+77 56 56.603887 56.603887 56.603887
+77 57 25.079872 25.079872 25.079872
+77 58 32.695565 32.695565 32.695565
+77 59 45.044423 45.044423 45.044423
+77 60 50.635956 50.635956 50.635956
+77 61 65.795137 65.795137 65.795137
+77 62 55.081757 55.081757 55.081757
+77 63 23.537205 23.537205 23.537205
+77 64 9.433981 9.433981 9.433981
+77 65 23.430749 23.430749 23.430749
+77 66 37.536649 37.536649 37.536649
+77 67 31.400637 31.400637 31.400637
+77 68 30.265492 30.265492 30.265492
+77 69 52.000000 52.000000 52.000000
+77 70 49.406477 49.406477 49.406477
+77 71 62.241465 62.241465 62.241465
+77 72 43.289722 43.289722 43.289722
+77 73 53.084838 53.084838 53.084838
+77 74 75.286121 75.286121 75.286121
+77 75 40.792156 40.792156 40.792156
+77 76 55.443665 55.443665 55.443665
+77 78 38.078866 38.078866 38.078866
+77 79 68.117545 68.117545 68.117545
+77 80 77.794601 77.794601 77.794601
+77 81 37.336309 37.336309 37.336309
+77 82 47.296934 47.296934 47.296934
+77 83 45.276926 45.276926 45.276926
+77 84 29.832868 29.832868 29.832868
+77 85 17.262677 17.262677 17.262677
+77 86 11.401754 11.401754 11.401754
+77 87 40.804412 40.804412 40.804412
+77 88 49.477268 49.477268 49.477268
+77 89 58.412327 58.412327 58.412327
+77 90 9.899495 9.899495 9.899495
+77 91 41.880783 41.880783 41.880783
+77 92 31.953091 31.953091 31.953091
+77 93 31.780497 31.780497 31.780497
+77 94 40.012498 40.012498 40.012498
+77 95 36.124784 36.124784 36.124784
+77 96 25.317978 25.317978 25.317978
+77 97 42.296572 42.296572 42.296572
+77 98 56.320511 56.320511 56.320511
+77 99 52.497619 52.497619 52.497619
+77 100 41.048752 41.048752 41.048752
+77 101 62.177166 62.177166 62.177166
+78 1 49.979996 49.979996 49.979996
+78 2 82.024387 82.024387 82.024387
+78 3 72.006944 72.006944 72.006944
+78 4 82.006097 82.006097 82.006097
+78 5 77.058419 77.058419 77.058419
+78 6 82.054860 82.054860 82.054860
+78 7 72.173402 72.173402 72.173402
+78 8 72.443081 72.443081 72.443081
+78 9 77.414469 77.414469 77.414469
+78 10 34.539832 34.539832 34.539832
+78 11 39.217343 39.217343 39.217343
+78 12 39.924930 39.924930 39.924930
+78 13 44.598206 44.598206 44.598206
+78 14 36.715120 36.715120 36.715120
+78 15 45.694639 45.694639 45.694639
+78 16 42.544095 42.544095 42.544095
+78 17 43.566042 43.566042 43.566042
+78 18 47.885280 47.885280 47.885280
+78 19 21.095023 21.095023 21.095023
+78 20 20.248457 20.248457 20.248457
+78 21 22.472205 22.472205 22.472205
+78 22 17.117243 17.117243 17.117243
+78 23 20.808652 20.808652 20.808652
+78 24 15.132746 15.132746 15.132746
+78 25 19.209373 19.209373 19.209373
+78 26 12.165525 12.165525 12.165525
+78 27 76.896034 76.896034 76.896034
+78 28 78.790862 78.790862 78.790862
+78 29 74.094534 74.094534 74.094534
+78 30 74.249579 74.249579 74.249579
+78 31 70.384657 70.384657 70.384657
+78 32 72.449983 72.449983 72.449983
+78 33 69.462220 69.462220 69.462220
+78 34 65.787537 65.787537 65.787537
+78 35 69.771054 69.771054 69.771054
+78 36 93.059121 93.059121 93.059121
+78 37 92.130342 92.130342 92.130342
+78 38 89.470666 89.470666 89.470666
+78 39 86.313383 86.313383 86.313383
+78 40 85.428333 85.428333 85.428333
+78 41 89.961103 89.961103 89.961103
+78 42 80.056230 80.056230 80.056230
+78 43 83.384651 83.384651 83.384651
+78 44 88.022724 88.022724 88.022724
+78 45 85.234969 85.234969 85.234969
+78 46 79.056942 79.056942 79.056942
+78 47 77.162167 77.162167 77.162167
+78 48 46.957428 46.957428 46.957428
+78 49 19.104973 19.104973 19.104973
+78 50 21.023796 21.023796 21.023796
+78 51 58.523500 58.523500 58.523500
+78 52 36.235342 36.235342 36.235342
+78 53 27.073973 27.073973 27.073973
+78 54 47.095647 47.095647 47.095647
+78 55 65.368188 65.368188 65.368188
+78 56 57.428216 57.428216 57.428216
+78 57 41.868843 41.868843 41.868843
+78 58 23.086793 23.086793 23.086793
+78 59 10.630146 10.630146 10.630146
+78 60 21.400935 21.400935 21.400935
+78 61 57.558666 57.558666 57.558666
+78 62 65.787537 65.787537 65.787537
+78 63 52.801515 52.801515 52.801515
+78 64 45.310043 45.310043 45.310043
+78 65 34.828150 34.828150 34.828150
+78 66 38.897301 38.897301 38.897301
+78 67 38.470768 38.470768 38.470768
+78 68 56.586217 56.586217 56.586217
+78 69 59.481089 59.481089 59.481089
+78 70 49.648766 49.648766 49.648766
+78 71 67.082039 67.082039 67.082039
+78 72 66.843100 66.843100 66.843100
+78 73 73.783467 73.783467 73.783467
+78 74 60.745370 60.745370 60.745370
+78 75 17.262677 17.262677 17.262677
+78 76 18.110770 18.110770 18.110770
+78 77 38.078866 38.078866 38.078866
+78 79 55.081757 55.081757 55.081757
+78 80 67.186308 67.186308 67.186308
+78 81 50.119856 50.119856 50.119856
+78 82 60.835845 60.835845 60.835845
+78 83 40.199502 40.199502 40.199502
+78 84 31.304952 31.304952 31.304952
+78 85 42.801869 42.801869 42.801869
+78 86 44.721360 44.721360 44.721360
+78 87 21.095023 21.095023 21.095023
+78 88 23.706539 23.706539 23.706539
+78 89 55.009090 55.009090 55.009090
+78 90 44.045431 44.045431 44.045431
+78 91 46.173586 46.173586 46.173586
+78 92 46.872167 46.872167 46.872167
+78 93 50.000000 50.000000 50.000000
+78 94 62.008064 62.008064 62.008064
+78 95 56.400355 56.400355 56.400355
+78 96 47.381431 47.381431 47.381431
+78 97 60.207973 60.207973 60.207973
+78 98 24.207437 24.207437 24.207437
+78 99 49.091751 49.091751 49.091751
+78 100 32.140317 32.140317 32.140317
+78 101 64.498062 64.498062 64.498062
+79 1 32.557641 32.557641 32.557641
+79 2 33.615473 33.615473 33.615473
+79 3 23.600847 23.600847 23.600847
+79 4 32.202484 32.202484 32.202484
+79 5 26.832816 26.832816 26.832816
+79 6 31.384710 31.384710 31.384710
+79 7 21.470911 21.470911 21.470911
+79 8 20.248457 20.248457 20.248457
+79 9 25.000000 25.000000 25.000000
+79 10 21.095023 21.095023 21.095023
+79 11 16.124515 16.124515 16.124515
+79 12 16.000000 16.000000 16.000000
+79 13 11.000000 11.000000 11.000000
+79 14 21.213203 21.213203 21.213203
+79 15 11.401754 11.401754 11.401754
+79 16 17.088007 17.088007 17.088007
+79 17 17.888544 17.888544 17.888544
+79 18 13.601471 13.601471 13.601471
+79 19 62.425956 62.425956 62.425956
+79 20 57.201399 57.201399 57.201399
+79 21 53.263496 53.263496 53.263496
+79 22 60.207973 60.207973 60.207973
+79 23 52.009614 52.009614 52.009614
+79 24 59.169249 59.169249 59.169249
+79 25 50.803543 50.803543 50.803543
+79 26 57.706152 57.706152 57.706152
+79 27 90.801982 90.801982 90.801982
+79 28 89.498603 89.498603 89.498603
+79 29 87.931792 87.931792 87.931792
+79 30 84.646323 84.646323 84.646323
+79 31 84.118963 84.118963 84.118963
+79 32 82.710338 82.710338 82.710338
+79 33 83.168504 83.168504 83.168504
+79 34 83.006024 83.006024 83.006024
+79 35 79.812280 79.812280 79.812280
+79 36 65.741920 65.741920 65.741920
+79 37 63.953108 63.953108 63.953108
+79 38 62.649820 62.649820 62.649820
+79 39 59.093147 59.093147 59.093147
+79 40 57.271284 57.271284 57.271284
+79 41 59.539903 59.539903 59.539903
+79 42 53.488316 53.488316 53.488316
+79 43 52.773099 52.773099 52.773099
+79 44 55.226805 55.226805 55.226805
+79 45 53.712196 53.712196 53.712196
+79 46 28.635642 28.635642 28.635642
+79 47 26.000000 26.000000 26.000000
+79 48 12.529964 12.529964 12.529964
+79 49 61.294372 61.294372 61.294372
+79 50 55.605755 55.605755 55.605755
+79 51 67.357256 67.357256 67.357256
+79 52 59.203040 59.203040 59.203040
+79 53 31.064449 31.064449 31.064449
+79 54 13.416408 13.416408 13.416408
+79 55 47.169906 47.169906 47.169906
+79 56 22.360680 22.360680 22.360680
+79 57 46.957428 46.957428 46.957428
+79 58 38.013156 38.013156 38.013156
+79 59 46.529560 46.529560 46.529560
+79 60 36.055513 36.055513 36.055513
+79 61 8.062258 8.062258 8.062258
+79 62 38.078866 38.078866 38.078866
+79 63 60.745370 60.745370 60.745370
+79 64 67.416615 67.416615 67.416615
+79 65 45.221676 45.221676 45.221676
+79 66 31.384710 31.384710 31.384710
+79 67 38.078866 38.078866 38.078866
+79 68 57.723479 57.723479 57.723479
+79 69 32.249031 32.249031 32.249031
+79 70 23.345235 23.345235 23.345235
+79 71 29.966648 29.966648 29.966648
+79 72 57.008771 57.008771 57.008771
+79 73 55.731499 55.731499 55.731499
+79 74 7.211103 7.211103 7.211103
+79 75 37.947332 37.947332 37.947332
+79 76 51.088159 51.088159 51.088159
+79 77 68.117545 68.117545 68.117545
+79 78 55.081757 55.081757 55.081757
+79 80 12.165525 12.165525 12.165525
+79 81 40.024992 40.024992 40.024992
+79 82 41.048752 41.048752 41.048752
+79 83 23.021729 23.021729 23.021729
+79 84 38.288379 38.288379 38.288379
+79 85 55.946403 55.946403 55.946403
+79 86 64.140471 64.140471 64.140471
+79 87 34.539832 34.539832 34.539832
+79 88 32.249031 32.249031 32.249031
+79 89 16.124515 16.124515 16.124515
+79 90 77.987178 77.987178 77.987178
+79 91 30.364453 30.364453 30.364453
+79 92 43.324358 43.324358 43.324358
+79 93 46.840154 46.840154 46.840154
+79 94 53.150729 53.150729 53.150729
+79 95 49.648766 49.648766 49.648766
+79 96 51.623638 51.623638 51.623638
+79 97 47.042534 47.042534 47.042534
+79 98 38.209946 38.209946 38.209946
+79 99 18.439089 18.439089 18.439089
+79 100 27.658633 27.658633 27.658633
+79 101 25.495098 25.495098 25.495098
+80 1 38.470768 38.470768 38.470768
+80 2 25.495098 25.495098 25.495098
+80 3 17.464249 17.464249 17.464249
+80 4 23.345235 23.345235 23.345235
+80 5 18.439089 18.439089 18.439089
+80 6 22.022716 22.022716 22.022716
+80 7 13.892444 13.892444 13.892444
+80 8 11.401754 11.401754 11.401754
+80 9 15.000000 15.000000 15.000000
+80 10 33.241540 33.241540 33.241540
+80 11 28.284271 28.284271 28.284271
+80 12 28.071338 28.071338 28.071338
+80 13 23.086793 23.086793 23.086793
+80 14 33.015148 33.015148 33.015148
+80 15 23.021729 23.021729 23.021729
+80 16 28.284271 28.284271 28.284271
+80 17 28.635642 28.635642 28.635642
+80 18 23.769729 23.769729 23.769729
+80 19 73.573093 73.573093 73.573093
+80 20 68.264193 68.264193 68.264193
+80 21 64.070274 64.070274 64.070274
+80 22 71.589105 71.589105 71.589105
+80 23 62.968246 62.968246 62.968246
+80 24 70.661163 70.661163 70.661163
+80 25 61.911227 61.911227 61.911227
+80 26 69.354164 69.354164 69.354164
+80 27 96.772930 96.772930 96.772930
+80 28 94.921020 94.921020 94.921020
+80 29 94.021274 94.021274 94.021274
+80 30 90.249654 90.249654 90.249654
+80 31 90.376988 90.376988 90.376988
+80 32 88.391176 88.391176 88.391176
+80 33 89.470666 89.470666 89.470666
+80 34 89.944427 89.944427 89.944427
+80 35 85.615419 85.615419 85.615419
+80 36 63.324561 63.324561 63.324561
+80 37 61.400326 61.400326 61.400326
+80 38 60.638272 60.638272 60.638272
+80 39 57.271284 57.271284 57.271284
+80 40 55.317267 55.317267 55.317267
+80 41 56.612719 56.612719 56.612719
+80 42 52.469038 52.469038 52.469038
+80 43 50.447993 50.447993 50.447993
+80 44 51.865210 51.865210 51.865210
+80 45 50.960769 50.960769 50.960769
+80 46 19.798990 19.798990 19.798990
+80 47 16.970563 16.970563 16.970563
+80 48 23.345235 23.345235 23.345235
+80 49 72.560320 72.560320 72.560320
+80 50 66.573268 66.573268 66.573268
+80 51 73.790243 73.790243 73.790243
+80 52 68.593003 68.593003 68.593003
+80 53 42.485292 42.485292 42.485292
+80 54 22.803509 22.803509 22.803509
+80 55 49.648766 49.648766 49.648766
+80 56 25.298221 25.298221 25.298221
+80 57 55.000000 55.000000 55.000000
+80 58 49.244289 49.244289 49.244289
+80 59 58.694122 58.694122 58.694122
+80 60 48.166378 48.166378 48.166378
+80 61 12.041595 12.041595 12.041595
+80 62 39.115214 39.115214 39.115214
+80 63 67.601775 67.601775 67.601775
+80 64 76.059187 76.059187 76.059187
+80 65 54.451814 54.451814 54.451814
+80 66 40.311289 40.311289 40.311289
+80 67 46.754679 46.754679 46.754679
+80 68 63.560994 63.560994 63.560994
+80 69 34.928498 34.928498 34.928498
+80 70 29.681644 29.681644 29.681644
+80 71 29.017236 29.017236 29.017236
+80 72 60.415230 60.415230 60.415230
+80 73 57.078893 57.078893 57.078893
+80 74 8.944272 8.944272 8.944272
+80 75 50.000000 50.000000 50.000000
+80 76 63.007936 63.007936 63.007936
+80 77 77.794601 77.794601 77.794601
+80 78 67.186308 67.186308 67.186308
+80 79 12.165525 12.165525 12.165525
+80 81 46.065171 46.065171 46.065171
+80 82 44.147480 44.147480 44.147480
+80 83 32.649655 32.649655 32.649655
+80 84 48.270074 48.270074 48.270074
+80 85 64.202804 64.202804 64.202804
+80 86 72.622311 72.622311 72.622311
+80 87 46.486557 46.486557 46.486557
+80 88 44.407207 44.407207 44.407207
+80 89 20.591260 20.591260 20.591260
+80 90 87.692645 87.692645 87.692645
+80 91 37.443290 37.443290 37.443290
+80 92 50.249378 50.249378 50.249378
+80 93 53.235327 53.235327 53.235327
+80 94 57.280014 57.280014 57.280014
+80 95 54.781384 54.781384 54.781384
+80 96 58.830264 58.830264 58.830264
+80 97 50.960769 50.960769 50.960769
+80 98 50.039984 50.039984 50.039984
+80 99 25.612497 25.612497 25.612497
+80 100 38.587563 38.587563 38.587563
+80 101 25.019992 25.019992 25.019992
+81 1 7.615773 7.615773 7.615773
+81 2 43.908997 43.908997 43.908997
+81 3 37.536649 37.536649 37.536649
+81 4 45.486262 45.486262 45.486262
+81 5 42.638011 42.638011 42.638011
+81 6 46.615448 46.615448 46.615448
+81 7 40.311289 40.311289 40.311289
+81 8 42.520583 42.520583 42.520583
+81 9 45.967380 45.967380 45.967380
+81 10 38.897301 38.897301 38.897301
+81 11 37.656341 37.656341 37.656341
+81 12 39.623226 39.623226 39.623226
+81 13 39.051248 39.051248 39.051248
+81 14 43.680659 43.680659 43.680659
+81 15 42.047592 42.047592 42.047592
+81 16 45.541190 45.541190 45.541190
+81 17 47.518417 47.518417 47.518417
+81 18 47.042534 47.042534 47.042534
+81 19 42.107007 42.107007 42.107007
+81 20 37.336309 37.336309 37.336309
+81 21 32.388269 32.388269 32.388269
+81 22 42.579338 42.579338 42.579338
+81 23 32.756679 32.756679 32.756679
+81 24 42.953463 42.953463 42.953463
+81 25 33.241540 33.241540 33.241540
+81 26 43.680659 43.680659 43.680659
+81 27 50.921508 50.921508 50.921508
+81 28 49.477268 49.477268 49.477268
+81 29 48.104054 48.104054 48.104054
+81 30 44.643029 44.643029 44.643029
+81 31 44.384682 44.384682 44.384682
+81 32 42.720019 42.720019 42.720019
+81 33 43.462628 43.462628 43.462628
+81 34 43.908997 43.908997 43.908997
+81 35 39.849718 39.849718 39.849718
+81 36 42.941821 42.941821 42.941821
+81 37 42.047592 42.047592 42.047592
+81 38 39.357337 39.357337 39.357337
+81 39 36.249138 36.249138 36.249138
+81 40 35.468296 35.468296 35.468296
+81 41 40.162171 40.162171 40.162171
+81 42 30.083218 30.083218 30.083218
+81 43 33.955854 33.955854 33.955854
+81 44 38.832976 38.832976 38.832976
+81 45 35.902646 35.902646 35.902646
+81 46 44.204072 44.204072 44.204072
+81 47 43.931765 43.931765 43.931765
+81 48 45.044423 45.044423 45.044423
+81 49 42.296572 42.296572 42.296572
+81 50 35.355339 35.355339 35.355339
+81 51 27.730849 27.730849 27.730849
+81 52 28.160256 28.160256 28.160256
+81 53 27.802878 27.802878 27.802878
+81 54 27.166155 27.166155 27.166155
+81 55 15.264338 15.264338 15.264338
+81 56 21.400935 21.400935 21.400935
+81 57 12.369317 12.369317 12.369317
+81 58 27.802878 27.802878 27.802878
+81 59 48.918299 48.918299 48.918299
+81 60 45.803930 45.803930 45.803930
+81 61 34.539832 34.539832 34.539832
+81 62 18.110770 18.110770 18.110770
+81 63 21.633308 21.633308 21.633308
+81 64 32.449961 32.449961 32.449961
+81 65 17.117243 17.117243 17.117243
+81 66 13.892444 13.892444 13.892444
+81 67 11.661904 11.661904 11.661904
+81 68 17.720045 17.720045 17.720045
+81 69 14.764823 14.764823 14.764823
+81 70 16.763055 16.763055 16.763055
+81 71 25.059928 25.059928 25.059928
+81 72 19.697716 19.697716 19.697716
+81 73 24.083189 24.083189 24.083189
+81 74 46.840154 46.840154 46.840154
+81 75 38.183766 38.183766 38.183766
+81 76 59.396970 59.396970 59.396970
+81 77 37.336309 37.336309 37.336309
+81 78 50.119856 50.119856 50.119856
+81 79 40.024992 40.024992 40.024992
+81 80 46.065171 46.065171 46.065171
+81 82 11.180340 11.180340 11.180340
+81 83 20.396078 20.396078 20.396078
+81 84 18.867962 18.867962 18.867962
+81 85 20.591260 20.591260 20.591260
+81 86 28.844410 28.844410 28.844410
+81 87 34.713110 34.713110 34.713110
+81 88 41.880783 41.880783 41.880783
+81 89 25.495098 25.495098 25.495098
+81 90 46.518813 46.518813 46.518813
+81 91 10.000000 10.000000 10.000000
+81 92 5.385165 5.385165 5.385165
+81 93 7.211103 7.211103 7.211103
+81 94 14.866069 14.866069 14.866069
+81 95 10.049876 10.049876 10.049876
+81 96 13.453624 13.453624 13.453624
+81 97 10.630146 10.630146 10.630146
+81 98 51.865210 51.865210 51.865210
+81 99 21.587033 21.587033 21.587033
+81 100 24.186773 24.186773 24.186773
+81 101 25.612497 25.612497 25.612497
+82 1 12.041595 12.041595 12.041595
+82 2 36.124784 36.124784 36.124784
+82 3 31.906112 31.906112 31.906112
+82 4 38.183766 38.183766 38.183766
+82 5 36.400549 36.400549 36.400549
+82 6 39.623226 39.623226 39.623226
+82 7 35.355339 35.355339 35.355339
+82 8 38.013156 38.013156 38.013156
+82 9 40.496913 40.496913 40.496913
+82 10 45.276926 45.276926 45.276926
+82 11 42.953463 42.953463 42.953463
+82 12 44.777226 44.777226 44.777226
+82 13 43.011626 43.011626 43.011626
+82 14 49.648766 49.648766 49.648766
+82 15 45.880279 45.880279 45.880279
+82 16 50.328918 50.328918 50.328918
+82 17 52.201533 52.201533 52.201533
+82 18 50.695167 50.695167 50.695167
+82 19 53.235327 53.235327 53.235327
+82 20 48.507731 48.507731 48.507731
+82 21 43.566042 43.566042 43.566042
+82 22 53.758720 53.758720 53.758720
+82 23 43.931765 43.931765 43.931765
+82 24 54.129474 54.129474 54.129474
+82 25 44.384682 44.384682 44.384682
+82 26 54.817880 54.817880 54.817880
+82 27 53.851648 53.851648 53.851648
+82 28 51.429563 51.429563 51.429563
+82 29 51.312766 51.312766 51.312766
+82 30 47.010637 47.010637 47.010637
+82 31 48.010416 48.010416 48.010416
+82 32 45.276926 45.276926 45.276926
+82 33 47.201695 47.201695 47.201695
+82 34 48.836462 48.836462 48.836462
+82 35 42.720019 42.720019 42.720019
+82 36 32.449961 32.449961 32.449961
+82 37 31.384710 31.384710 31.384710
+82 38 28.844410 28.844410 28.844410
+82 39 25.553865 25.553865 25.553865
+82 40 24.596748 24.596748 24.596748
+82 41 29.154759 29.154759 29.154759
+82 42 19.235384 19.235384 19.235384
+82 43 22.803509 22.803509 22.803509
+82 44 27.658633 27.658633 27.658633
+82 45 24.738634 24.738634 24.738634
+82 46 37.643060 37.643060 37.643060
+82 47 38.013156 38.013156 38.013156
+82 48 48.764741 48.764741 48.764741
+82 49 53.460266 53.460266 53.460266
+82 50 46.529560 46.529560 46.529560
+82 51 32.526912 32.526912 32.526912
+82 52 38.470768 38.470768 38.470768
+82 53 36.878178 36.878178 36.878178
+82 54 30.083218 30.083218 30.083218
+82 55 6.324555 6.324555 6.324555
+82 56 19.104973 19.104973 19.104973
+82 57 23.021729 23.021729 23.021729
+82 58 38.078866 38.078866 38.078866
+82 59 58.821765 58.821765 58.821765
+82 60 54.451814 54.451814 54.451814
+82 61 34.058773 34.058773 34.058773
+82 62 8.062258 8.062258 8.062258
+82 63 28.017851 28.017851 28.017851
+82 64 41.231056 41.231056 41.231056
+82 65 28.284271 28.284271 28.284271
+82 66 22.803509 22.803509 22.803509
+82 67 22.472205 22.472205 22.472205
+82 68 21.931712 21.931712 21.931712
+82 69 9.219544 9.219544 9.219544
+82 70 18.973666 18.973666 18.973666
+82 71 17.804494 17.804494 17.804494
+82 72 16.278821 16.278821 16.278821
+82 73 15.652476 15.652476 15.652476
+82 74 47.042534 47.042534 47.042534
+82 75 47.801674 47.801674 47.801674
+82 76 68.883960 68.883960 68.883960
+82 77 47.296934 47.296934 47.296934
+82 78 60.835845 60.835845 60.835845
+82 79 41.048752 41.048752 41.048752
+82 80 44.147480 44.147480 44.147480
+82 81 11.180340 11.180340 11.180340
+82 83 26.627054 26.627054 26.627054
+82 84 29.546573 29.546573 29.546573
+82 85 30.083218 30.083218 30.083218
+82 86 37.696154 37.696154 37.696154
+82 87 44.045431 44.045431 44.045431
+82 88 50.249378 50.249378 50.249378
+82 89 25.000000 25.000000 25.000000
+82 90 55.973208 55.973208 55.973208
+82 91 16.278821 16.278821 16.278821
+82 92 16.000000 16.000000 16.000000
+82 93 15.524175 15.524175 15.524175
+82 94 13.416408 13.416408 13.416408
+82 95 12.806248 12.806248 12.806248
+82 96 22.135944 22.135944 22.135944
+82 97 7.211103 7.211103 7.211103
+82 98 60.207973 60.207973 60.207973
+82 99 23.769729 23.769729 23.769729
+82 100 32.526912 32.526912 32.526912
+82 101 20.124612 20.124612 20.124612
+83 1 14.764823 14.764823 14.764823
+83 2 42.047592 42.047592 42.047592
+83 3 32.388269 32.388269 32.388269
+83 4 42.296572 42.296572 42.296572
+83 5 37.656341 37.656341 37.656341
+83 6 42.579338 42.579338 42.579338
+83 7 33.241540 33.241540 33.241540
+83 8 34.176015 34.176015 34.176015
+83 9 38.897301 38.897301 38.897301
+83 10 18.788294 18.788294 18.788294
+83 11 17.262677 17.262677 17.262677
+83 12 19.235384 19.235384 19.235384
+83 13 19.104973 19.104973 19.104973
+83 14 23.409400 23.409400 23.409400
+83 15 22.090722 22.090722 22.090722
+83 16 25.179357 25.179357 25.179357
+83 17 27.166155 27.166155 27.166155
+83 18 27.073973 27.073973 27.073973
+83 19 41.629317 41.629317 41.629317
+83 20 36.249138 36.249138 36.249138
+83 21 31.764760 31.764760 31.764760
+83 22 40.162171 40.162171 40.162171
+83 23 30.870698 30.870698 30.870698
+83 24 39.560081 39.560081 39.560081
+83 25 30.083218 30.083218 30.083218
+83 26 38.832976 38.832976 38.832976
+83 27 69.231496 69.231496 69.231496
+83 28 68.468971 68.468971 68.468971
+83 29 66.287254 66.287254 66.287254
+83 30 63.505905 63.505905 63.505905
+83 31 62.369865 62.369865 62.369865
+83 32 61.522354 61.522354 61.522354
+83 33 61.392182 61.392182 61.392182
+83 34 60.728906 60.728906 60.728906
+83 35 58.549125 58.549125 58.549125
+83 36 58.000000 58.000000 58.000000
+83 37 56.639209 56.639209 56.639209
+83 38 54.451814 54.451814 54.451814
+83 39 50.931326 50.931326 50.931326
+83 40 49.578221 49.578221 49.578221
+83 41 53.413481 53.413481 53.413481
+83 42 44.553339 44.553339 44.553339
+83 43 46.400431 46.400431 46.400431
+83 44 50.477718 50.477718 50.477718
+83 45 48.010416 48.010416 48.010416
+83 46 39.623226 39.623226 39.623226
+83 47 38.078866 38.078866 38.078866
+83 48 25.079872 25.079872 25.079872
+83 49 40.853396 40.853396 40.853396
+83 50 34.438351 34.438351 34.438351
+83 51 45.705580 45.705580 45.705580
+83 52 36.235342 36.235342 36.235342
+83 53 13.152946 13.152946 13.152946
+83 54 9.899495 9.899495 9.899495
+83 55 32.756679 32.756679 32.756679
+83 56 17.262677 17.262677 17.262677
+83 57 24.351591 24.351591 24.351591
+83 58 18.248288 18.248288 18.248288
+83 59 35.114100 35.114100 35.114100
+83 60 28.600699 28.600699 28.600699
+83 61 20.808652 20.808652 20.808652
+83 62 28.425341 28.425341 28.425341
+83 63 38.832976 38.832976 38.832976
+83 64 44.418465 44.418465 44.418465
+83 65 22.203603 22.203603 22.203603
+83 66 8.544004 8.544004 8.544004
+83 67 15.231546 15.231546 15.231546
+83 68 37.013511 37.013511 37.013511
+83 69 21.400935 21.400935 21.400935
+83 70 9.848858 9.848858 9.848858
+83 71 27.202941 27.202941 27.202941
+83 72 39.849718 39.849718 39.849718
+83 73 42.190046 42.190046 42.190046
+83 74 30.232433 30.232433 30.232433
+83 75 24.041631 24.041631 24.041631
+83 76 43.908997 43.908997 43.908997
+83 77 45.276926 45.276926 45.276926
+83 78 40.199502 40.199502 40.199502
+83 79 23.021729 23.021729 23.021729
+83 80 32.649655 32.649655 32.649655
+83 81 20.396078 20.396078 20.396078
+83 82 26.627054 26.627054 26.627054
+83 84 15.620499 15.620499 15.620499
+83 85 33.105891 33.105891 33.105891
+83 86 41.182521 41.182521 41.182521
+83 87 19.924859 19.924859 19.924859
+83 88 24.207437 24.207437 24.207437
+83 89 15.297059 15.297059 15.297059
+83 90 55.172457 55.172457 55.172457
+83 91 10.770330 10.770330 10.770330
+83 92 22.022716 22.022716 22.022716
+83 93 26.000000 26.000000 26.000000
+83 94 35.171011 35.171011 35.171011
+83 95 30.413813 30.413813 30.413813
+83 96 29.614186 29.614186 29.614186
+83 97 30.083218 30.083218 30.083218
+83 98 33.970576 33.970576 33.970576
+83 99 9.055385 9.055385 9.055385
+83 100 8.062258 8.062258 8.062258
+83 101 24.331050 24.331050 24.331050
+84 1 19.235384 19.235384 19.235384
+84 2 55.317267 55.317267 55.317267
+84 3 46.486557 46.486557 46.486557
+84 4 56.044625 56.044625 56.044625
+84 5 51.865210 51.865210 51.865210
+84 6 56.612719 56.612719 56.612719
+84 7 47.927028 47.927028 47.927028
+84 8 49.193496 49.193496 49.193496
+84 9 53.712196 53.712196 53.712196
+84 10 27.294688 27.294688 27.294688
+84 11 28.460499 28.460499 28.460499
+84 12 30.364453 30.364453 30.364453
+84 13 32.202484 32.202484 32.202484
+84 14 32.249031 32.249031 32.249031
+84 15 34.928498 34.928498 34.928498
+84 16 36.138622 36.138622 36.138622
+84 17 38.078866 38.078866 38.078866
+84 18 39.560081 39.560081 39.560081
+84 19 26.925824 26.925824 26.925824
+84 20 21.587033 21.587033 21.587033
+84 21 16.763055 16.763055 16.763055
+84 22 26.172505 26.172505 26.172505
+84 23 16.278821 16.278821 16.278821
+84 24 26.019224 26.019224 26.019224
+84 25 16.031220 16.031220 16.031220
+84 26 26.076810 26.076810 26.076810
+84 27 58.008620 58.008620 58.008620
+84 28 58.137767 58.137767 58.137767
+84 29 55.009090 55.009090 55.009090
+84 30 53.150729 53.150729 53.150729
+84 31 51.009803 51.009803 51.009803
+84 32 51.156622 51.156622 51.156622
+84 33 50.009999 50.009999 50.009999
+84 34 48.373546 48.373546 48.373546
+84 35 48.166378 48.166378 48.166378
+84 36 61.773781 61.773781 61.773781
+84 37 60.827625 60.827625 60.827625
+84 38 58.180753 58.180753 58.180753
+84 39 55.009090 55.009090 55.009090
+84 40 54.129474 54.129474 54.129474
+84 41 58.694122 58.694122 58.694122
+84 42 48.754487 48.754487 48.754487
+84 43 52.201533 52.201533 52.201533
+84 44 56.920998 56.920998 56.920998
+84 45 54.083269 54.083269 54.083269
+84 46 53.758720 53.758720 53.758720
+84 47 52.554733 52.554733 52.554733
+84 48 37.696154 37.696154 37.696154
+84 49 26.476405 26.476405 26.476405
+84 50 19.646883 19.646883 19.646883
+84 51 35.227830 35.227830 35.227830
+84 52 21.095023 21.095023 21.095023
+84 53 12.041595 12.041595 12.041595
+84 54 25.495098 25.495098 25.495098
+84 55 34.132096 34.132096 34.132096
+84 56 29.832868 29.832868 29.832868
+84 57 13.601471 13.601471 13.601471
+84 58 9.219544 9.219544 9.219544
+84 59 30.413813 30.413813 30.413813
+84 60 29.154759 29.154759 29.154759
+84 61 36.400549 36.400549 36.400549
+84 62 34.928498 34.928498 34.928498
+84 63 28.284271 28.284271 28.284271
+84 64 30.083218 30.083218 30.083218
+84 65 8.062258 8.062258 8.062258
+84 66 9.219544 9.219544 9.219544
+84 67 7.211103 7.211103 7.211103
+84 68 29.154759 29.154759 29.154759
+84 69 29.154759 29.154759 29.154759
+84 70 21.840330 21.840330 21.840330
+84 71 38.052595 38.052595 38.052595
+84 72 36.878178 36.878178 36.878178
+84 73 42.801869 42.801869 42.801869
+84 74 45.453273 45.453273 45.453273
+84 75 20.248457 20.248457 20.248457
+84 76 41.231056 41.231056 41.231056
+84 77 29.832868 29.832868 29.832868
+84 78 31.304952 31.304952 31.304952
+84 79 38.288379 38.288379 38.288379
+84 80 48.270074 48.270074 48.270074
+84 81 18.867962 18.867962 18.867962
+84 82 29.546573 29.546573 29.546573
+84 83 15.620499 15.620499 15.620499
+84 85 20.099751 20.099751 20.099751
+84 86 27.202941 27.202941 27.202941
+84 87 17.464249 17.464249 17.464249
+84 88 25.961510 25.961510 25.961510
+84 89 29.966648 29.966648 29.966648
+84 90 39.698866 39.698866 39.698866
+84 91 16.000000 16.000000 16.000000
+84 92 16.278821 16.278821 16.278821
+84 93 20.000000 20.000000 20.000000
+84 94 31.890437 31.890437 31.890437
+84 95 26.248809 26.248809 26.248809
+84 96 19.924859 19.924859 19.924859
+84 97 29.206164 29.206164 29.206164
+84 98 35.468296 35.468296 35.468296
+84 99 23.706539 23.706539 23.706539
+84 100 11.704700 11.704700 11.704700
+84 101 36.496575 36.496575 36.496575
+85 1 27.018512 27.018512 27.018512
+85 2 64.498062 64.498062 64.498062
+85 3 57.801384 57.801384 57.801384
+85 4 66.037868 66.037868 66.037868
+85 5 63.007936 63.007936 63.007936
+85 6 67.119297 67.119297 67.119297
+85 7 60.307545 60.307545 60.307545
+85 8 62.289646 62.289646 62.289646
+85 9 66.068147 66.068147 66.068147
+85 10 47.381431 47.381431 47.381431
+85 11 48.270074 48.270074 48.270074
+85 12 50.219518 50.219518 50.219518
+85 13 51.546096 51.546096 51.546096
+85 14 52.345009 52.345009 52.345009
+85 15 54.405882 54.405882 54.405882
+85 16 56.089215 56.089215 56.089215
+85 17 58.051701 58.051701 58.051701
+85 18 59.203040 59.203040 59.203040
+85 19 27.294688 27.294688 27.294688
+85 20 24.207437 24.207437 24.207437
+85 21 20.518285 20.518285 20.518285
+85 22 29.410882 29.410882 29.410882
+85 23 22.022716 22.022716 22.022716
+85 24 30.610456 30.610456 30.610456
+85 25 23.600847 23.600847 23.600847
+85 26 32.557641 32.557641 32.557641
+85 27 38.013156 38.013156 38.013156
+85 28 38.470768 38.470768 38.470768
+85 29 35.014283 35.014283 35.014283
+85 30 33.541020 33.541020 33.541020
+85 31 31.016125 31.016125 31.016125
+85 32 31.575307 31.575307 31.575307
+85 33 30.016662 30.016662 30.016662
+85 34 28.284271 28.284271 28.284271
+85 35 28.635642 28.635642 28.635642
+85 36 56.885851 56.885851 56.885851
+85 37 56.568542 56.568542 56.568542
+85 38 53.600373 53.600373 53.600373
+85 39 51.244512 51.244512 51.244512
+85 40 51.088159 51.088159 51.088159
+85 41 56.080300 56.080300 56.080300
+85 42 46.010868 46.010868 46.010868
+85 43 51.039201 51.039201 51.039201
+85 44 56.035703 56.035703 56.035703
+85 45 53.037722 53.037722 53.037722
+85 46 64.637450 64.637450 64.637450
+85 47 64.202804 64.202804 64.202804
+85 48 57.280014 57.280014 57.280014
+85 49 28.301943 28.301943 28.301943
+85 50 22.671568 22.671568 22.671568
+85 51 16.155494 16.155494 16.155494
+85 52 9.219544 9.219544 9.219544
+85 53 32.015621 32.015621 32.015621
+85 54 42.544095 42.544095 42.544095
+85 55 31.064449 31.064449 31.064449
+85 56 41.109610 41.109610 41.109610
+85 57 9.219544 9.219544 9.219544
+85 58 27.294688 27.294688 27.294688
+85 59 46.097722 46.097722 46.097722
+85 60 47.853944 47.853944 47.853944
+85 61 52.201533 52.201533 52.201533
+85 62 37.947332 37.947332 37.947332
+85 63 10.000000 10.000000 10.000000
+85 64 12.041595 12.041595 12.041595
+85 65 12.041595 12.041595 12.041595
+85 66 24.596748 24.596748 24.596748
+85 67 17.888544 17.888544 17.888544
+85 68 14.764823 14.764823 14.764823
+85 69 35.355339 35.355339 35.355339
+85 70 34.713110 34.713110 34.713110
+85 71 45.650849 45.650849 45.650849
+85 72 27.202941 27.202941 27.202941
+85 73 36.496575 36.496575 36.496575
+85 74 63.134776 63.134776 63.134776
+85 75 38.078866 38.078866 38.078866
+85 76 57.271284 57.271284 57.271284
+85 77 17.262677 17.262677 17.262677
+85 78 42.801869 42.801869 42.801869
+85 79 55.946403 55.946403 55.946403
+85 80 64.202804 64.202804 64.202804
+85 81 20.591260 20.591260 20.591260
+85 82 30.083218 30.083218 30.083218
+85 83 33.105891 33.105891 33.105891
+85 84 20.099751 20.099751 20.099751
+85 86 8.485281 8.485281 8.485281
+85 87 36.345564 36.345564 36.345564
+85 88 45.276926 45.276926 45.276926
+85 89 43.931765 43.931765 43.931765
+85 90 26.000000 26.000000 26.000000
+85 91 26.907248 26.907248 26.907248
+85 92 15.264338 15.264338 15.264338
+85 93 14.560220 14.560220 14.560220
+85 94 23.345235 23.345235 23.345235
+85 95 19.000000 19.000000 19.000000
+85 96 8.062258 8.062258 8.062258
+85 97 25.079872 25.079872 25.079872
+85 98 54.129474 54.129474 54.129474
+85 99 38.600518 38.600518 38.600518
+85 100 31.575307 31.575307 31.575307
+85 101 46.043458 46.043458 46.043458
+86 1 35.468296 35.468296 35.468296
+86 2 72.718636 72.718636 72.718636
+86 3 66.219333 66.219333 66.219333
+86 4 74.330344 74.330344 74.330344
+86 5 71.400280 71.400280 71.400280
+86 6 75.451971 75.451971 75.451971
+86 7 68.767725 68.767725 68.767725
+86 8 70.767224 70.767224 70.767224
+86 9 74.518454 74.518454 74.518454
+86 10 54.341513 54.341513 54.341513
+86 11 55.659680 55.659680 55.659680
+86 12 57.567352 57.567352 57.567352
+86 13 59.236813 59.236813 59.236813
+86 14 59.228372 59.228372 59.228372
+86 15 62.032250 62.032250 62.032250
+86 16 63.324561 63.324561 63.324561
+86 17 65.253352 65.253352 65.253352
+86 18 66.730802 66.730802 66.730802
+86 19 26.172505 26.172505 26.172505
+86 20 24.698178 24.698178 24.698178
+86 21 22.472205 22.472205 22.472205
+86 22 29.206164 29.206164 29.206164
+86 23 24.351591 24.351591 24.351591
+86 24 30.805844 30.805844 30.805844
+86 25 26.248809 26.248809 26.248809
+86 26 33.286634 33.286634 33.286634
+86 27 32.756679 32.756679 32.756679
+86 28 34.176015 34.176015 34.176015
+86 29 29.832868 29.832868 29.832868
+86 30 29.546573 29.546573 29.546573
+86 31 25.961510 25.961510 25.961510
+86 32 27.730849 27.730849 27.730849
+86 33 25.000000 25.000000 25.000000
+86 34 22.090722 22.090722 22.090722
+86 35 25.059928 25.059928 25.059928
+86 36 62.128898 62.128898 62.128898
+86 37 62.032250 62.032250 62.032250
+86 38 59.033889 59.033889 59.033889
+86 39 57.008771 57.008771 57.008771
+86 40 57.078893 57.078893 57.078893
+86 41 62.072538 62.072538 62.072538
+86 42 52.239832 52.239832 52.239832
+86 43 57.558666 57.558666 57.558666
+86 44 62.513998 62.513998 62.513998
+86 45 59.539903 59.539903 59.539903
+86 46 73.006849 73.006849 73.006849
+86 47 72.622311 72.622311 72.622311
+86 48 64.845971 64.845971 64.845971
+86 49 27.658633 27.658633 27.658633
+86 50 23.706539 23.706539 23.706539
+86 51 15.000000 15.000000 15.000000
+86 52 8.544004 8.544004 8.544004
+86 53 38.639358 38.639358 38.639358
+86 54 50.774009 50.774009 50.774009
+86 55 37.854986 37.854986 37.854986
+86 56 49.578221 49.578221 49.578221
+86 57 17.691806 17.691806 17.691806
+86 58 33.060551 33.060551 33.060551
+86 59 49.729267 49.729267 49.729267
+86 60 53.084838 53.084838 53.084838
+86 61 60.605280 60.605280 60.605280
+86 62 45.694639 45.694639 45.694639
+86 63 12.165525 12.165525 12.165525
+86 64 3.605551 3.605551 3.605551
+86 65 19.313208 19.313208 19.313208
+86 66 32.756679 32.756679 32.756679
+86 67 26.076810 26.076810 26.076810
+86 68 19.026298 19.026298 19.026298
+86 69 43.566042 43.566042 43.566042
+86 70 43.185646 43.185646 43.185646
+86 71 53.851648 53.851648 53.851648
+86 72 32.062439 32.062439 32.062439
+86 73 42.000000 42.000000 42.000000
+86 74 71.344236 71.344236 71.344236
+86 75 43.104524 43.104524 43.104524
+86 76 60.728906 60.728906 60.728906
+86 77 11.401754 11.401754 11.401754
+86 78 44.721360 44.721360 44.721360
+86 79 64.140471 64.140471 64.140471
+86 80 72.622311 72.622311 72.622311
+86 81 28.844410 28.844410 28.844410
+86 82 37.696154 37.696154 37.696154
+86 83 41.182521 41.182521 41.182521
+86 84 27.202941 27.202941 27.202941
+86 85 8.485281 8.485281 8.485281
+86 87 42.011903 42.011903 42.011903
+86 88 51.009803 51.009803 51.009803
+86 89 52.402290 52.402290 52.402290
+86 90 18.439089 18.439089 18.439089
+86 91 35.383612 35.383612 35.383612
+86 92 23.600847 23.600847 23.600847
+86 93 22.360680 22.360680 22.360680
+86 94 29.068884 29.068884 29.068884
+86 95 25.709920 25.709920 25.709920
+86 96 15.652476 15.652476 15.652476
+86 97 32.015621 32.015621 32.015621
+86 98 59.211485 59.211485 59.211485
+86 99 47.010637 47.010637 47.010637
+86 100 38.897301 38.897301 38.897301
+86 101 54.405882 54.405882 54.405882
+87 1 32.202484 32.202484 32.202484
+87 2 61.131007 61.131007 61.131007
+87 3 51.009803 51.009803 51.009803
+87 4 61.008196 61.008196 61.008196
+87 5 56.008928 56.008928 56.008928
+87 6 61.008196 61.008196 61.008196
+87 7 51.088159 51.088159 51.088159
+87 8 51.351728 51.351728 51.351728
+87 9 56.320511 56.320511 56.320511
+87 10 15.556349 15.556349 15.556349
+87 11 19.416488 19.416488 19.416488
+87 12 20.615528 20.615528 20.615528
+87 13 24.698178 24.698178 24.698178
+87 14 19.416488 19.416488 19.416488
+87 15 26.400758 26.400758 26.400758
+87 16 24.839485 24.839485 24.839485
+87 17 26.400758 26.400758 26.400758
+87 18 29.698485 29.698485 29.698485
+87 19 29.832868 29.832868 29.832868
+87 20 25.238859 25.238859 25.238859
+87 21 22.847319 22.847319 22.847319
+87 22 26.870058 26.870058 26.870058
+87 23 21.023796 21.023796 21.023796
+87 24 25.495098 25.495098 25.495098
+87 25 19.235384 19.235384 19.235384
+87 26 23.600847 23.600847 23.600847
+87 27 74.242845 74.242845 74.242845
+87 28 74.813100 74.813100 74.813100
+87 29 71.253070 71.253070 71.253070
+87 30 69.871310 69.871310 69.871310
+87 31 67.268120 67.268120 67.268120
+87 32 67.896981 67.896981 67.896981
+87 33 66.272166 66.272166 66.272166
+87 34 64.007812 64.007812 64.007812
+87 35 64.938432 64.938432 64.938432
+87 36 76.400262 76.400262 76.400262
+87 37 75.213031 75.213031 75.213031
+87 38 72.801099 72.801099 72.801099
+87 39 69.404611 69.404611 69.404611
+87 40 68.242216 68.242216 68.242216
+87 41 72.401657 72.401657 72.401657
+87 42 63.007936 63.007936 63.007936
+87 43 65.513357 65.513357 65.513357
+87 44 69.835521 69.835521 69.835521
+87 45 67.230945 67.230945 67.230945
+87 46 58.008620 58.008620 58.008620
+87 47 56.080300 56.080300 56.080300
+87 48 28.319605 28.319605 28.319605
+87 49 28.319605 28.319605 28.319605
+87 50 24.186773 24.186773 24.186773
+87 51 52.172790 52.172790 52.172790
+87 52 34.234486 34.234486 34.234486
+87 53 7.211103 7.211103 7.211103
+87 54 26.019224 26.019224 26.019224
+87 55 49.517674 49.517674 49.517674
+87 56 37.107951 37.107951 37.107951
+87 57 31.016125 31.016125 31.016125
+87 58 9.055385 9.055385 9.055385
+87 59 15.231546 15.231546 15.231546
+87 60 11.704700 11.704700 11.704700
+87 61 36.496575 36.496575 36.496575
+87 62 47.507894 47.507894 47.507894
+87 63 45.354162 45.354162 45.354162
+87 64 44.181444 44.181444 44.181444
+87 65 24.738634 24.738634 24.738634
+87 66 21.260292 21.260292 21.260292
+87 67 23.853721 23.853721 23.853721
+87 68 46.615448 46.615448 46.615448
+87 69 40.706265 40.706265 40.706265
+87 70 29.732137 29.732137 29.732137
+87 71 47.127487 47.127487 47.127487
+87 72 53.823787 53.823787 53.823787
+87 73 58.694122 58.694122 58.694122
+87 74 40.706265 40.706265 40.706265
+87 75 4.123106 4.123106 4.123106
+87 76 24.839485 24.839485 24.839485
+87 77 40.804412 40.804412 40.804412
+87 78 21.095023 21.095023 21.095023
+87 79 34.539832 34.539832 34.539832
+87 80 46.486557 46.486557 46.486557
+87 81 34.713110 34.713110 34.713110
+87 82 44.045431 44.045431 44.045431
+87 83 19.924859 19.924859 19.924859
+87 84 17.464249 17.464249 17.464249
+87 85 36.345564 36.345564 36.345564
+87 86 42.011903 42.011903 42.011903
+87 88 9.000000 9.000000 9.000000
+87 89 34.132096 34.132096 34.132096
+87 90 49.769469 49.769469 49.769469
+87 91 28.017851 28.017851 28.017851
+87 92 33.286634 33.286634 33.286634
+87 93 37.215588 37.215588 37.215588
+87 94 48.826222 48.826222 48.826222
+87 95 43.266615 43.266615 43.266615
+87 96 37.336309 37.336309 37.336309
+87 97 45.343136 45.343136 45.343136
+87 98 18.027756 18.027756 18.027756
+87 99 28.442925 28.442925 28.442925
+87 100 12.083046 12.083046 12.083046
+87 101 44.147480 44.147480 44.147480
+88 1 38.209946 38.209946 38.209946
+88 2 62.369865 62.369865 62.369865
+88 3 51.971146 51.971146 51.971146
+88 4 61.814238 61.814238 61.814238
+88 5 56.568542 56.568542 56.568542
+88 6 61.522354 61.522354 61.522354
+88 7 51.351728 51.351728 51.351728
+88 8 51.088159 51.088159 51.088159
+88 9 56.080300 56.080300 56.080300
+88 10 11.180340 11.180340 11.180340
+88 11 16.124515 16.124515 16.124515
+88 12 16.492423 16.492423 16.492423
+88 13 21.377558 21.377558 21.377558
+88 14 13.038405 13.038405 13.038405
+88 15 22.135944 22.135944 22.135944
+88 16 18.867962 18.867962 18.867962
+88 17 20.000000 20.000000 20.000000
+88 18 24.186773 24.186773 24.186773
+88 19 37.215588 37.215588 37.215588
+88 20 33.105891 33.105891 33.105891
+88 21 31.320920 31.320920 31.320920
+88 22 33.837849 33.837849 33.837849
+88 23 29.410882 29.410882 29.410882
+88 24 32.202484 32.202484 32.202484
+88 25 27.513633 27.513633 27.513633
+88 26 29.832868 29.832868 29.832868
+88 27 83.216585 83.216585 83.216585
+88 28 83.725743 83.725743 83.725743
+88 29 80.224684 80.224684 80.224684
+88 30 78.771822 78.771822 78.771822
+88 31 76.236474 76.236474 76.236474
+88 32 76.791927 76.791927 76.791927
+88 33 75.239617 75.239617 75.239617
+88 34 73.006849 73.006849 73.006849
+88 35 73.824115 73.824115 73.824115
+88 36 82.134037 82.134037 82.134037
+88 37 80.808415 80.808415 80.808415
+88 38 78.568442 78.568442 78.568442
+88 39 75.073298 75.073298 75.073298
+88 40 73.756356 73.756356 73.756356
+88 41 77.620873 77.620873 77.620873
+88 42 68.680419 68.680419 68.680419
+88 43 70.604532 70.604532 70.604532
+88 44 74.632433 74.632433 74.632433
+88 45 72.201108 72.201108 72.201108
+88 46 58.549125 58.549125 58.549125
+88 47 56.320511 56.320511 56.320511
+88 48 23.259407 23.259407 23.259407
+88 49 35.510562 35.510562 35.510562
+88 50 32.310989 32.310989 32.310989
+88 51 61.000000 61.000000 61.000000
+88 52 43.185646 43.185646 43.185646
+88 53 14.317821 14.317821 14.317821
+88 54 27.202941 27.202941 27.202941
+88 55 56.080300 56.080300 56.080300
+88 56 40.249224 40.249224 40.249224
+88 57 39.560081 39.560081 39.560081
+88 58 18.027756 18.027756 18.027756
+88 59 14.317821 14.317821 14.317821
+88 60 4.472136 4.472136 4.472136
+88 61 36.124784 36.124784 36.124784
+88 62 52.630789 52.630789 52.630789
+88 63 54.129474 54.129474 54.129474
+88 64 53.150729 53.150729 53.150729
+88 65 33.541020 33.541020 33.541020
+88 66 28.017851 28.017851 28.017851
+88 67 31.780497 31.780497 31.780497
+88 68 55.027266 55.027266 55.027266
+88 69 45.607017 45.607017 45.607017
+88 70 33.837849 33.837849 33.837849
+88 71 50.537115 50.537115 50.537115
+88 72 61.400326 61.400326 61.400326
+88 73 65.436993 65.436993 65.436993
+88 74 37.363083 37.363083 37.363083
+88 75 8.944272 8.944272 8.944272
+88 76 20.248457 20.248457 20.248457
+88 77 49.477268 49.477268 49.477268
+88 78 23.706539 23.706539 23.706539
+88 79 32.249031 32.249031 32.249031
+88 80 44.407207 44.407207 44.407207
+88 81 41.880783 41.880783 41.880783
+88 82 50.249378 50.249378 50.249378
+88 83 24.207437 24.207437 24.207437
+88 84 25.961510 25.961510 25.961510
+88 85 45.276926 45.276926 45.276926
+88 86 51.009803 51.009803 51.009803
+88 87 9.000000 9.000000 9.000000
+88 89 36.055513 36.055513 36.055513
+88 90 58.189346 58.189346 58.189346
+88 91 33.970576 33.970576 33.970576
+88 92 41.146081 41.146081 41.146081
+88 93 45.188494 45.188494 45.188494
+88 94 56.435804 56.435804 56.435804
+88 95 51.000000 51.000000 51.000000
+88 96 45.880279 45.880279 45.880279
+88 97 52.430907 52.430907 52.430907
+88 98 10.000000 10.000000 10.000000
+88 99 31.304952 31.304952 31.304952
+88 100 17.804494 17.804494 17.804494
+88 101 47.010637 47.010637 47.010637
+89 1 17.888544 17.888544 17.888544
+89 2 27.018512 27.018512 27.018512
+89 3 17.117243 17.117243 17.117243
+89 4 27.073973 27.073973 27.073973
+89 5 22.360680 22.360680 22.360680
+89 6 27.294688 27.294688 27.294688
+89 7 18.027756 18.027756 18.027756
+89 8 19.235384 19.235384 19.235384
+89 9 23.769729 23.769729 23.769729
+89 10 26.925824 26.925824 26.925824
+89 11 22.803509 22.803509 22.803509
+89 12 24.083189 24.083189 24.083189
+89 13 20.615528 20.615528 20.615528
+89 14 29.832868 29.832868 29.832868
+89 15 23.021729 23.021729 23.021729
+89 16 28.425341 28.425341 28.425341
+89 17 30.000000 30.000000 30.000000
+89 18 27.294688 27.294688 27.294688
+89 19 56.648036 56.648036 56.648036
+89 20 51.264022 51.264022 51.264022
+89 21 46.615448 46.615448 46.615448
+89 22 55.362442 55.362442 55.362442
+89 23 45.880279 45.880279 45.880279
+89 24 54.817880 54.817880 54.817880
+89 25 45.221676 45.221676 45.221676
+89 26 54.129474 54.129474 54.129474
+89 27 76.321688 76.321688 76.321688
+89 28 74.632433 74.632433 74.632433
+89 29 73.539105 73.539105 73.539105
+89 30 69.892775 69.892775 69.892775
+89 31 69.856997 69.856997 69.856997
+89 32 68.007353 68.007353 68.007353
+89 33 68.942005 68.942005 68.942005
+89 34 69.354164 69.354164 69.354164
+89 35 65.192024 65.192024 65.192024
+89 36 50.774009 50.774009 50.774009
+89 37 49.091751 49.091751 49.091751
+89 38 47.507894 47.507894 47.507894
+89 39 43.908997 43.908997 43.908997
+89 40 42.190046 42.190046 42.190046
+89 41 45.000000 45.000000 45.000000
+89 42 38.013156 38.013156 38.013156
+89 43 38.013156 38.013156 38.013156
+89 44 41.109610 41.109610 41.109610
+89 45 39.204592 39.204592 39.204592
+89 46 24.331050 24.331050 24.331050
+89 47 22.803509 22.803509 22.803509
+89 48 25.553865 25.553865 25.553865
+89 49 55.973208 55.973208 55.973208
+89 50 49.396356 49.396356 49.396356
+89 51 53.225934 53.225934 53.225934
+89 52 49.040799 49.040799 49.040799
+89 53 28.017851 28.017851 28.017851
+89 54 8.944272 8.944272 8.944272
+89 55 31.064449 31.064449 31.064449
+89 56 6.324555 6.324555 6.324555
+89 57 34.713110 34.713110 34.713110
+89 58 33.541020 33.541020 33.541020
+89 59 48.836462 48.836462 48.836462
+89 60 40.496913 40.496913 40.496913
+89 61 9.219544 9.219544 9.219544
+89 62 22.135944 22.135944 22.135944
+89 63 47.010637 47.010637 47.010637
+89 64 55.901699 55.901699 55.901699
+89 65 35.000000 35.000000 35.000000
+89 66 21.095023 21.095023 21.095023
+89 67 27.018512 27.018512 27.018512
+89 68 43.081318 43.081318 43.081318
+89 69 16.124515 16.124515 16.124515
+89 70 9.219544 9.219544 9.219544
+89 71 15.556349 15.556349 15.556349
+89 72 41.109610 41.109610 41.109610
+89 73 39.623226 39.623226 39.623226
+89 74 22.090722 22.090722 22.090722
+89 75 38.209946 38.209946 38.209946
+89 76 56.302753 56.302753 56.302753
+89 77 58.412327 58.412327 58.412327
+89 78 55.009090 55.009090 55.009090
+89 79 16.124515 16.124515 16.124515
+89 80 20.591260 20.591260 20.591260
+89 81 25.495098 25.495098 25.495098
+89 82 25.000000 25.000000 25.000000
+89 83 15.297059 15.297059 15.297059
+89 84 29.966648 29.966648 29.966648
+89 85 43.931765 43.931765 43.931765
+89 86 52.402290 52.402290 52.402290
+89 87 34.132096 34.132096 34.132096
+89 88 36.055513 36.055513 36.055513
+89 90 68.249542 68.249542 68.249542
+89 91 17.029386 17.029386 17.029386
+89 92 29.681644 29.681644 29.681644
+89 93 32.649655 32.649655 32.649655
+89 94 37.483330 37.483330 37.483330
+89 95 34.481879 34.481879 34.481879
+89 96 38.275318 38.275318 38.275318
+89 97 31.256999 31.256999 31.256999
+89 98 44.721360 44.721360 44.721360
+89 99 6.324555 6.324555 6.324555
+89 100 23.086793 23.086793 23.086793
+89 101 11.401754 11.401754 11.401754
+90 1 52.478567 52.478567 52.478567
+90 2 90.354856 90.354856 90.354856
+90 3 83.216585 83.216585 83.216585
+90 4 91.787799 91.787799 91.787799
+90 5 88.509886 88.509886 88.509886
+90 6 92.784697 92.784697 92.784697
+90 7 85.445889 85.445889 85.445889
+90 8 87.200917 87.200917 87.200917
+90 9 91.263355 91.263355 91.263355
+90 10 64.412732 64.412732 64.412732
+90 11 66.887966 66.887966 66.887966
+90 12 68.600292 68.600292 68.600292
+90 13 71.281134 71.281134 71.281134
+90 14 68.876701 68.876701 68.876701
+90 15 73.783467 73.783467 73.783467
+90 16 73.824115 73.824115 73.824115
+90 17 75.591005 75.591005 75.591005
+90 18 78.032045 78.032045 78.032045
+90 19 23.000000 23.000000 23.000000
+90 20 25.495098 25.495098 25.495098
+90 21 26.925824 26.925824 26.925824
+90 22 27.000000 27.000000 27.000000
+90 23 28.792360 28.792360 28.792360
+90 24 29.000000 29.000000 29.000000
+90 25 30.675723 30.675723 30.675723
+90 26 32.000000 32.000000 32.000000
+90 27 37.536649 37.536649 37.536649
+90 28 41.036569 41.036569 41.036569
+90 29 35.355339 35.355339 35.355339
+90 30 37.802116 37.802116 37.802116
+90 31 32.649655 32.649655 32.649655
+90 32 36.619667 36.619667 36.619667
+90 33 32.015621 32.015621 32.015621
+90 34 26.907248 26.907248 26.907248
+90 35 34.985711 34.985711 34.985711
+90 36 80.000000 80.000000 80.000000
+90 37 80.024996 80.024996 80.024996
+90 38 77.025970 77.025970 77.025970
+90 39 75.166482 75.166482 75.166482
+90 40 75.325958 75.325958 75.325958
+90 41 80.305666 80.305666 80.305666
+90 42 70.576200 70.576200 70.576200
+90 43 75.953933 75.953933 75.953933
+90 44 80.894994 80.894994 80.894994
+90 45 77.929455 77.929455 77.929455
+90 46 90.210864 90.210864 90.210864
+90 47 89.587946 89.587946 89.587946
+90 48 76.321688 76.321688 76.321688
+90 49 25.000000 25.000000 25.000000
+90 50 25.961510 25.961510 25.961510
+90 51 30.413813 30.413813 30.413813
+90 52 19.209373 19.209373 19.209373
+90 53 48.877398 48.877398 48.877398
+90 54 65.069194 65.069194 65.069194
+90 55 56.293872 56.293872 56.293872
+90 56 66.287254 66.287254 66.287254
+90 57 34.481879 34.481879 34.481879
+90 58 42.059482 42.059482 42.059482
+90 59 52.239832 52.239832 52.239832
+90 60 58.940648 58.940648 58.940648
+90 61 75.690158 75.690158 75.690158
+90 62 63.906181 63.906181 63.906181
+90 63 30.066593 30.066593 30.066593
+90 64 15.132746 15.132746 15.132746
+90 65 33.301652 33.301652 33.301652
+90 66 47.423623 47.423623 47.423623
+90 67 41.231056 41.231056 41.231056
+90 68 37.121422 37.121422 37.121422
+90 69 61.269895 61.269895 61.269895
+90 70 59.203040 59.203040 59.203040
+90 71 71.554175 71.554175 71.554175
+90 72 50.039984 50.039984 50.039984
+90 73 60.133186 60.133186 60.133186
+90 74 85.146932 85.146932 85.146932
+90 75 49.335586 49.335586 49.335586
+90 76 62.000000 62.000000 62.000000
+90 77 9.899495 9.899495 9.899495
+90 78 44.045431 44.045431 44.045431
+90 79 77.987178 77.987178 77.987178
+90 80 87.692645 87.692645 87.692645
+90 81 46.518813 46.518813 46.518813
+90 82 55.973208 55.973208 55.973208
+90 83 55.172457 55.172457 55.172457
+90 84 39.698866 39.698866 39.698866
+90 85 26.000000 26.000000 26.000000
+90 86 18.439089 18.439089 18.439089
+90 87 49.769469 49.769469 49.769469
+90 88 58.189346 58.189346 58.189346
+90 89 68.249542 68.249542 68.249542
+90 91 51.613952 51.613952 51.613952
+90 92 41.146081 41.146081 41.146081
+90 93 40.496913 40.496913 40.496913
+90 94 47.381431 47.381431 47.381431
+90 95 44.147480 44.147480 44.147480
+90 96 33.837849 33.837849 33.837849
+90 97 50.447993 50.447993 50.447993
+90 98 64.327288 64.327288 64.327288
+90 99 62.369865 62.369865 62.369865
+90 100 50.803543 50.803543 50.803543
+90 101 71.693793 71.693793 71.693793
+91 1 4.242641 4.242641 4.242641
+91 2 39.849718 39.849718 39.849718
+91 3 31.764760 31.764760 31.764760
+91 4 40.853396 40.853396 40.853396
+91 5 37.121422 37.121422 37.121422
+91 6 41.629317 41.629317 41.629317
+91 7 33.837849 33.837849 33.837849
+91 8 35.608988 35.608988 35.608988
+91 9 39.661064 39.661064 39.661064
+91 10 29.546573 29.546573 29.546573
+91 11 27.892651 27.892651 27.892651
+91 12 29.832868 29.832868 29.832868
+91 13 29.068884 29.068884 29.068884
+91 14 34.176015 34.176015 34.176015
+91 15 32.062439 32.062439 32.062439
+91 16 35.693137 35.693137 35.693137
+91 17 37.656341 37.656341 37.656341
+91 18 37.054015 37.054015 37.054015
+91 19 42.579338 42.579338 42.579338
+91 20 37.336309 37.336309 37.336309
+91 21 32.388269 32.388269 32.388269
+91 22 42.107007 42.107007 42.107007
+91 23 32.140317 32.140317 32.140317
+91 24 42.011903 42.011903 42.011903
+91 25 32.015621 32.015621 32.015621
+91 26 42.047592 42.047592 42.047592
+91 27 60.440053 60.440053 60.440053
+91 28 59.228372 59.228372 59.228372
+91 29 57.567352 57.567352 57.567352
+91 30 54.341513 54.341513 54.341513
+91 31 53.758720 53.758720 53.758720
+91 32 52.392748 52.392748 52.392748
+91 33 52.810984 52.810984 52.810984
+91 34 52.801515 52.801515 52.801515
+91 35 49.477268 49.477268 49.477268
+91 36 48.414874 48.414874 48.414874
+91 37 47.201695 47.201695 47.201695
+91 38 44.821870 44.821870 44.821870
+91 39 41.400483 41.400483 41.400483
+91 40 40.224371 40.224371 40.224371
+91 41 44.418465 44.418465 44.418465
+91 42 35.000000 35.000000 35.000000
+91 43 37.589892 37.589892 37.589892
+91 44 42.047592 42.047592 42.047592
+91 45 39.357337 39.357337 39.357337
+91 46 38.910153 38.910153 38.910153
+91 47 38.078866 38.078866 38.078866
+91 48 35.057096 35.057096 35.057096
+91 49 42.296572 42.296572 42.296572
+91 50 35.355339 35.355339 35.355339
+91 51 37.000000 37.000000 37.000000
+91 52 32.449961 32.449961 32.449961
+91 53 20.808652 20.808652 20.808652
+91 54 17.262677 17.262677 17.262677
+91 55 22.203603 22.203603 22.203603
+91 56 14.764823 14.764823 14.764823
+91 57 17.691806 17.691806 17.691806
+91 58 23.086793 23.086793 23.086793
+91 59 43.046487 43.046487 43.046487
+91 60 38.183766 38.183766 38.183766
+91 61 25.553865 25.553865 25.553865
+91 62 19.697716 19.697716 19.697716
+91 63 30.463092 30.463092 30.463092
+91 64 38.897301 38.897301 38.897301
+91 65 18.788294 18.788294 18.788294
+91 66 7.280110 7.280110 7.280110
+91 67 10.770330 10.770330 10.770330
+91 68 27.459060 27.459060 27.459060
+91 69 13.341664 13.341664 13.341664
+91 70 7.810250 7.810250 7.810250
+91 71 22.090722 22.090722 22.090722
+91 72 29.120440 29.120440 29.120440
+91 73 31.622777 31.622777 31.622777
+91 74 37.336309 37.336309 37.336309
+91 75 31.906112 31.906112 31.906112
+91 76 52.801515 52.801515 52.801515
+91 77 41.880783 41.880783 41.880783
+91 78 46.173586 46.173586 46.173586
+91 79 30.364453 30.364453 30.364453
+91 80 37.443290 37.443290 37.443290
+91 81 10.000000 10.000000 10.000000
+91 82 16.278821 16.278821 16.278821
+91 83 10.770330 10.770330 10.770330
+91 84 16.000000 16.000000 16.000000
+91 85 26.907248 26.907248 26.907248
+91 86 35.383612 35.383612 35.383612
+91 87 28.017851 28.017851 28.017851
+91 88 33.970576 33.970576 33.970576
+91 89 17.029386 17.029386 17.029386
+91 90 51.613952 51.613952 51.613952
+91 92 13.000000 13.000000 13.000000
+91 93 16.492423 16.492423 16.492423
+91 94 24.515301 24.515301 24.515301
+91 95 20.024984 20.024984 20.024984
+91 96 21.470911 21.470911 21.470911
+91 97 19.313208 19.313208 19.313208
+91 98 43.931765 43.931765 43.931765
+91 99 12.083046 12.083046 12.083046
+91 100 16.278821 16.278821 16.278821
+91 101 20.880613 20.880613 20.880613
+92 1 12.041595 12.041595 12.041595
+92 2 49.244289 49.244289 49.244289
+92 3 42.638011 42.638011 42.638011
+92 4 50.774009 50.774009 50.774009
+92 5 47.801674 47.801674 47.801674
+92 6 51.865210 51.865210 51.865210
+92 7 45.276926 45.276926 45.276926
+92 8 47.381431 47.381431 47.381431
+92 9 50.990195 50.990195 50.990195
+92 10 39.623226 39.623226 39.623226
+92 11 39.051248 39.051248 39.051248
+92 12 41.048752 41.048752 41.048752
+92 13 41.109610 41.109610 41.109610
+92 14 44.553339 44.553339 44.553339
+92 15 44.102154 44.102154 44.102154
+92 16 47.042534 47.042534 47.042534
+92 17 49.040799 49.040799 49.040799
+92 18 49.091751 49.091751 49.091751
+92 19 37.336309 37.336309 37.336309
+92 20 32.756679 32.756679 32.756679
+92 21 27.892651 27.892651 27.892651
+92 22 38.078866 38.078866 38.078866
+92 23 28.460499 28.460499 28.460499
+92 24 38.600518 38.600518 38.600518
+92 25 29.154759 29.154759 29.154759
+92 26 39.560081 39.560081 39.560081
+92 27 47.539457 47.539457 47.539457
+92 28 46.529560 46.529560 46.529560
+92 29 44.643029 44.643029 44.643029
+92 30 41.593269 41.593269 41.593269
+92 31 40.804412 40.804412 40.804412
+92 32 39.623226 39.623226 39.623226
+92 33 39.849718 39.849718 39.849718
+92 34 39.812058 39.812058 39.812058
+92 35 36.674242 36.674242 36.674242
+92 36 46.615448 46.615448 46.615448
+92 37 45.880279 45.880279 45.880279
+92 38 43.081318 43.081318 43.081318
+92 39 40.162171 40.162171 40.162171
+92 40 39.560081 39.560081 39.560081
+92 41 44.384682 44.384682 44.384682
+92 42 34.205263 34.205263 34.205263
+92 43 38.470768 38.470768 38.470768
+92 44 43.416587 43.416587 43.416587
+92 45 40.447497 40.447497 40.447497
+92 46 49.406477 49.406477 49.406477
+92 47 49.040799 49.040799 49.040799
+92 48 47.095647 47.095647 47.095647
+92 49 37.656341 37.656341 37.656341
+92 50 30.805844 30.805844 30.805844
+92 51 24.041631 24.041631 24.041631
+92 52 22.803509 22.803509 22.803509
+92 53 26.832816 26.832816 26.832816
+92 54 30.083218 30.083218 30.083218
+92 55 18.973666 18.973666 18.973666
+92 56 26.172505 26.172505 26.172505
+92 57 7.071068 7.071068 7.071068
+92 58 25.495098 25.495098 25.495098
+92 59 46.690470 46.690470 46.690470
+92 60 44.777226 44.777226 44.777226
+92 61 38.470768 38.470768 38.470768
+92 62 23.345235 23.345235 23.345235
+92 63 17.464249 17.464249 17.464249
+92 64 27.202941 27.202941 27.202941
+92 65 12.649111 12.649111 12.649111
+92 66 14.142136 14.142136 14.142136
+92 67 9.433981 9.433981 9.433981
+92 68 15.000000 15.000000 15.000000
+92 69 20.124612 20.124612 20.124612
+92 70 20.591260 20.591260 20.591260
+92 71 30.413813 30.413813 30.413813
+92 72 20.615528 20.615528 20.615528
+92 73 26.925824 26.925824 26.925824
+92 74 50.328918 50.328918 50.328918
+92 75 36.400549 36.400549 36.400549
+92 76 57.489129 57.489129 57.489129
+92 77 31.953091 31.953091 31.953091
+92 78 46.872167 46.872167 46.872167
+92 79 43.324358 43.324358 43.324358
+92 80 50.249378 50.249378 50.249378
+92 81 5.385165 5.385165 5.385165
+92 82 16.000000 16.000000 16.000000
+92 83 22.022716 22.022716 22.022716
+92 84 16.278821 16.278821 16.278821
+92 85 15.264338 15.264338 15.264338
+92 86 23.600847 23.600847 23.600847
+92 87 33.286634 33.286634 33.286634
+92 88 41.146081 41.146081 41.146081
+92 89 29.681644 29.681644 29.681644
+92 90 41.146081 41.146081 41.146081
+92 91 13.000000 13.000000 13.000000
+92 93 4.123106 4.123106 4.123106
+92 94 15.620499 15.620499 15.620499
+92 95 10.000000 10.000000 10.000000
+92 96 8.602325 8.602325 8.602325
+92 97 13.416408 13.416408 13.416408
+92 98 51.000000 51.000000 51.000000
+92 99 25.079872 25.079872 25.079872
+92 100 24.041631 24.041631 24.041631
+92 101 30.805844 30.805844 30.805844
+93 1 14.764823 14.764823 14.764823
+93 2 50.477718 50.477718 50.477718
+93 3 44.553339 44.553339 44.553339
+93 4 52.201533 52.201533 52.201533
+93 5 49.578221 49.578221 49.578221
+93 6 53.413481 53.413481 53.413481
+93 7 47.423623 47.423623 47.423623
+93 8 49.678969 49.678969 49.678969
+93 9 53.037722 53.037722 53.037722
+93 10 43.737855 43.737855 43.737855
+93 11 43.104524 43.104524 43.104524
+93 12 45.099889 45.099889 45.099889
+93 13 45.044423 45.044423 45.044423
+93 14 48.662100 48.662100 48.662100
+93 15 48.041649 48.041649 48.041649
+93 16 51.088159 51.088159 51.088159
+93 17 53.084838 53.084838 53.084838
+93 18 53.037722 53.037722 53.037722
+93 19 39.051248 39.051248 39.051248
+93 20 34.785054 34.785054 34.785054
+93 21 30.083218 30.083218 30.083218
+93 22 40.162171 40.162171 40.162171
+93 23 30.870698 30.870698 30.870698
+93 24 40.853396 40.853396 40.853396
+93 25 31.764760 31.764760 31.764760
+93 26 42.047592 42.047592 42.047592
+93 27 43.965896 43.965896 43.965896
+93 28 42.755117 42.755117 42.755117
+93 29 41.109610 41.109610 41.109610
+93 30 37.854986 37.854986 37.854986
+93 31 37.336309 37.336309 37.336309
+93 32 35.902646 35.902646 35.902646
+93 33 36.400549 36.400549 36.400549
+93 34 36.715120 36.715120 36.715120
+93 35 32.984845 32.984845 32.984845
+93 36 44.271887 44.271887 44.271887
+93 37 43.680659 43.680659 43.680659
+93 38 40.804412 40.804412 40.804412
+93 39 38.078866 38.078866 38.078866
+93 40 37.656341 37.656341 37.656341
+93 41 42.579338 42.579338 42.579338
+93 42 32.388269 32.388269 32.388269
+93 43 37.054015 37.054015 37.054015
+93 44 42.047592 42.047592 42.047592
+93 45 39.051248 39.051248 39.051248
+93 46 51.088159 51.088159 51.088159
+93 47 50.931326 50.931326 50.931326
+93 48 51.039201 51.039201 51.039201
+93 49 39.560081 39.560081 39.560081
+93 50 32.893768 32.893768 32.893768
+93 51 20.615528 20.615528 20.615528
+93 52 23.086793 23.086793 23.086793
+93 53 30.870698 30.870698 30.870698
+93 54 33.734256 33.734256 33.734256
+93 55 17.117243 17.117243 17.117243
+93 56 28.600699 28.600699 28.600699
+93 57 8.544004 8.544004 8.544004
+93 58 29.206164 29.206164 29.206164
+93 59 50.328918 50.328918 50.328918
+93 60 48.764741 48.764741 48.764741
+93 61 41.629317 41.629317 41.629317
+93 62 23.409400 23.409400 23.409400
+93 63 14.422205 14.422205 14.422205
+93 64 25.942244 25.942244 25.942244
+93 65 15.264338 15.264338 15.264338
+93 66 18.248288 18.248288 18.248288
+93 67 13.416408 13.416408 13.416408
+93 68 11.045361 11.045361 11.045361
+93 69 21.400935 21.400935 21.400935
+93 70 23.769729 23.769729 23.769729
+93 71 31.622777 31.622777 31.622777
+93 72 16.970563 16.970563 16.970563
+93 73 24.166092 24.166092 24.166092
+93 74 53.758720 53.758720 53.758720
+93 75 40.224371 40.224371 40.224371
+93 76 61.220911 61.220911 61.220911
+93 77 31.780497 31.780497 31.780497
+93 78 50.000000 50.000000 50.000000
+93 79 46.840154 46.840154 46.840154
+93 80 53.235327 53.235327 53.235327
+93 81 7.211103 7.211103 7.211103
+93 82 15.524175 15.524175 15.524175
+93 83 26.000000 26.000000 26.000000
+93 84 20.000000 20.000000 20.000000
+93 85 14.560220 14.560220 14.560220
+93 86 22.360680 22.360680 22.360680
+93 87 37.215588 37.215588 37.215588
+93 88 45.188494 45.188494 45.188494
+93 89 32.649655 32.649655 32.649655
+93 90 40.496913 40.496913 40.496913
+93 91 16.492423 16.492423 16.492423
+93 92 4.123106 4.123106 4.123106
+93 94 12.041595 12.041595 12.041595
+93 95 6.403124 6.403124 6.403124
+93 96 6.708204 6.708204 6.708204
+93 97 11.180340 11.180340 11.180340
+93 98 55.009090 55.009090 55.009090
+93 99 28.460499 28.460499 28.460499
+93 100 28.160256 28.160256 28.160256
+93 101 32.557641 32.557641 32.557641
+94 1 21.095023 21.095023 21.095023
+94 2 48.836462 48.836462 48.836462
+94 3 45.276926 45.276926 45.276926
+94 4 51.088159 51.088159 51.088159
+94 5 49.648766 49.648766 49.648766
+94 6 52.630789 52.630789 52.630789
+94 7 48.764741 48.764741 48.764741
+94 8 51.429563 51.429563 51.429563
+94 9 53.851648 53.851648 53.851648
+94 10 53.758720 53.758720 53.758720
+94 11 52.392748 52.392748 52.392748
+94 12 54.341513 54.341513 54.341513
+94 13 53.460266 53.460266 53.460266
+94 14 58.523500 58.523500 58.523500
+94 15 56.435804 56.435804 56.435804
+94 16 60.207973 60.207973 60.207973
+94 17 62.169124 62.169124 62.169124
+94 18 61.400326 61.400326 61.400326
+94 19 49.979996 49.979996 49.979996
+94 20 46.097722 46.097722 46.097722
+94 21 41.593269 41.593269 41.593269
+94 22 51.478151 51.478151 51.478151
+94 23 42.544095 42.544095 42.544095
+94 24 52.325902 52.325902 52.325902
+94 25 43.566042 43.566042 43.566042
+94 26 53.712196 53.712196 53.712196
+94 27 40.496913 40.496913 40.496913
+94 28 38.013156 38.013156 38.013156
+94 29 38.013156 38.013156 38.013156
+94 30 33.615473 33.615473 33.615473
+94 31 34.828150 34.828150 34.828150
+94 32 31.906112 31.906112 31.906112
+94 33 34.058773 34.058773 34.058773
+94 34 36.124784 36.124784 36.124784
+94 35 29.410882 29.410882 29.410882
+94 36 33.541020 33.541020 33.541020
+94 37 33.241540 33.241540 33.241540
+94 38 30.265492 30.265492 30.265492
+94 39 28.017851 28.017851 28.017851
+94 40 28.017851 28.017851 28.017851
+94 41 33.015148 33.015148 33.015148
+94 42 23.194827 23.194827 23.194827
+94 43 28.635642 28.635642 28.635642
+94 44 33.541020 33.541020 33.541020
+94 45 30.594117 30.594117 30.594117
+94 46 50.803543 50.803543 50.803543
+94 47 51.312766 51.312766 51.312766
+94 48 59.413803 59.413803 59.413803
+94 49 50.695167 50.695167 50.695167
+94 50 44.283180 44.283180 44.283180
+94 51 20.248457 20.248457 20.248457
+94 52 32.557641 32.557641 32.557641
+94 53 42.190046 42.190046 42.190046
+94 54 41.048752 41.048752 41.048752
+94 55 10.000000 10.000000 10.000000
+94 56 32.015621 32.015621 32.015621
+94 57 20.248457 20.248457 20.248457
+94 58 41.109610 41.109610 41.109610
+94 59 62.289646 62.289646 62.289646
+94 60 60.207973 60.207973 60.207973
+94 61 46.690470 46.690470 46.690470
+94 62 20.615528 20.615528 20.615528
+94 63 17.464249 17.464249 17.464249
+94 64 32.249031 32.249031 32.249031
+94 65 27.202941 27.202941 27.202941
+94 66 28.635642 28.635642 28.635642
+94 67 25.000000 25.000000 25.000000
+94 68 10.440307 10.440307 10.440307
+94 69 22.472205 22.472205 22.472205
+94 70 30.000000 30.000000 30.000000
+94 71 31.064449 31.064449 31.064449
+94 72 5.000000 5.000000 5.000000
+94 73 13.152946 13.152946 13.152946
+94 74 59.539903 59.539903 59.539903
+94 75 52.009614 52.009614 52.009614
+94 76 73.109507 73.109507 73.109507
+94 77 40.012498 40.012498 40.012498
+94 78 62.008064 62.008064 62.008064
+94 79 53.150729 53.150729 53.150729
+94 80 57.280014 57.280014 57.280014
+94 81 14.866069 14.866069 14.866069
+94 82 13.416408 13.416408 13.416408
+94 83 35.171011 35.171011 35.171011
+94 84 31.890437 31.890437 31.890437
+94 85 23.345235 23.345235 23.345235
+94 86 29.068884 29.068884 29.068884
+94 87 48.826222 48.826222 48.826222
+94 88 56.435804 56.435804 56.435804
+94 89 37.483330 37.483330 37.483330
+94 90 47.381431 47.381431 47.381431
+94 91 24.515301 24.515301 24.515301
+94 92 15.620499 15.620499 15.620499
+94 93 12.041595 12.041595 12.041595
+94 95 5.656854 5.656854 5.656854
+94 96 15.811388 15.811388 15.811388
+94 97 6.324555 6.324555 6.324555
+94 98 66.370174 66.370174 66.370174
+94 99 35.000000 35.000000 35.000000
+94 100 38.910153 38.910153 38.910153
+94 101 33.541020 33.541020 33.541020
+95 1 17.117243 17.117243 17.117243
+95 2 48.918299 48.918299 48.918299
+95 3 44.204072 44.204072 44.204072
+95 4 50.931326 50.931326 50.931326
+95 5 48.918299 48.918299 48.918299
+95 6 52.325902 52.325902 52.325902
+95 7 47.434165 47.434165 47.434165
+95 8 49.929951 49.929951 49.929951
+95 9 52.801515 52.801515 52.801515
+95 10 48.764741 48.764741 48.764741
+95 11 47.675990 47.675990 47.675990
+95 12 49.648766 49.648766 49.648766
+95 13 49.091751 49.091751 49.091751
+95 14 53.600373 53.600373 53.600373
+95 15 52.086467 52.086467 52.086467
+95 16 55.578773 55.578773 55.578773
+95 17 57.558666 57.558666 57.558666
+95 18 57.078893 57.078893 57.078893
+95 19 44.922155 44.922155 44.922155
+95 20 40.853396 40.853396 40.853396
+95 21 36.249138 36.249138 36.249138
+95 22 46.238512 46.238512 46.238512
+95 23 37.121422 37.121422 37.121422
+95 24 47.010637 47.010637 47.010637
+95 25 38.078866 38.078866 38.078866
+95 26 48.301139 48.301139 48.301139
+95 27 42.047592 42.047592 42.047592
+95 28 40.162171 40.162171 40.162171
+95 29 39.357337 39.357337 39.357337
+95 30 35.468296 35.468296 35.468296
+95 31 35.846897 35.846897 35.846897
+95 32 33.615473 33.615473 33.615473
+95 33 34.985711 34.985711 34.985711
+95 34 36.235342 36.235342 36.235342
+95 35 30.870698 30.870698 30.870698
+95 36 38.327536 38.327536 38.327536
+95 37 37.854986 37.854986 37.854986
+95 38 34.928498 34.928498 34.928498
+95 39 32.388269 32.388269 32.388269
+95 40 32.140317 32.140317 32.140317
+95 41 37.121422 37.121422 37.121422
+95 42 27.018512 27.018512 27.018512
+95 43 32.062439 32.062439 32.062439
+95 44 37.054015 37.054015 37.054015
+95 45 34.058773 34.058773 34.058773
+95 46 50.249378 50.249378 50.249378
+95 47 50.447993 50.447993 50.447993
+95 48 55.081757 55.081757 55.081757
+95 49 45.541190 45.541190 45.541190
+95 50 39.000000 39.000000 39.000000
+95 51 19.849433 19.849433 19.849433
+95 52 28.071338 28.071338 28.071338
+95 53 36.715120 36.715120 36.715120
+95 54 37.054015 37.054015 37.054015
+95 55 12.165525 12.165525 12.165525
+95 56 29.546573 29.546573 29.546573
+95 57 14.764823 14.764823 14.764823
+95 58 35.468296 35.468296 35.468296
+95 59 56.639209 56.639209 56.639209
+95 60 54.708317 54.708317 54.708317
+95 61 43.680659 43.680659 43.680659
+95 62 20.808652 20.808652 20.808652
+95 63 15.264338 15.264338 15.264338
+95 64 29.120440 29.120440 29.120440
+95 65 21.633308 21.633308 21.633308
+95 66 23.409400 23.409400 23.409400
+95 67 19.416488 19.416488 19.416488
+95 68 9.219544 9.219544 9.219544
+95 69 20.808652 20.808652 20.808652
+95 70 26.305893 26.305893 26.305893
+95 71 30.413813 30.413813 30.413813
+95 72 10.630146 10.630146 10.630146
+95 73 18.027756 18.027756 18.027756
+95 74 56.293872 56.293872 56.293872
+95 75 46.400431 46.400431 46.400431
+95 76 67.475922 67.475922 67.475922
+95 77 36.124784 36.124784 36.124784
+95 78 56.400355 56.400355 56.400355
+95 79 49.648766 49.648766 49.648766
+95 80 54.781384 54.781384 54.781384
+95 81 10.049876 10.049876 10.049876
+95 82 12.806248 12.806248 12.806248
+95 83 30.413813 30.413813 30.413813
+95 84 26.248809 26.248809 26.248809
+95 85 19.000000 19.000000 19.000000
+95 86 25.709920 25.709920 25.709920
+95 87 43.266615 43.266615 43.266615
+95 88 51.000000 51.000000 51.000000
+95 89 34.481879 34.481879 34.481879
+95 90 44.147480 44.147480 44.147480
+95 91 20.024984 20.024984 20.024984
+95 92 10.000000 10.000000 10.000000
+95 93 6.403124 6.403124 6.403124
+95 94 5.656854 5.656854 5.656854
+95 96 11.045361 11.045361 11.045361
+95 97 6.324555 6.324555 6.324555
+95 98 60.901560 60.901560 60.901560
+95 99 31.256999 31.256999 31.256999
+95 100 33.615473 33.615473 33.615473
+95 101 32.202484 32.202484 32.202484
+96 1 20.615528 20.615528 20.615528
+96 2 57.140179 57.140179 57.140179
+96 3 50.990195 50.990195 50.990195
+96 4 58.821765 58.821765 58.821765
+96 5 56.080300 56.080300 56.080300
+96 6 60.000000 60.000000 60.000000
+96 7 53.740115 53.740115 53.740115
+96 8 55.901699 55.901699 55.901699
+96 9 59.413803 59.413803 59.413803
+96 10 46.043458 46.043458 46.043458
+96 11 46.097722 46.097722 46.097722
+96 12 48.093659 48.093659 48.093659
+96 13 48.662100 48.662100 48.662100
+96 14 51.039201 51.039201 51.039201
+96 15 51.623638 51.623638 51.623638
+96 16 54.083269 54.083269 54.083269
+96 17 56.080300 56.080300 56.080300
+96 18 56.568542 56.568542 56.568542
+96 19 34.176015 34.176015 34.176015
+96 20 30.413813 30.413813 30.413813
+96 21 26.076810 26.076810 26.076810
+96 22 35.777088 35.777088 35.777088
+96 23 27.202941 27.202941 27.202941
+96 24 36.715120 36.715120 36.715120
+96 25 28.425341 28.425341 28.425341
+96 26 38.275318 38.275318 38.275318
+96 27 39.623226 39.623226 39.623226
+96 28 39.051248 39.051248 39.051248
+96 29 36.674242 36.674242 36.674242
+96 30 34.058773 34.058773 34.058773
+96 31 32.756679 32.756679 32.756679
+96 32 32.062439 32.062439 32.062439
+96 33 31.780497 31.780497 31.780497
+96 34 31.384710 31.384710 31.384710
+96 35 29.068884 29.068884 29.068884
+96 36 49.244289 49.244289 49.244289
+96 37 48.836462 48.836462 48.836462
+96 38 45.891176 45.891176 45.891176
+96 39 43.416587 43.416587 43.416587
+96 40 43.185646 43.185646 43.185646
+96 41 48.166378 48.166378 48.166378
+96 42 38.052595 38.052595 38.052595
+96 43 43.011626 43.011626 43.011626
+96 44 48.010416 48.010416 48.010416
+96 45 45.011110 45.011110 45.011110
+96 46 57.628118 57.628118 57.628118
+96 47 57.384667 57.384667 57.384667
+96 48 54.589376 54.589376 54.589376
+96 49 34.928498 34.928498 34.928498
+96 50 28.653098 28.653098 28.653098
+96 51 16.124515 16.124515 16.124515
+96 52 17.029386 17.029386 17.029386
+96 53 31.780497 31.780497 31.780497
+96 54 38.275318 38.275318 38.275318
+96 55 23.021729 23.021729 23.021729
+96 56 34.713110 34.713110 34.713110
+96 57 6.324555 6.324555 6.324555
+96 58 28.635642 28.635642 28.635642
+96 59 49.091751 49.091751 49.091751
+96 60 49.040799 49.040799 49.040799
+96 61 47.010637 47.010637 47.010637
+96 62 30.083218 30.083218 30.083218
+96 63 9.219544 9.219544 9.219544
+96 64 19.235384 19.235384 19.235384
+96 65 13.038405 13.038405 13.038405
+96 66 21.213203 21.213203 21.213203
+96 67 15.000000 15.000000 15.000000
+96 68 9.433981 9.433981 9.433981
+96 69 28.017851 28.017851 28.017851
+96 70 29.154759 29.154759 29.154759
+96 71 38.275318 38.275318 38.275318
+96 72 20.124612 20.124612 20.124612
+96 73 28.861739 28.861739 28.861739
+96 74 58.694122 58.694122 58.694122
+96 75 39.812058 39.812058 39.812058
+96 76 60.207973 60.207973 60.207973
+96 77 25.317978 25.317978 25.317978
+96 78 47.381431 47.381431 47.381431
+96 79 51.623638 51.623638 51.623638
+96 80 58.830264 58.830264 58.830264
+96 81 13.453624 13.453624 13.453624
+96 82 22.135944 22.135944 22.135944
+96 83 29.614186 29.614186 29.614186
+96 84 19.924859 19.924859 19.924859
+96 85 8.062258 8.062258 8.062258
+96 86 15.652476 15.652476 15.652476
+96 87 37.336309 37.336309 37.336309
+96 88 45.880279 45.880279 45.880279
+96 89 38.275318 38.275318 38.275318
+96 90 33.837849 33.837849 33.837849
+96 91 21.470911 21.470911 21.470911
+96 92 8.602325 8.602325 8.602325
+96 93 6.708204 6.708204 6.708204
+96 94 15.811388 15.811388 15.811388
+96 95 11.045361 11.045361 11.045361
+96 97 17.029386 17.029386 17.029386
+96 98 55.362442 55.362442 55.362442
+96 99 33.541020 33.541020 33.541020
+96 100 30.066593 30.066593 30.066593
+96 101 39.051248 39.051248 39.051248
+97 1 15.524175 15.524175 15.524175
+97 2 43.139309 43.139309 43.139309
+97 3 39.115214 39.115214 39.115214
+97 4 45.276926 45.276926 45.276926
+97 5 43.600459 43.600459 43.600459
+97 6 46.754679 46.754679 46.754679
+97 7 42.544095 42.544095 42.544095
+97 8 45.177428 45.177428 45.177428
+97 9 47.707442 47.707442 47.707442
+97 10 48.846699 48.846699 48.846699
+97 11 47.127487 47.127487 47.127487
+97 12 49.040799 49.040799 49.040799
+97 13 47.853944 47.853944 47.853944
+97 14 53.488316 53.488316 53.488316
+97 15 50.803543 50.803543 50.803543
+97 16 54.817880 54.817880 54.817880
+97 17 56.753854 56.753854 56.753854
+97 18 55.731499 55.731499 55.731499
+97 19 50.219518 50.219518 50.219518
+97 20 45.880279 45.880279 45.880279
+97 21 41.109610 41.109610 41.109610
+97 22 51.244512 51.244512 51.244512
+97 23 41.785165 41.785165 41.785165
+97 24 51.865210 51.865210 51.865210
+97 25 42.544095 42.544095 42.544095
+97 26 52.924474 52.924474 52.924474
+97 27 46.647615 46.647615 46.647615
+97 28 44.283180 44.283180 44.283180
+97 29 44.102154 44.102154 44.102154
+97 30 39.824616 39.824616 39.824616
+97 31 40.804412 40.804412 40.804412
+97 32 38.078866 38.078866 38.078866
+97 33 40.000000 40.000000 40.000000
+97 34 41.725292 41.725292 41.725292
+97 35 35.510562 35.510562 35.510562
+97 36 33.241540 33.241540 33.241540
+97 37 32.572995 32.572995 32.572995
+97 38 29.732137 29.732137 29.732137
+97 39 26.925824 26.925824 26.925824
+97 40 26.476405 26.476405 26.476405
+97 41 31.400637 31.400637 31.400637
+97 42 21.213203 21.213203 21.213203
+97 43 26.000000 26.000000 26.000000
+97 44 31.000000 31.000000 31.000000
+97 45 28.000000 28.000000 28.000000
+97 46 44.821870 44.821870 44.821870
+97 47 45.221676 45.221676 45.221676
+97 48 53.758720 53.758720 53.758720
+97 49 50.695167 50.695167 50.695167
+97 50 43.965896 43.965896 43.965896
+97 51 25.495098 25.495098 25.495098
+97 52 34.000000 34.000000 34.000000
+97 53 38.418745 38.418745 38.418745
+97 54 35.227830 35.227830 35.227830
+97 55 6.000000 6.000000 6.000000
+97 56 25.709920 25.709920 25.709920
+97 57 19.646883 19.646883 19.646883
+97 58 38.288379 38.288379 38.288379
+97 59 59.464275 59.464275 59.464275
+97 60 56.400355 56.400355 56.400355
+97 61 40.447497 40.447497 40.447497
+97 62 14.866069 14.866069 14.866069
+97 63 21.470911 21.470911 21.470911
+97 64 35.440090 35.440090 35.440090
+97 65 26.000000 26.000000 26.000000
+97 66 24.413111 24.413111 24.413111
+97 67 22.022716 22.022716 22.022716
+97 68 15.000000 15.000000 15.000000
+97 69 16.155494 16.155494 16.155494
+97 70 24.083189 24.083189 24.083189
+97 71 25.000000 25.000000 25.000000
+97 72 10.049876 10.049876 10.049876
+97 73 13.601471 13.601471 13.601471
+97 74 53.338541 53.338541 53.338541
+97 75 48.795492 48.795492 48.795492
+97 76 70.007142 70.007142 70.007142
+97 77 42.296572 42.296572 42.296572
+97 78 60.207973 60.207973 60.207973
+97 79 47.042534 47.042534 47.042534
+97 80 50.960769 50.960769 50.960769
+97 81 10.630146 10.630146 10.630146
+97 82 7.211103 7.211103 7.211103
+97 83 30.083218 30.083218 30.083218
+97 84 29.206164 29.206164 29.206164
+97 85 25.079872 25.079872 25.079872
+97 86 32.015621 32.015621 32.015621
+97 87 45.343136 45.343136 45.343136
+97 88 52.430907 52.430907 52.430907
+97 89 31.256999 31.256999 31.256999
+97 90 50.447993 50.447993 50.447993
+97 91 19.313208 19.313208 19.313208
+97 92 13.416408 13.416408 13.416408
+97 93 11.180340 11.180340 11.180340
+97 94 6.324555 6.324555 6.324555
+97 95 6.324555 6.324555 6.324555
+97 96 17.029386 17.029386 17.029386
+97 98 62.425956 62.425956 62.425956
+97 99 29.068884 29.068884 29.068884
+97 100 34.669872 34.669872 34.669872
+97 101 27.294688 27.294688 27.294688
+98 1 48.166378 48.166378 48.166378
+98 2 70.213959 70.213959 70.213959
+98 3 59.774577 59.774577 59.774577
+98 4 69.375788 69.375788 69.375788
+98 5 64.031242 64.031242 64.031242
+98 6 68.883960 68.883960 68.883960
+98 7 58.694122 58.694122 58.694122
+98 8 58.051701 58.051701 58.051701
+98 9 62.968246 62.968246 62.968246
+98 10 18.027756 18.027756 18.027756
+98 11 22.803509 22.803509 22.803509
+98 12 22.360680 22.360680 22.360680
+98 13 27.294688 27.294688 27.294688
+98 14 17.029386 17.029386 17.029386
+98 15 27.018512 27.018512 27.018512
+98 16 22.090722 22.090722 22.090722
+98 17 22.360680 22.360680 22.360680
+98 18 27.294688 27.294688 27.294688
+98 19 42.059482 42.059482 42.059482
+98 20 38.832976 38.832976 38.832976
+98 21 38.118237 38.118237 38.118237
+98 22 38.275318 38.275318 38.275318
+98 23 36.124784 36.124784 36.124784
+98 24 36.400549 36.400549 36.400549
+98 25 34.132096 34.132096 34.132096
+98 26 33.615473 33.615473 33.615473
+98 27 91.787799 91.787799 91.787799
+98 28 92.574294 92.574294 92.574294
+98 29 88.814413 88.814413 88.814413
+98 30 87.664132 87.664132 87.664132
+98 31 84.852814 84.852814 84.852814
+98 32 85.702975 85.702975 85.702975
+98 33 83.862983 83.862983 83.862983
+98 34 81.301906 81.301906 81.301906
+98 35 82.764727 82.764727 82.764727
+98 36 91.967386 91.967386 91.967386
+98 37 90.609050 90.609050 90.609050
+98 38 88.413800 88.413800 88.413800
+98 39 84.899941 84.899941 84.899941
+98 40 83.546394 83.546394 83.546394
+98 41 87.321246 87.321246 87.321246
+98 42 78.517514 78.517514 78.517514
+98 43 80.280757 80.280757 80.280757
+98 44 84.202138 84.202138 84.202138
+98 45 81.835200 81.835200 81.835200
+98 46 65.969690 65.969690 65.969690
+98 47 63.560994 63.560994 63.560994
+98 48 27.073973 27.073973 27.073973
+98 49 40.162171 40.162171 40.162171
+98 50 38.470768 38.470768 38.470768
+98 51 70.092796 70.092796 70.092796
+98 52 51.039201 51.039201 51.039201
+98 53 24.186773 24.186773 24.186773
+98 54 35.777088 35.777088 35.777088
+98 55 66.068147 66.068147 66.068147
+98 56 49.396356 49.396356 49.396356
+98 57 49.040799 49.040799 49.040799
+98 58 26.925824 26.925824 26.925824
+98 59 13.601471 13.601471 13.601471
+98 60 6.324555 6.324555 6.324555
+98 61 43.416587 43.416587 43.416587
+98 62 62.369865 62.369865 62.369865
+98 63 63.324561 63.324561 63.324561
+98 64 61.032778 61.032778 61.032778
+98 65 42.720019 42.720019 42.720019
+98 66 38.013156 38.013156 38.013156
+98 67 41.593269 41.593269 41.593269
+98 68 64.621978 64.621978 64.621978
+98 69 55.317267 55.317267 55.317267
+98 70 43.416587 43.416587 43.416587
+98 71 59.682493 59.682493 59.682493
+98 72 71.344236 71.344236 71.344236
+98 73 75.432089 75.432089 75.432089
+98 74 42.047592 42.047592 42.047592
+98 75 16.124515 16.124515 16.124515
+98 76 13.038405 13.038405 13.038405
+98 77 56.320511 56.320511 56.320511
+98 78 24.207437 24.207437 24.207437
+98 79 38.209946 38.209946 38.209946
+98 80 50.039984 50.039984 50.039984
+98 81 51.865210 51.865210 51.865210
+98 82 60.207973 60.207973 60.207973
+98 83 33.970576 33.970576 33.970576
+98 84 35.468296 35.468296 35.468296
+98 85 54.129474 54.129474 54.129474
+98 86 59.211485 59.211485 59.211485
+98 87 18.027756 18.027756 18.027756
+98 88 10.000000 10.000000 10.000000
+98 89 44.721360 44.721360 44.721360
+98 90 64.327288 64.327288 64.327288
+98 91 43.931765 43.931765 43.931765
+98 92 51.000000 51.000000 51.000000
+98 93 55.009090 55.009090 55.009090
+98 94 66.370174 66.370174 66.370174
+98 95 60.901560 60.901560 60.901560
+98 96 55.362442 55.362442 55.362442
+98 97 62.425956 62.425956 62.425956
+98 99 40.496913 40.496913 40.496913
+98 100 27.802878 27.802878 27.802878
+98 101 55.946403 55.946403 55.946403
+99 1 14.142136 14.142136 14.142136
+99 2 33.015148 33.015148 33.015148
+99 3 23.345235 23.345235 23.345235
+99 4 33.241540 33.241540 33.241540
+99 5 28.635642 28.635642 28.635642
+99 6 33.541020 33.541020 33.541020
+99 7 24.351591 24.351591 24.351591
+99 8 25.495098 25.495098 25.495098
+99 9 30.083218 30.083218 30.083218
+99 10 23.345235 23.345235 23.345235
+99 11 20.000000 20.000000 20.000000
+99 12 21.633308 21.633308 21.633308
+99 13 19.313208 19.313208 19.313208
+99 14 27.018512 27.018512 27.018512
+99 15 22.135944 22.135944 22.135944
+99 16 26.832816 26.832816 26.832816
+99 17 28.635642 28.635642 28.635642
+99 18 26.925824 26.925824 26.925824
+99 19 50.328918 50.328918 50.328918
+99 20 44.944410 44.944410 44.944410
+99 21 40.311289 40.311289 40.311289
+99 22 49.040799 49.040799 49.040799
+99 23 39.560081 39.560081 39.560081
+99 24 48.507731 48.507731 48.507731
+99 25 38.897301 38.897301 38.897301
+99 26 47.853944 47.853944 47.853944
+99 27 72.422372 72.422372 72.422372
+99 28 71.063352 71.063352 71.063352
+99 29 69.570109 69.570109 69.570109
+99 30 66.219333 66.219333 66.219333
+99 31 65.787537 65.787537 65.787537
+99 32 64.288413 64.288413 64.288413
+99 33 64.845971 64.845971 64.845971
+99 34 64.884513 64.884513 64.884513
+99 35 61.400326 61.400326 61.400326
+99 36 52.630789 52.630789 52.630789
+99 37 51.088159 51.088159 51.088159
+99 38 49.203658 49.203658 49.203658
+99 39 45.607017 45.607017 45.607017
+99 40 44.045431 44.045431 44.045431
+99 41 47.381431 47.381431 47.381431
+99 42 39.408121 39.408121 39.408121
+99 43 40.311289 40.311289 40.311289
+99 44 43.931765 43.931765 43.931765
+99 45 41.725292 41.725292 41.725292
+99 46 30.594117 30.594117 30.594117
+99 47 29.120440 29.120440 29.120440
+99 48 25.000000 25.000000 25.000000
+99 49 49.648766 49.648766 49.648766
+99 50 43.081318 43.081318 43.081318
+99 51 49.040799 49.040799 49.040799
+99 52 43.185646 43.185646 43.185646
+99 53 22.022716 22.022716 22.022716
+99 54 6.324555 6.324555 6.324555
+99 55 30.083218 30.083218 30.083218
+99 56 8.944272 8.944272 8.944272
+99 57 29.410882 29.410882 29.410882
+99 58 27.294688 27.294688 27.294688
+99 59 43.416587 43.416587 43.416587
+99 60 35.777088 35.777088 35.777088
+99 61 13.601471 13.601471 13.601471
+99 62 23.021729 23.021729 23.021729
+99 63 42.544095 42.544095 42.544095
+99 64 50.447993 50.447993 50.447993
+99 65 29.068884 29.068884 29.068884
+99 66 15.000000 15.000000 15.000000
+99 67 21.213203 21.213203 21.213203
+99 68 39.293765 39.293765 39.293765
+99 69 16.124515 16.124515 16.124515
+99 70 5.000000 5.000000 5.000000
+99 71 19.235384 19.235384 19.235384
+99 72 39.115214 39.115214 39.115214
+99 73 39.217343 39.217343 39.217343
+99 74 25.298221 25.298221 25.298221
+99 75 32.557641 32.557641 32.557641
+99 76 51.478151 51.478151 51.478151
+99 77 52.497619 52.497619 52.497619
+99 78 49.091751 49.091751 49.091751
+99 79 18.439089 18.439089 18.439089
+99 80 25.612497 25.612497 25.612497
+99 81 21.587033 21.587033 21.587033
+99 82 23.769729 23.769729 23.769729
+99 83 9.055385 9.055385 9.055385
+99 84 23.706539 23.706539 23.706539
+99 85 38.600518 38.600518 38.600518
+99 86 47.010637 47.010637 47.010637
+99 87 28.442925 28.442925 28.442925
+99 88 31.304952 31.304952 31.304952
+99 89 6.324555 6.324555 6.324555
+99 90 62.369865 62.369865 62.369865
+99 91 12.083046 12.083046 12.083046
+99 92 25.079872 25.079872 25.079872
+99 93 28.460499 28.460499 28.460499
+99 94 35.000000 35.000000 35.000000
+99 95 31.256999 31.256999 31.256999
+99 96 33.541020 33.541020 33.541020
+99 97 29.068884 29.068884 29.068884
+99 98 40.496913 40.496913 40.496913
+99 100 17.000000 17.000000 17.000000
+99 101 15.811388 15.811388 15.811388
+100 1 20.518285 20.518285 20.518285
+100 2 50.009999 50.009999 50.009999
+100 3 40.199502 40.199502 40.199502
+100 4 50.159745 50.159745 50.159745
+100 5 45.398238 45.398238 45.398238
+100 6 50.358713 50.358713 50.358713
+100 7 40.792156 40.792156 40.792156
+100 8 41.484937 41.484937 41.484937
+100 9 46.324939 46.324939 46.324939
+100 10 16.000000 16.000000 16.000000
+100 11 16.763055 16.763055 16.763055
+100 12 18.681542 18.681542 18.681542
+100 13 20.591260 20.591260 20.591260
+100 14 21.000000 21.000000 21.000000
+100 15 23.259407 23.259407 23.259407
+100 16 24.515301 24.515301 24.515301
+100 17 26.476405 26.476405 26.476405
+100 18 27.856777 27.856777 27.856777
+100 19 34.985711 34.985711 34.985711
+100 20 29.681644 29.681644 29.681644
+100 21 25.612497 25.612497 25.612497
+100 22 33.105891 33.105891 33.105891
+100 23 24.413111 24.413111 24.413111
+100 24 32.310989 32.310989 32.310989
+100 25 23.323808 23.323808 23.323808
+100 26 31.320920 31.320920 31.320920
+100 27 69.180922 69.180922 69.180922
+100 28 69.000000 69.000000 69.000000
+100 29 66.189123 66.189123 66.189123
+100 30 64.000000 64.000000 64.000000
+100 31 62.201286 62.201286 62.201286
+100 32 62.000000 62.000000 62.000000
+100 33 61.204575 61.204575 61.204575
+100 34 59.841457 59.841457 59.841457
+100 35 59.000000 59.000000 59.000000
+100 36 64.660653 64.660653 64.660653
+100 37 63.411355 63.411355 63.411355
+100 38 61.073726 61.073726 61.073726
+100 39 57.628118 57.628118 57.628118
+100 40 56.400355 56.400355 56.400355
+100 41 60.464866 60.464866 60.464866
+100 42 51.224994 51.224994 51.224994
+100 43 53.535035 53.535035 53.535035
+100 44 57.801384 57.801384 57.801384
+100 45 55.226805 55.226805 55.226805
+100 46 47.381431 47.381431 47.381431
+100 47 45.705580 45.705580 45.705580
+100 48 26.000000 26.000000 26.000000
+100 49 34.000000 34.000000 34.000000
+100 50 28.017851 28.017851 28.017851
+100 51 46.000000 46.000000 46.000000
+100 52 32.649655 32.649655 32.649655
+100 53 5.099020 5.099020 5.099020
+100 54 16.155494 16.155494 16.155494
+100 55 38.288379 38.288379 38.288379
+100 56 25.317978 25.317978 25.317978
+100 57 24.000000 24.000000 24.000000
+100 58 10.770330 10.770330 10.770330
+100 59 27.313001 27.313001 27.313001
+100 60 21.931712 21.931712 21.931712
+100 61 27.313001 27.313001 27.313001
+100 62 35.510562 35.510562 35.510562
+100 63 39.000000 39.000000 39.000000
+100 64 41.785165 41.785165 41.785165
+100 65 19.646883 19.646883 19.646883
+100 66 10.295630 10.295630 10.295630
+100 67 15.132746 15.132746 15.132746
+100 68 38.639358 38.639358 38.639358
+100 69 28.653098 28.653098 28.653098
+100 70 17.720045 17.720045 17.720045
+100 71 35.171011 35.171011 35.171011
+100 72 43.829214 43.829214 43.829214
+100 73 47.634021 47.634021 47.634021
+100 74 34.655447 34.655447 34.655447
+100 75 16.155494 16.155494 16.155494
+100 76 36.619667 36.619667 36.619667
+100 77 41.048752 41.048752 41.048752
+100 78 32.140317 32.140317 32.140317
+100 79 27.658633 27.658633 27.658633
+100 80 38.587563 38.587563 38.587563
+100 81 24.186773 24.186773 24.186773
+100 82 32.526912 32.526912 32.526912
+100 83 8.062258 8.062258 8.062258
+100 84 11.704700 11.704700 11.704700
+100 85 31.575307 31.575307 31.575307
+100 86 38.897301 38.897301 38.897301
+100 87 12.083046 12.083046 12.083046
+100 88 17.804494 17.804494 17.804494
+100 89 23.086793 23.086793 23.086793
+100 90 50.803543 50.803543 50.803543
+100 91 16.278821 16.278821 16.278821
+100 92 24.041631 24.041631 24.041631
+100 93 28.160256 28.160256 28.160256
+100 94 38.910153 38.910153 38.910153
+100 95 33.615473 33.615473 33.615473
+100 96 30.066593 30.066593 30.066593
+100 97 34.669872 34.669872 34.669872
+100 98 27.802878 27.802878 27.802878
+100 99 17.000000 17.000000 17.000000
+100 101 32.388269 32.388269 32.388269
+101 1 19.235384 19.235384 19.235384
+101 2 18.973666 18.973666 18.973666
+101 3 12.041595 12.041595 12.041595
+101 4 20.124612 20.124612 20.124612
+101 5 17.029386 17.029386 17.029386
+101 6 21.095023 21.095023 21.095023
+101 7 15.264338 15.264338 15.264338
+101 8 17.888544 17.888544 17.888544
+101 9 20.615528 20.615528 20.615528
+101 10 38.275318 38.275318 38.275318
+101 11 34.205263 34.205263 34.205263
+101 12 35.468296 35.468296 35.468296
+101 13 31.827661 31.827661 31.827661
+101 14 41.231056 41.231056 41.231056
+101 15 34.058773 34.058773 34.058773
+101 16 39.623226 39.623226 39.623226
+101 17 41.109610 41.109610 41.109610
+101 18 38.013156 38.013156 38.013156
+101 19 63.348244 63.348244 63.348244
+101 20 58.051701 58.051701 58.051701
+101 21 53.150729 53.150729 53.150729
+101 22 62.649820 62.649820 62.649820
+101 23 52.773099 52.773099 52.773099
+101 24 62.393910 62.393910 62.393910
+101 25 52.469038 52.469038 52.469038
+101 26 62.128898 62.128898 62.128898
+101 27 73.925638 73.925638 73.925638
+101 28 71.554175 71.554175 71.554175
+101 29 71.344236 71.344236 71.344236
+101 30 67.119297 67.119297 67.119297
+101 31 67.955868 67.955868 67.955868
+101 32 65.368188 65.368188 65.368188
+101 33 67.119297 67.119297 67.119297
+101 34 68.410526 68.410526 68.410526
+101 35 62.769419 62.769419 62.769419
+101 36 40.249224 40.249224 40.249224
+101 37 38.470768 38.470768 38.470768
+101 38 37.161808 37.161808 37.161808
+101 39 33.615473 33.615473 33.615473
+101 40 31.780497 31.780497 31.780497
+101 41 34.132096 34.132096 34.132096
+101 42 28.160256 28.160256 28.160256
+101 43 27.294688 27.294688 27.294688
+101 44 30.000000 30.000000 30.000000
+101 45 28.301943 28.301943 28.301943
+101 46 18.601075 18.601075 18.601075
+101 47 18.384776 18.384776 18.384776
+101 48 36.400549 36.400549 36.400549
+101 49 62.968246 62.968246 62.968246
+101 50 56.089215 56.089215 56.089215
+101 51 52.009614 52.009614 52.009614
+101 52 52.773099 52.773099 52.773099
+101 53 37.483330 37.483330 37.483330
+101 54 20.248457 20.248457 20.248457
+101 55 25.000000 25.000000 25.000000
+101 56 7.071068 7.071068 7.071068
+101 57 37.215588 37.215588 37.215588
+101 58 42.011903 42.011903 42.011903
+101 59 59.203040 59.203040 59.203040
+101 60 51.478151 51.478151 51.478151
+101 61 17.464249 17.464249 17.464249
+101 62 14.142136 14.142136 14.142136
+101 63 46.690470 46.690470 46.690470
+101 64 58.008620 58.008620 58.008620
+101 65 39.560081 39.560081 39.560081
+101 66 27.294688 27.294688 27.294688
+101 67 31.622777 31.622777 31.622777
+101 68 41.400483 41.400483 41.400483
+101 69 11.401754 11.401754 11.401754
+101 70 15.000000 15.000000 15.000000
+101 71 4.472136 4.472136 4.472136
+101 72 36.055513 36.055513 36.055513
+101 73 32.062439 32.062439 32.062439
+101 74 29.832868 29.832868 29.832868
+101 75 48.270074 48.270074 48.270074
+101 76 67.230945 67.230945 67.230945
+101 77 62.177166 62.177166 62.177166
+101 78 64.498062 64.498062 64.498062
+101 79 25.495098 25.495098 25.495098
+101 80 25.019992 25.019992 25.019992
+101 81 25.612497 25.612497 25.612497
+101 82 20.124612 20.124612 20.124612
+101 83 24.331050 24.331050 24.331050
+101 84 36.496575 36.496575 36.496575
+101 85 46.043458 46.043458 46.043458
+101 86 54.405882 54.405882 54.405882
+101 87 44.147480 44.147480 44.147480
+101 88 47.010637 47.010637 47.010637
+101 89 11.401754 11.401754 11.401754
+101 90 71.693793 71.693793 71.693793
+101 91 20.880613 20.880613 20.880613
+101 92 30.805844 30.805844 30.805844
+101 93 32.557641 32.557641 32.557641
+101 94 33.541020 33.541020 33.541020
+101 95 32.202484 32.202484 32.202484
+101 96 39.051248 39.051248 39.051248
+101 97 27.294688 27.294688 27.294688
+101 98 55.946403 55.946403 55.946403
+101 99 15.811388 15.811388 15.811388
+101 100 32.388269 32.388269 32.388269
+\.
+
diff --git a/src/vrp_basic/test/VRP-any-01.data b/src/vrp_basic/test/VRP-any-01.data
new file mode 100644
index 0000000..f1f265b
--- /dev/null
+++ b/src/vrp_basic/test/VRP-any-01.data
@@ -0,0 +1,114 @@
+drop table if exists vrp100_orders cascade;
+create table vrp100_orders (
+ id integer not null primary key,
+ order_unit integer,
+ open_time integer,
+ close_time integer,
+ service_time integer,
+ x float,
+ y float
+);
+
+copy vrp100_orders (id, x, y, order_unit, open_time, close_time, service_time) from STDIN delimiter ',';
+0,40,50,0,0,1236,0
+1,45,68,10,912,967,90
+2,45,70,30,825,870,90
+3,42,66,10,65,146,90
+4,42,68,10,727,782,90
+5,42,65,10,15,67,90
+6,40,69,20,621,702,90
+7,40,66,20,170,225,90
+8,38,68,20,255,324,90
+9,38,70,10,534,605,90
+10,35,66,10,357,410,90
+11,35,69,10,448,505,90
+12,25,85,20,652,721,90
+13,22,75,30,30,92,90
+14,22,85,10,567,620,90
+15,20,80,40,384,429,90
+16,20,85,40,475,528,90
+17,18,75,20,99,148,90
+18,15,75,20,179,254,90
+19,15,80,10,278,345,90
+20,30,50,10,10,73,90
+21,30,52,20,914,965,90
+22,28,52,20,812,883,90
+23,28,55,10,732,777,90
+24,25,50,10,65,144,90
+25,25,52,40,169,224,90
+26,25,55,10,622,701,90
+27,23,52,10,261,316,90
+28,23,55,20,546,593,90
+29,20,50,10,358,405,90
+30,20,55,10,449,504,90
+31,10,35,20,200,237,90
+32,10,40,30,31,100,90
+33,8,40,40,87,158,90
+34,8,45,20,751,816,90
+35,5,35,10,283,344,90
+36,5,45,10,665,716,90
+37,2,40,20,383,434,90
+38,0,40,30,479,522,90
+39,0,45,20,567,624,90
+40,35,30,10,264,321,90
+41,35,32,10,166,235,90
+42,33,32,20,68,149,90
+43,33,35,10,16,80,90
+44,32,30,10,359,412,90
+45,30,30,10,541,600,90
+46,30,32,30,448,509,90
+47,30,35,10,1054,1127,90
+48,28,30,10,632,693,90
+49,28,35,10,1001,1066,90
+50,26,32,10,815,880,90
+51,25,30,10,725,786,90
+52,25,35,10,912,969,90
+53,44,5,20,286,347,90
+54,42,10,40,186,257,90
+55,42,15,10,95,158,90
+56,40,5,30,385,436,90
+57,40,15,40,35,87,90
+58,38,5,30,471,534,90
+59,38,15,10,651,740,90
+60,35,5,20,562,629,90
+61,50,30,10,531,610,90
+62,50,35,20,262,317,90
+63,50,40,50,171,218,90
+64,48,30,10,632,693,90
+65,48,40,10,76,129,90
+66,47,35,10,826,875,90
+67,47,40,10,12,77,90
+68,45,30,10,734,777,90
+69,45,35,10,916,969,90
+70,95,30,30,387,456,90
+71,95,35,20,293,360,90
+72,53,30,10,450,505,90
+73,92,30,10,478,551,90
+74,53,35,50,353,412,90
+75,45,65,20,997,1068,90
+76,90,35,10,203,260,90
+77,88,30,10,574,643,90
+78,88,35,20,109,170,90
+79,87,30,10,668,731,90
+80,85,25,10,769,820,90
+81,85,35,30,47,124,90
+82,75,55,20,369,420,90
+83,72,55,10,265,338,90
+84,70,58,20,458,523,90
+85,68,60,30,555,612,90
+86,66,55,10,173,238,90
+87,65,55,20,85,144,90
+88,65,60,30,645,708,90
+89,63,58,10,737,802,90
+90,60,55,10,20,84,90
+91,60,60,10,836,889,90
+92,67,85,20,368,441,90
+93,65,85,40,475,518,90
+94,65,82,10,285,336,90
+95,62,80,30,196,239,90
+96,60,80,10,95,156,90
+97,60,85,30,561,622,90
+98,58,75,20,30,84,90
+99,55,80,10,743,820,90
+100,55,85,20,647,726,90
+\.
diff --git a/src/common/src/CMakeLists.txt b/src/vrp_basic/test/VRP-any-01.result
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/vrp_basic/test/VRP-any-01.result
diff --git a/src/vrp_basic/test/VRP-any-01.test.sql b/src/vrp_basic/test/VRP-any-01.test.sql
new file mode 100644
index 0000000..db9d364
--- /dev/null
+++ b/src/vrp_basic/test/VRP-any-01.test.sql
@@ -0,0 +1,5 @@
+select * from pgr_vrpOneDepot(
+ 'select * from vrp_orders order by id'::text,
+ 'select * from vrp_vehicles order by vehicle_id'::text,
+ 'select * from vrp_distance order by src_id, dest_id'::text,
+ 1 ) ORDER BY vid, opos;
diff --git a/src/vrp_basic/test/VRP-any-02.test.sql b/src/vrp_basic/test/VRP-any-02.test.sql
new file mode 100644
index 0000000..c5a977d
--- /dev/null
+++ b/src/vrp_basic/test/VRP-any-02.test.sql
@@ -0,0 +1,4 @@
+select * from pgr_vrpOneDepot(
+ 'select * from vrp100_orders order by id'::text,
+ 'select vehicle_id::integer, 200 as capacity from generate_series(1,50) as vehicle_id',
+ 'select a.id as src_id, b.id as dest_id, sqrt((a.x-b.x)*(a.x-b.x)) as cost, sqrt((a.x-b.x)*(a.x-b.x)) as distance, sqrt((a.x-b.x)*(a.x-b.x)) as traveltime from vrp100_orders a, vrp100_orders b where a.id != b.id order by a.id, b.id', 0) order by vid, opos;
diff --git a/src/vrp_basic/test/Vehicles.txt b/src/vrp_basic/test/Vehicles.txt
new file mode 100644
index 0000000..04aa1c2
--- /dev/null
+++ b/src/vrp_basic/test/Vehicles.txt
@@ -0,0 +1,21 @@
+V_d Capacity
+1 200
+2 200
+3 200
+4 200
+5 200
+6 200
+7 200
+8 200
+9 200
+10 200
+11 200
+12 200
+13 200
+14 200
+15 200
+16 200
+17 200
+18 200
+19 200
+20 200
diff --git a/src/vrp_basic/test/solomon100-optimal.png b/src/vrp_basic/test/solomon100-optimal.png
new file mode 100644
index 0000000..ece0cbb
Binary files /dev/null and b/src/vrp_basic/test/solomon100-optimal.png differ
diff --git a/src/ksp/test/test.conf b/src/vrp_basic/test/test.conf
similarity index 58%
copy from src/ksp/test/test.conf
copy to src/vrp_basic/test/test.conf
index cadeada..fc73366 100644
--- a/src/ksp/test/test.conf
+++ b/src/vrp_basic/test/test.conf
@@ -2,9 +2,10 @@
%main::tests = (
'any' => {
- 'comment' => 'KSP test for any versions.',
- 'data' => ['ksp-any-00.data'],
- 'tests' => [qw(ksp-any-01 ksp-any-02)]
+ 'comment' => 'VRP Single depot test for any versions.',
+ 'data' => ['VRP-any-00.data'],
+ #'tests' => [qw(VRP-any-01)]
+ 'tests' => []
},
# 'vpg-vpgis' => {}, # for version specific tests
# '8-1' => {}, # for pg 8.x and postgis 1.x
diff --git a/src/vrpdptw/test/README.vrpdptw-testdata b/src/vrpdptw/test/README.vrpdptw-testdata
new file mode 100644
index 0000000..caf333a
--- /dev/null
+++ b/src/vrpdptw/test/README.vrpdptw-testdata
@@ -0,0 +1,33 @@
+
+# Li & Lim benchmark
+
+Here you find instance definitions and the best known solutions
+(to our knowledge) for the 100, 200, 400, 600, 800, and 1000 customer
+instances of Li & Lim's PDPTW benchmark problems. The version reported
+here has a hierarchical objective:
+
+ 1. Minimize number of vehicles
+ 2. Minimize total distance.
+
+Distance and time should be calculated with double precision, total
+distance results are rounded to two decimals. Exact methods typically
+use a total distance objective and use integral or low precision distance
+and time calculations. Hence, results are not directly comparable.
+
+This data base was built from data published at
+http://www.sintef.no/Projectweb/TOP/PDPTW/Li--Lim-benchmark/
+
+The data loads into a schema named "testdata" and there are 352 test cases
+with each test cases loaded into a table. there is a summary table called
+"pdp_problems" which lists each data table as "instance" and provides
+additional information about the best know result and the number of
+vehicles and vehicle capacity for each test cases.
+
+You might load these with commands like:
+
+```
+createdb -U postgres -h localhost vrpdptw_tests
+zcat vrpdptw-testdata.sql.gz | psql -U postgres -h localhost vrpdptw_tests
+```
+
+
diff --git a/src/vrpdptw/test/vrpdptw-testdata.sql.gz b/src/vrpdptw/test/vrpdptw-testdata.sql.gz
new file mode 100644
index 0000000..efda4b2
Binary files /dev/null and b/src/vrpdptw/test/vrpdptw-testdata.sql.gz differ
diff --git a/src/driving_distance/CMakeLists.txt b/src/vrppdtw/CMakeLists.txt
similarity index 69%
copy from src/driving_distance/CMakeLists.txt
copy to src/vrppdtw/CMakeLists.txt
index c4a8382..302fdcd 100644
--- a/src/driving_distance/CMakeLists.txt
+++ b/src/vrppdtw/CMakeLists.txt
@@ -1,5 +1,5 @@
SET(PACKAGE_SQL_FILES "")
ADD_SUBDIRECTORY(sql)
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
-#MESSAGE("core/driving_distance: ${PACKAGE_SQL_FILES}")
SUBDIRS(doc src test)
+
diff --git a/src/common/src/CMakeLists.txt b/src/vrppdtw/doc/CMakeLists.txt
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/vrppdtw/doc/CMakeLists.txt
diff --git a/src/vrppdtw/doc/index.rst b/src/vrppdtw/doc/index.rst
new file mode 100755
index 0000000..0ab5cc3
--- /dev/null
+++ b/src/vrppdtw/doc/index.rst
@@ -0,0 +1,85 @@
+..
+ ****************************************************************************
+ pgRouting Manual
+ Copyright(c) pgRouting Contributors
+
+ This documentation is licensed under a Creative Commons Attribution-Share
+ Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/
+ ****************************************************************************
+
+.. _pgr_gsocvrppdtw:
+
+pgr_vrppdtw - Pickup and Delivery problem
+===============================================================================
+
+.. index::
+ single: pgr_gsocvrppdtw(text,integer,integer)
+ module: vrppdtw
+
+Name
+-------------------------------------------------------------------------------
+
+``pgr_gsoc_vrppdtw`` — Returns optimized solution
+
+
+Synopsis
+-------------------------------------------------------------------------------
+
+Vehicle Routing Problem with Pickup and Delivery (VRPPD): A number of goods need to be moved from certain pickup locations to other delivery locations. The goal is to find optimal routes for a fleet of vehicles to visit the pickup and drop-off locations.
+
+.. code-block:: sql
+
+ pgr_gsoc_vrppdtw(text sql, integer , integer;
+
+
+Description
+-------------------------------------------------------------------------------
+
+:sql: a SQL query, which should return a set of rows with the following columns:
+
+ .. code-block:: sql
+
+ select * from pgr_gsoc_vrppdtw(
+ 'select * from customer order by id'::text, 25,200
+ );
+
+
+
+Returns set of :ref:`type_cost_result`:
+
+:seq: row sequence
+:rid: route ID
+:nid: node ID (``-1`` for the last row)
+:cost: cost to traverse to ``seq``
+
+Examples
+-------------------------------------------------------------------------------
+
+
+.. code-block:: sql
+
+
+ SELECT * from pgr_gsoc_vrppdtw(
+ 'select * from customer order by id'::text, 25,200
+ );
+
+
+
+
+ seq | rid | nid | cost
+ -----+------+------+------
+ 0 | 7 | 8 | 1
+ 1 | 8 | 9 | 1
+ 2 | 9 | 15 | 1
+ 3 | 12 | -1 | 0
+ . | . | . | .
+ . | . | . | .
+
+
+
+
+See Also
+-------------------------------------------------------------------------------
+
+* :ref:`type_cost_result`
+* http://en.wikipedia.org/wiki/Vehicle_routing_problem
diff --git a/src/ksp/sql/CMakeLists.txt b/src/vrppdtw/sql/CMakeLists.txt
similarity index 70%
copy from src/ksp/sql/CMakeLists.txt
copy to src/vrppdtw/sql/CMakeLists.txt
index dd5c7d9..0ad253c 100644
--- a/src/ksp/sql/CMakeLists.txt
+++ b/src/vrppdtw/sql/CMakeLists.txt
@@ -1,7 +1,8 @@
# Append in local scope
LIST(APPEND PACKAGE_SQL_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/routing_ksp.sql)
-
+ ${CMAKE_CURRENT_SOURCE_DIR}/routing_vrppdtw.sql
+)
+
# set in parent scope
SET(PACKAGE_SQL_FILES "${PACKAGE_SQL_FILES}" PARENT_SCOPE)
diff --git a/src/vrppdtw/sql/routing_vrppdtw.sql b/src/vrppdtw/sql/routing_vrppdtw.sql
new file mode 100644
index 0000000..e675772
--- /dev/null
+++ b/src/vrppdtw/sql/routing_vrppdtw.sql
@@ -0,0 +1,41 @@
+/*PGR
+
+Copyright (c) 2014 Manikata Kondeti
+mani.iiit123 at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+-----------------------------------------------------------------------
+-- Core function for vrp with sigle depot computation
+-- See README for description
+-----------------------------------------------------------------------
+--
+--
+create or replace function pgr_gsoc_vrppdtw(
+ sql text,
+ vehicle_num integer,
+ capacity integer,
+ OUT seq integer,
+ OUT rid integer,
+ OUT nid integer,
+ OUT cost integer
+ )
+returns setof record as
+'$libdir/librouting-2.1', 'vrppdtw'
+LANGUAGE c VOLATILE STRICT;
+
+
diff --git a/src/vrppdtw/src/CMakeLists.txt b/src/vrppdtw/src/CMakeLists.txt
new file mode 100644
index 0000000..3dd4e76
--- /dev/null
+++ b/src/vrppdtw/src/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_library(vrppdtw OBJECT pdp.h pdp.c Route.h Solution.h pdp_solver.cpp )
+
+
diff --git a/src/vrppdtw/src/Route.h b/src/vrppdtw/src/Route.h
new file mode 100644
index 0000000..89b5e82
--- /dev/null
+++ b/src/vrppdtw/src/Route.h
@@ -0,0 +1,348 @@
+/*PGR
+
+Copyright (c) 2014 Manikata Kondeti
+mani.iiit123 at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+
+#ifndef _ROUTE_H
+#define _ROUTE_H
+
+#include <vector>
+#include <map>
+#include <queue>
+#include <string>
+#include <stdlib.h>
+#include <iostream>
+#include <algorithm>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <set>
+
+class Route
+{
+ public:
+ int twv;
+ int cv;
+ int dis;
+ int path[1200];
+ int order[1200];
+ int path_length;
+ Route()
+ {
+ twv=0;
+ cv=0;
+ dis=0;
+ path_length=0;
+ for(int i=0;i<1000;i++)
+ {
+ path[i]=0;
+ order[i]=0;
+ }
+ }
+ State append(customer *c, Pickup p, depot d,int CustomerLength, int PickupLength, State S);
+ void update(customer *c,depot d);
+ double cost();
+ int HillClimbing(customer *c,depot d,Pickup p);
+ int insertOrder(customer *c,depot d,Pickup p);
+ void remove(State S);
+ // void print();
+ int RemoveOrder(Pickup p);
+};
+
+
+
+int Route::RemoveOrder(Pickup p){
+ int flag=0;
+ // printf("Remove Order with Pid=%d Did=%d\n",p.Pid,p.Did);
+ for(int i=0;i<path_length;i++)
+ {
+ if(path[i]==p.Pid || path[i]==p.Did)
+ {
+ flag=1;
+ path[i]=0;
+ order[i]=0;
+ }
+ }
+ int new_path[path_length+1],new_length=0,new_order[path_length+1];
+ if(flag==1)
+ {
+ //copy
+ for(int i=0;i<path_length;i++)
+ {
+ if(path[i]!=0)
+ {
+ // printf("path[%d]=%d \n",new_length,path[i]);
+ new_path[new_length]=path[i];
+ new_order[new_length]=order[i];
+ new_length++;
+ }
+ }
+ //Reverse Copy
+ for(int i=0;i<new_length;i++)
+ {
+ path[i]=new_path[i];
+ order[i]=new_order[i];
+ }
+ path_length=new_length;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+State Route::append(customer *c, Pickup p, depot d, int CustomerLength, int PickupLength, State S){
+
+ //Save State;
+ S.twv=twv;
+ S.cv=cv;
+ S.dis=dis;
+ S.path_length=path_length;
+ for(int i=0;i<path_length;i++)
+ {
+ S.path[i]=path[i];
+ S.order[i]=order[i];
+ }
+
+ // Insert Order
+ path[path_length]=p.Pid;
+ order[path_length]=p.id;
+ path[path_length+1]=p.Did;
+ order[path_length+1]=p.id;
+ path_length+=2;
+
+ return S;
+}
+void Route::update(customer *c, depot d)
+{
+ dis=0,twv=0,cv=0;
+ int load=0;
+ for(int i=-1;i<path_length;i++)
+ {
+ //depot to first customer
+ if(i==-1)
+ {
+ dis+=sqrt(((d.x-c[path[i+1]].x)*(d.x-c[path[i+1]].x))+((d.y-c[path[i+1]].y)*(d.y-c[path[i+1]].y)));
+ if(dis<c[path[i+1]].Etime)
+ {
+ dis=c[path[i+1]].Etime;
+ }
+ else if(dis>c[path[i+1]].Ltime)
+ {
+ twv+=1;
+ }
+ dis+=c[path[i+1]].Stime;
+ load+=c[path[i+1]].demand;
+ }
+ //Last cusotmer to depot
+ if(i==path_length-1)
+ {
+ dis+=sqrt(((d.x-c[path[i]].x)*(d.x-c[path[i]].x))+((d.y-c[path[i]].y)*(d.y-c[path[i]].y)));
+ if(dis>d.Ltime)
+ {
+ twv+=1;
+ }
+ }
+ //Middle customers
+ if(i>=0 && i< path_length-1)
+ {
+ dis+=sqrt(((c[path[i]].x-c[path[i+1]].x)*(c[path[i]].x-c[path[i+1]].x))+((c[path[i]].y-c[path[i+1]].y)*(c[path[i]].y-c[path[i+1]].y)));
+ if(dis<c[path[i+1]].Etime)
+ {
+ dis=c[path[i+1]].Etime;
+ }
+ else if(dis>c[path[i+1]].Ltime)
+ {
+ twv+=1;
+ }
+ dis+=c[path[i+1]].Stime;
+ load+=c[path[i+1]].demand;
+ }
+
+ if(load>200 || load<0)
+ {
+ cv+=1;
+ }
+ }
+ return;
+}
+double Route::cost()
+{
+ return (0.3*dis)+(0.5*twv)+(0.2*cv);
+}
+int Route::insertOrder(customer *c, depot d, Pickup p)
+{
+ // double cost1=0,cost2=0;
+ twv=0,cv=0,dis=0;
+ int swap=0;
+ update(c,d);
+ if(twv==0 && cv==0 && dis<d.Ltime)
+ return 0;
+
+ for(int i=0;i<path_length;i++)
+ {
+ for(int j=0;j<path_length;j++)
+ {
+ if((c[path[i]].Ltime > c[path[j]].Ltime) ){
+ //Swap Path
+ swap=path[i];
+ path[i]=path[j];
+ path[j]=swap;
+ //Swap order
+ swap=order[i];
+ order[i]=order[j];
+ order[j]=swap;
+
+ }
+ }
+ }
+ //After complete sort
+ int *temp=NULL;
+ int *tempo=NULL;
+ temp= (int *)malloc(1000*sizeof(int));
+ tempo= (int *)malloc(1000*sizeof(int));
+ for(int i=0;i<path_length;i++)
+ {
+ temp[i]=path[path_length-i-1];
+ tempo[i]=order[path_length-i-1];
+ }
+ for(int i=0;i<path_length;i++)
+ {
+ path[i]=temp[i];
+ order[i]=tempo[i];
+ }
+
+ twv=0,cv=0,dis=0;
+ update(c,d);
+ // print();
+ if(twv>0 || cv>0 || dis> d.Ltime)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+int Route::HillClimbing(customer *c, depot d, Pickup p)
+{
+ double cost1=0,cost2=0;
+ twv=0,cv=0,dis=0;
+ int swap=0;
+ update(c,d);
+ cost1=cost();
+ if(twv==0 && cv==0 && dis<d.Ltime)
+ return 0;
+
+ for(int i=0;i<path_length;i++){
+ for(int j=0;j<path_length;j++){
+ int swap_flag=0,count_flag=0;
+ if((c[path[i]].Ltime > c[path[j]].Ltime) && (count_flag==0) ){
+ swap_flag=1;
+ count_flag=1;
+ //Swap Path
+ swap=path[i];
+ path[i]=path[j];
+ path[j]=swap;
+ //Swap order
+ swap=order[i];
+ order[i]=order[j];
+ order[j]=swap;
+
+ }
+ update(c,d);
+ cost2=cost();
+ if(cost2>cost1){
+ if(swap_flag==1){
+ //Swap Path
+ swap=path[i];
+ path[i]=path[j];
+ path[j]=swap;
+ //Swap order
+ swap=order[i];
+ order[i]=order[j];
+ order[j]=swap;
+ // update(c,d);
+ }
+ }
+ }
+ }
+ //After complete sort
+ int *temp=NULL;
+ int *tempo=NULL;
+ temp= (int *)malloc(1000*sizeof(int));
+ tempo= (int *)malloc(1000*sizeof(int));
+ for(int i=0;i<path_length;i++)
+ {
+ temp[i]=path[path_length-i-1];
+ tempo[i]=order[path_length-i-1];
+ }
+ for(int i=0;i<path_length;i++)
+ {
+ path[i]=temp[i];
+ order[i]=tempo[i];
+ }
+
+
+ update(c,d);
+ if(twv>0 || cv>0 || dis> d.Ltime)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+
+#if 0
+void Route::print(){
+ printf("%d ",dis);
+ printf("%d ",twv);
+ printf("%d ",cv);
+ printf("%lf ",cost());
+ printf("[");
+ for(int i=0;i<path_length;i++)
+ {
+ printf("%d ",path[i]);
+ }
+ printf("] ");
+ printf("[");
+ for(int i=0;i<path_length;i++)
+ {
+ printf("%d ",order[i]);
+ }
+ printf("] \n");
+ return;
+
+}
+#endif
+
+void Route::remove( State S){
+ twv=S.twv;
+ cv=S.cv;
+ dis=S.dis;
+ path_length=S.path_length;
+ for(int i=0;i<path_length;i++)
+ {
+ path[i]=S.path[i];
+ order[i]=S.order[i];
+ }
+ return;
+}
+
+
+#endif
diff --git a/src/vrppdtw/src/Solution.h b/src/vrppdtw/src/Solution.h
new file mode 100644
index 0000000..e8690ae
--- /dev/null
+++ b/src/vrppdtw/src/Solution.h
@@ -0,0 +1,185 @@
+/*PGR
+
+Copyright (c) 2014 Manikata Kondeti
+mani.iiit123 at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#ifndef _SOLUTION_H
+#define _SOLUTION_H
+
+#include <vector>
+#include <map>
+#include <queue>
+#include <string>
+#include <stdlib.h>
+#include <iostream>
+#include <algorithm>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <set>
+
+#include "./Route.h"
+
+class Solution{
+ public:
+ Solution(){
+ route_length=0,cost_total=0,twv_total=0,cv_total=0,dis_total=0;
+ }
+ //Variables
+ int twv_total;
+ int cv_total;
+ int dis_total;
+ double cost_total;
+ std::vector<Route> r;
+ int route_length;
+ //Methods
+ void dump();
+ double getCost();
+ Solution getBestofNeighborhood(Solution S, customer *c, depot d, Pickup *p,int CustomerLength, int PickupLength);
+ void UpdateSol();
+
+};
+class Neighborhoods{
+ public:
+ Neighborhoods(){}
+ Solution BestSPI(Solution S, customer *c, depot d, Pickup *p, int CustomerLength, int PickupLength);
+};
+
+
+
+void Solution::UpdateSol()
+{
+ cost_total=0,twv_total=0,cv_total=0,dis_total=0;
+ int routes_del=0;
+ for(int i=0;i<route_length;i++)
+ {
+ twv_total+=r[i].twv;
+ dis_total+=r[i].dis;
+ cv_total+=r[i].cv;
+ cost_total+=r[i].cost();
+ if(r[i].path_length==0)
+ {
+ routes_del++;
+ r.erase(r.begin()+i);
+ }
+ }
+ route_length=route_length-routes_del;
+ return;
+}
+
+
+//Methods in Solution
+
+#if 0
+void Solution::dump(){
+ printf("Routes Length=%d ",route_length);
+ printf("Total Cost=%lf ",cost_total);
+ printf("Total Distance=%d \n",dis_total);
+ printf("Routes \n");
+ for(int i=0;i<route_length;i++)
+ {
+ printf("Route::%d ",i);
+ printf("TWV=%d CV=%d DIS=%d [ ",r[i].twv,r[i].cv,r[i].dis);
+ for(int j=0;j<r[i].path_length;j++)
+ {
+ printf("%d ",r[i].path[j]);
+ }
+ printf("]\n");
+ }
+ return;
+}
+#endif
+
+double Solution::getCost(){
+ cost_total=0;
+ for(unsigned int i=0;i<r.size();i++)
+ {
+ cost_total+=r[i].cost();
+ }
+ return cost_total;
+}
+
+Solution Solution::getBestofNeighborhood(Solution S, customer *c, depot d, Pickup *p, int CustomerLength, int PickupLength){
+ // printf("twv_total=%lf\n",S.cost_total);
+ Neighborhoods N;
+ Solution S1;
+ S1=N.BestSPI(S,c,d,p,CustomerLength,PickupLength);
+ return S1;
+}
+
+
+
+Solution Neighborhoods::BestSPI(Solution S, customer *c, depot d, Pickup *p, int CustomerLength, int PickupLength){
+ Solution CurrSol,BestSol,TempSol;
+ CurrSol=BestSol=S;
+ Pickup *OrderRequests=NULL;
+ OrderRequests= (Pickup *)malloc(2000*sizeof(Pickup));
+ int Ro_flag,Hc_flag;
+ State TempState;
+ //Copy Order requests from pickup's
+ for(int order=1;order<=PickupLength;order++)
+ {
+ OrderRequests[order]=p[order];
+ }
+
+ //Main SPI
+ for(int order=1;order<=PickupLength;order++)
+ {
+ //Order Find and Remove it!
+ for(unsigned int route_remove=0;route_remove<CurrSol.r.size();route_remove++)
+ {
+ Ro_flag=CurrSol.r[route_remove].RemoveOrder(OrderRequests[order]);
+ TempSol=CurrSol;
+ if(Ro_flag==1)
+ {
+ //Insert, Total Cost, (if it is more copy back the solution) , (else store best=temp, checked=2, break )
+ for(unsigned int route=0;route<CurrSol.r.size();route++)
+ {
+ TempState=CurrSol.r[route].append(c,OrderRequests[order],d,CustomerLength, PickupLength,TempState);
+ Hc_flag=CurrSol.r[route].insertOrder(c,d,OrderRequests[order]);
+ // Hc flag tells us about insertion
+ if(Hc_flag==0)
+ {
+ if(CurrSol.r[route].cost() <= BestSol.r[route].cost())
+ {
+ CurrSol.UpdateSol();
+ BestSol=CurrSol;
+ }
+ }
+ TempSol.UpdateSol();
+ CurrSol=TempSol;
+ // CurrSol = BestSol;
+ }
+ BestSol.UpdateSol();
+ CurrSol = BestSol;
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ }
+ BestSol.UpdateSol();
+ return BestSol;
+}
+
+
+
+#endif
diff --git a/src/vrppdtw/src/pdp.c b/src/vrppdtw/src/pdp.c
new file mode 100644
index 0000000..f7a0807
--- /dev/null
+++ b/src/vrppdtw/src/pdp.c
@@ -0,0 +1,478 @@
+/*PGR
+
+Copyright (c) 2014 Manikata Kondeti
+mani.iiit123 at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include "./postgres.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "catalog/pg_type.h"
+#if PGSQL_VERSION > 92
+#include "access/htup_details.h"
+#endif
+
+#include "fmgr.h"
+#include "./pdp.h"
+
+
+Datum vrppdtw(PG_FUNCTION_ARGS);
+
+
+#undef DEBUG
+//#define DEBUG 1
+
+#ifdef DEBUG
+#define DBG(format, arg...) \
+ elog(NOTICE, format , ## arg)
+#else
+#define DBG(format, arg...) do { ; } while (0)
+#endif
+
+// The number of tuples to fetch from the SPI cursor at each iteration
+#define TUPLIMIT 1000
+
+#ifndef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+
+
+static char *text2char(text *in)
+{
+ char *out = (char*)palloc(VARSIZE(in));
+
+ memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
+ out[VARSIZE(in) - VARHDRSZ] = '\0';
+ return out;
+}
+
+ static int
+ finish(int code, int ret)
+ {
+ code = SPI_finish();
+ if (code != SPI_OK_FINISH ) {
+ elog(ERROR,"couldn't disconnect from SPI");
+ return -1 ;
+ }
+ return ret;
+ }
+
+
+typedef struct Customer_type{
+ int id;
+ int x;
+ int y;
+ int demand;
+ int Etime;
+ int Ltime;
+ int Stime;
+ int Pindex;
+ int Dindex;
+}customer_t;
+
+
+
+#if 0
+static int conn(int *SPIcode)
+{
+ int res = 0;
+
+ *SPIcode = SPI_connect();
+
+ if (*SPIcode != SPI_OK_CONNECT)
+ {
+ elog(ERROR, "vrppdtw: couldn't open a connection to SPI");
+ res = -1;
+ }
+
+ return res;
+}
+
+static int prepare_query(Portal *SPIportal, char* sql)
+{
+ int res = 0;
+
+ void* SPIplan = SPI_prepare(sql, 0, NULL);
+
+ if (SPIplan == NULL)
+ {
+ elog(ERROR, "vrppdtw: couldn't create query plan via SPI");
+ res = -1;
+ }
+
+ if ((*SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL)
+ {
+ elog(ERROR, "vrppdtw: SPI_cursor_open('%s') returns NULL", sql);
+ res = -1;
+ }
+
+ return res;
+}
+#endif
+
+static int fetch_customer_columns(SPITupleTable *tuptable, customer_t *c , int vehicle_count , int capacity)
+{
+ DBG("Customer Data");
+
+ c->id = SPI_fnumber(SPI_tuptable->tupdesc, "id");
+ DBG(" id done ");
+ c->x = SPI_fnumber(SPI_tuptable->tupdesc, "x");
+ DBG("x done");
+ c->y = SPI_fnumber(SPI_tuptable->tupdesc, "y");
+ DBG("y done");
+ c->demand = SPI_fnumber(SPI_tuptable->tupdesc, "demand");
+ DBG("demand done");
+ c->Etime = SPI_fnumber(SPI_tuptable->tupdesc, "etime");
+ DBG("etime done");
+ c->Ltime = SPI_fnumber(SPI_tuptable->tupdesc, "ltime");
+ DBG("ltime done");
+ c->Stime = SPI_fnumber(SPI_tuptable->tupdesc, "stime");
+ DBG("stime done");
+ c->Pindex = SPI_fnumber(SPI_tuptable->tupdesc, "pindex");
+ DBG("pindex done");
+ c->Dindex = SPI_fnumber(SPI_tuptable->tupdesc, "dindex");
+ DBG("dindex done");
+ if (c->id == SPI_ERROR_NOATTRIBUTE ||
+ c->x == SPI_ERROR_NOATTRIBUTE ||
+ c->y == SPI_ERROR_NOATTRIBUTE ||
+ c->demand == SPI_ERROR_NOATTRIBUTE ||
+ c->Ltime == SPI_ERROR_NOATTRIBUTE ||
+ c->Stime == SPI_ERROR_NOATTRIBUTE ||
+ c->Pindex == SPI_ERROR_NOATTRIBUTE ||
+ c->Dindex == SPI_ERROR_NOATTRIBUTE ||
+ c->Etime == SPI_ERROR_NOATTRIBUTE)
+ {
+ elog(ERROR, "Error, query must return columns "
+ "'id', 'x','y','demand', 'Etime', 'Ltime', 'Stime', 'Pindex', and 'Dindex'");
+ return -1;
+ }
+
+ DBG("Returned from here ");
+ return 0;
+}
+
+
+static void fetch_customer(HeapTuple *tuple, TupleDesc *tupdesc, customer_t *c_all, customer *c_single)
+{
+ Datum binval;
+ bool isnull;
+ DBG("Hey baby in fetch_customer");
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->id, &isnull);
+ DBG("fetching first thing");
+ if (isnull) elog(ERROR, "id contains a null value");
+ c_single->id = DatumGetInt32(binval);
+ DBG("id = %d", c_single->id);
+
+
+ DBG("fetching second thing");
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->x, &isnull);
+ if (isnull)
+ elog(ERROR, "x contains a null value");
+ c_single->x = DatumGetInt32(binval);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->y, &isnull);
+ if (isnull) elog(ERROR, "y contains a null value");
+ c_single->y = DatumGetInt32(binval);
+
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->demand, &isnull);
+ if (isnull) elog(ERROR, "demand contains a null value");
+ c_single->demand = DatumGetInt32(binval);
+
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->Etime, &isnull);
+ if (isnull) elog(ERROR, "Etime contains a null value");
+ c_single->Etime = DatumGetInt32(binval);
+
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->Ltime, &isnull);
+ if (isnull) elog(ERROR, "Ltime contains a null value");
+ c_single->Ltime = DatumGetInt32(binval);
+
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->Stime, &isnull);
+ if (isnull) elog(ERROR, "Stime contains a null value");
+ c_single->Stime = DatumGetInt32(binval);
+
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->Pindex, &isnull);
+ if (isnull) elog(ERROR, "pindex contains a null value");
+ c_single->Pindex = DatumGetInt32(binval);
+
+ binval = SPI_getbinval(*tuple, *tupdesc, c_all->Dindex, &isnull);
+ if (isnull) elog(ERROR, "dindex contains a null value");
+ c_single->Dindex = DatumGetInt32(binval);
+
+ return;
+}
+
+
+
+
+//Note:: edge_colums = total , //ly customer_t = total ....
+
+static int compute_shortest_path(char* sql, int vehicle_count, int capacity , path_element **results, int *length_results_struct)
+{
+
+ int SPIcode;
+ void *SPIplan;
+ Portal SPIportal;
+ bool moredata = TRUE;
+ int ntuples;
+ customer *customer_single=NULL;
+ int total_tuples = 0;
+ customer_t customer_all = {.id= -1, .x=-1, .y=-1 , .demand=-1 , .Etime=-1, .Ltime=-1 , .Stime=-1 , .Pindex=-1 , .Dindex=-1 }; // write this
+
+ char *err_msg;
+ int ret = -1;
+ // register int z;
+
+ DBG("start shortest_path\n");
+
+ SPIcode = SPI_connect();
+ if (SPIcode != SPI_OK_CONNECT) {
+ elog(ERROR, "shortest_path: couldn't open a connection to SPI");
+ return -1;
+ }
+
+ SPIplan = SPI_prepare(sql, 0, NULL);
+ if (SPIplan == NULL) {
+ elog(ERROR, "shortest_path: couldn't create query plan via SPI");
+ return -1;
+ }
+
+ if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) {
+ elog(ERROR, "shortest_path: SPI_cursor_open('%s') returns NULL", sql);
+ return -1;
+ }
+
+ while (moredata == TRUE) {
+ SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
+
+ DBG("Checking ");
+
+ if (customer_all.id == -1) {
+ if (fetch_customer_columns(SPI_tuptable, &customer_all,vehicle_count, capacity) == -1)
+ {
+ return finish(SPIcode, ret);
+ }
+ DBG("Here I am ");
+ }
+
+ ntuples = SPI_processed;
+ total_tuples += ntuples;
+ DBG("Calculated total_tuples ntuples=%d total_tuples =%d ", ntuples, total_tuples);
+
+ if (customer_single==NULL)
+ customer_single = palloc(total_tuples * sizeof(customer));
+ else
+ customer_single = repalloc(customer_single, total_tuples * sizeof(customer));
+
+
+ DBG("Error here ");
+ if (customer_single == NULL) {
+ elog(ERROR, "Out of memory");
+ return finish(SPIcode, ret);
+ }
+
+
+
+ if (ntuples > 0) {
+ DBG("Check here ");
+ int t;
+ SPITupleTable *tuptable = SPI_tuptable;
+ TupleDesc tupdesc = SPI_tuptable->tupdesc;
+
+ for (t = 0; t < ntuples; t++) {
+ DBG("In for loop ");
+ HeapTuple tuple = tuptable->vals[t];
+ DBG("Manikanta ");
+ fetch_customer(&tuple, &tupdesc, &customer_all , &customer_single[total_tuples - ntuples + t]);
+ DBG("After Function call");
+ }
+ SPI_freetuptable(tuptable);
+ }
+ else {
+ moredata = FALSE;
+ }
+ }
+
+ int k;
+ for(k=0;k<total_tuples;k++)
+ {
+ DBG("%d %d %d %d %d %d %d %d %d" , customer_single[k].id, customer_single[k].x , customer_single[k].y , customer_single[k].demand , customer_single[k].Etime ,customer_single[k].Ltime ,customer_single[k].Stime, customer_single[k].Pindex, customer_single[k].Dindex);
+ }
+
+ DBG("Calling Solver Instance\n");
+
+
+ ret = Solver(customer_single, total_tuples, vehicle_count, capacity , &err_msg,results, length_results_struct);
+
+ if (ret < -2) {
+ //elog(ERROR, "Error computing path: %s", err_msg);
+ ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
+ errmsg("Error computing path: %s", err_msg)));
+ }
+
+
+ DBG("*length_results_count = %i\n", *length_results_struct);
+
+ DBG("ret = %i\n", ret);
+
+
+
+
+ int vb;
+ for(vb=1;vb<*length_results_struct;vb++)
+ {
+ DBG("results[%d].seq=%d ",vb, (*results)[vb].seq);
+ DBG("results[%d].rid=%d ",vb, (*results)[vb].rid);
+ DBG("results[%d].nid=%d \n",vb, (*results)[vb].nid);
+ }
+
+ pfree(customer_single);
+ DBG("Working till here ");
+ return finish(SPIcode, ret);
+
+}
+
+
+
+PG_FUNCTION_INFO_V1(vrppdtw);
+ Datum
+vrppdtw(PG_FUNCTION_ARGS)
+{
+ FuncCallContext *funcctx;
+ int call_cntr;
+ int max_calls;
+ TupleDesc tuple_desc;
+ path_element *results = 0;
+
+
+ /* stuff done only on the first call of the function */
+
+ if (SRF_IS_FIRSTCALL())
+
+ {
+ MemoryContext oldcontext;
+ // int ret;
+ int length_results_struct = 0;
+
+
+
+
+ /* create a function context for cross-call persistence */
+
+ funcctx = SRF_FIRSTCALL_INIT();
+
+
+
+ /* switch to memory context appropriate for multiple function calls */
+
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+
+ results = (path_element *)palloc(sizeof(path_element)*((length_results_struct)+1));
+
+ DBG("Calling compute_shortes_path");
+
+
+
+ // ret =
+ compute_shortest_path(
+
+ text2char(PG_GETARG_TEXT_P(0)), // customers sql
+
+ PG_GETARG_INT32(1), // vehicles count
+
+ PG_GETARG_INT32(2), // capacity count
+
+ &results, &length_results_struct
+ );
+
+ DBG("Back from solve_vrp, length_results: %d", length_results_struct);
+
+ /* total number of tuples to be returned */
+ funcctx->max_calls = length_results_struct;
+ funcctx->user_fctx = results;
+
+ /* Build a tuple descriptor for our result type */
+ 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 = BlessTupleDesc(tuple_desc);
+
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ call_cntr = funcctx->call_cntr;
+ max_calls = funcctx->max_calls;
+ tuple_desc = funcctx->tuple_desc;
+ results = (path_element *) funcctx->user_fctx;
+
+ /* do when there is more left to send */
+ if (call_cntr < max_calls) {
+ HeapTuple tuple;
+ Datum result;
+ Datum *values;
+ char* nulls;
+
+ DBG("Till hereee ");
+ values = palloc(4 * sizeof(Datum));
+ nulls = palloc(4 * sizeof(char));
+
+ values[0] = Int32GetDatum(results[call_cntr].seq);
+ nulls[0] = ' ';
+ values[1] = Int32GetDatum(results[call_cntr].rid);
+ nulls[1] = ' ';
+ values[2] = Int32GetDatum(results[call_cntr].nid);
+ nulls[2] = ' ';
+ values[3] = Int32GetDatum(results[call_cntr].cost);
+ nulls[3] = ' ';
+ tuple = heap_formtuple(tuple_desc, values, nulls);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ /* clean up (this is not really necessary) */
+ pfree(values);
+ pfree(nulls);
+
+ SRF_RETURN_NEXT(funcctx, result);
+ }
+ /* do when there is no more left */
+ else {
+ DBG("Ending function\n");
+
+ free(results);
+ DBG("Itinerary cleared\n");
+
+
+ SRF_RETURN_DONE(funcctx);
+ }
+
+
+}
diff --git a/src/vrppdtw/src/pdp.h b/src/vrppdtw/src/pdp.h
new file mode 100644
index 0000000..40dae60
--- /dev/null
+++ b/src/vrppdtw/src/pdp.h
@@ -0,0 +1,191 @@
+/*PGR
+
+Copyright (c) 2014 Manikata Kondeti
+mani.iiit123 at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include<stdio.h>
+#include<stdlib.h>
+#include<math.h>
+#include "postgres.h"
+
+#ifndef _PDP_H
+#define _PDP_H
+
+
+// Structures and variables which help us in storing the data
+
+typedef struct Depot{
+ int id;
+ int x;
+ int y;
+ int demand;
+ int Etime;
+ int Ltime;
+ int Stime;
+ int Pindex;
+ int Dindex;
+}depot;
+
+
+
+typedef struct Customer{
+ int id;
+ int x;
+ int y;
+ int demand;
+ int Etime;
+ int Ltime;
+ int Stime;
+ int Pindex;
+ int Dindex;
+ double Ddist;
+ int P;
+ int D;
+}customer;
+
+
+typedef struct Pickup{
+ int id;
+ int Pid;
+ double Ddist;
+ int Did;
+ int checked;
+}pickup;
+
+
+
+typedef struct Vehicle{
+ int capacity;
+ int used_vehicles;
+ int given_vehicles;
+ int speed;
+ int cost;
+}VehicleInfo;
+
+
+// A module which calculates distance
+double CalculateDistance(int x1,int y1,int x2,int y2)
+{
+ return sqrt(((x2-x1)*(x2-x1))+((y2-y1)*(y2-y1)));
+}
+
+/*
+// DEPOT: With id=0
+depot ScanDepot(depot d)
+{
+
+scanf("%d",&d.id);
+scanf("%d",&d.x);
+scanf("%d",&d.y);
+scanf("%d",&d.demand);
+scanf("%d",&d.Etime);
+scanf("%d",&d.Ltime);
+scanf("%d",&d.Stime);
+scanf("%d",&d.Pindex);
+scanf("%d",&d.Dindex);
+return d;
+}
+
+// CUSTOMER: WITH id>=1
+customer ScanCustomer(int id,customer c,depot d)
+{
+c.id=id;
+scanf("%d",&c.x);
+scanf("%d",&c.y);
+scanf("%d",&c.demand);
+scanf("%d",&c.Etime);
+scanf("%d",&c.Ltime);
+scanf("%d",&c.Stime);
+scanf("%d",&c.Pindex);
+scanf("%d",&c.Dindex);
+if(c.Pindex==0)
+{
+c.P=1;
+c.D=0;
+}
+else if(c.Dindex==0)
+{
+c.D=1;
+c.P=0;
+}
+c.Ddist=CalculateDistance(c.x,c.y,d.x,d.y);
+return c;
+}
+
+
+//VEHICLE: First Line contains vehicle data
+VehicleInfo ScanVehicle(VehicleInfo Vehicle)
+{
+scanf("%d",&Vehicle.given_vehicles);
+scanf("%d",&Vehicle.capacity);
+scanf("%d",&Vehicle.speed);
+Vehicle.used_vehicles=0;
+return Vehicle;
+
+}
+
+
+ */
+
+
+// Part of code: It is used to save some variables and helps if we need to revisit previous state.
+typedef struct statesave{
+ int twv;
+ int cv;
+ int dis;
+ // vector<int> path;
+ // vector<int> order;
+ int path[1000];
+ int order[1000];
+ int path_length;
+}State;
+
+
+typedef struct PathElement {
+ int seq;
+ int rid;
+ int nid;
+ int nseq;
+ int cost;
+} path_element;
+
+
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int Solver(customer *c, int total_tuples, int vehicle_count, int capacity , char **msg, path_element **results, int *length_results);
+
+#ifdef __cplusplus
+extern "C"
+#endif
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
diff --git a/src/vrppdtw/src/pdp_solver.cpp b/src/vrppdtw/src/pdp_solver.cpp
new file mode 100644
index 0000000..e154607
--- /dev/null
+++ b/src/vrppdtw/src/pdp_solver.cpp
@@ -0,0 +1,445 @@
+/*PGR
+
+Copyright (c) 2014 Manikata Kondeti
+mani.iiit123 at gmail.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+/*
+
+ *****list of files in this dir*******
+ pdp.cpp --> Main solver
+ pdp.h ---> Structures defined in this header file
+ Solution.h -----> It contains the Solution Class and Code related to Neighborhoods
+ Route.h -----> Explains all about Route Class.
+ pdp.c ---> Contains all the details on pgRouting integration.
+
+ The main problem is in two steps. 1.)Getting the initial solutiion and 2.)Optimizing it.
+
+ 1.) "Initial solution":
+ A few heuristics are applied to find a feasible initial solution. Sequential Construction and Hill climbing. More implementation details are found here:: https://github.com/pgRouting/pgrouting/wiki/VRP-Pickup-Delivery-Problem
+
+ 2.) "Optimizing the Solution":
+ A reactive tabu search is applied on the initial solution to get a feasible optimized solution. TabuSearch comes under local search methods. We have three neighborhoods
+ i) Single Paired Insertion
+ ii) Swapping pairs between routes
+ iii)Within Route Insertion.
+ Tabu attributes plays an important role in giving the best solution(it includes TabuLength, A vector containing feasible solutions and a counter for number of solutions).
+ Reactive part discussed in the paper is to modify TabuLength based on the solution cycle.
+
+ */
+#ifdef __MINGW32__
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+
+#include <vector>
+#include <map>
+#include <queue>
+#include <string>
+#include <stdlib.h>
+#include <iostream>
+#include <algorithm>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <set>
+//Headers Include
+#include "./pdp.h"
+#include "./Solution.h"
+#include "./Route.h"
+
+
+int PickupLength=0;
+
+//Depot
+depot d;
+//Vehicle
+//Customer Data
+customer *c=NULL;
+pickup *p=NULL;
+int len=0;
+
+int CustomerLength;
+
+
+std::vector<Solution> T;
+
+Route *r=NULL;
+//Definitions for a few functions
+int TabuSearch();
+//Vector containing solutions
+
+//Initial Solution
+Solution S0;
+
+void result_struct();
+int Solver(customer *c1,int total_tuples, int VehicleLength, int capacity , char **msg, path_element **results, int *length_results_struct)
+{
+ CustomerLength= total_tuples-1;
+
+ c = (customer *)malloc((CustomerLength+5)*sizeof(customer));
+ p = (pickup *)malloc((CustomerLength+5)*sizeof(pickup));
+ r = (Route *)malloc((CustomerLength+5)*sizeof(Route));
+VehicleInfo Vehicle;
+ //Depot Data
+ d.id = c1[0].id;
+ d.x = c1[0].x;
+ d.y = c1[0].y;
+ d.demand = c1[0].demand;
+ d.Etime = c1[0].Etime;
+ d.Ltime = c1[0].Ltime;
+ d.Stime = c1[0].Stime;
+ d.Pindex = c1[0].Pindex;
+ d.Dindex = c1[0].Dindex;
+
+
+ //Customer Data
+ for(int i=1;i<=CustomerLength;i++)
+ {
+ c[i].id = c1[i].id;
+ c[i].x = c1[i].x;
+ c[i].y = c1[i].y;
+ c[i].Etime = c1[i].Etime;
+ c[i].demand = c1[i].demand;
+ c[i].Ltime = c1[i].Ltime;
+ c[i].Stime = c1[i].Stime;
+ c[i].Pindex = c1[i].Pindex;
+ c[i].Dindex = c1[i].Dindex;
+ c[i].Ddist= CalculateDistance(c[i].x, c[i].y ,d.x, d.y);
+ if(c[i].Pindex==0){
+ c[i].P=1;
+ c[i].D=0;
+ }
+ if(c[i].Dindex==0){
+ c[i].D=1;
+ c[i].P=0;
+ }
+ }
+
+ //Vehicle Data
+
+ Vehicle.given_vehicles = VehicleLength;
+ Vehicle.capacity = capacity;
+ Vehicle.speed = 1;
+ Vehicle.used_vehicles=0;
+
+
+
+
+ //From customers put aside all the pickup's;
+ for(int i=1;i<=CustomerLength;i++){
+ if(c[i].P==1){
+ PickupLength+=1;
+ p[PickupLength].id=PickupLength;
+ p[PickupLength].Did=c[i].Dindex;
+ p[PickupLength].Ddist=c[i].Ddist;
+ p[PickupLength].Pid=c[i].id;
+ }
+ }
+ // printf("Pickup Length=%d \n",PickupLength);
+
+ //Sort Pickup's
+ int swap;
+ double swap1;
+ for(int i=1;i<=PickupLength;i++)
+ {
+ for(int j=1;j<=PickupLength-i;j++){
+ if(p[j].Ddist>p[j+1].Ddist){
+ swap1=p[j].Ddist;
+ p[j].Ddist=p[j+1].Ddist;
+ p[j+1].Ddist=swap1;
+ swap=p[j].Did;
+ p[j].Did=p[j+1].Did;
+ p[j+1].Did=swap;
+ swap=p[j].Pid;
+ p[j].Pid=p[j+1].Pid;
+ p[j+1].Pid=swap;
+ swap=p[j].id;
+ p[j].id=p[j+1].id;
+ p[j+1].id=swap;
+ }
+ }
+ p[i].checked=0;
+ }
+
+
+ for(int i=1;i<=PickupLength;i++)
+ {
+ // DBG("PickupID[%d]=%lf\n",p[i].id,p[i].Ddist);
+ }
+
+ // int flag_complete=0;
+ int checked=0;
+ //Sequential Construction
+ for(int v=1;v<110;v++){
+ for(int i=PickupLength;i>=1;i--){
+ if(p[i].checked!=1){
+ State S;
+ S=r[v].append(c,p[i],d,CustomerLength,PickupLength,S);
+ int flag=r[v].HillClimbing(c,d,p[i]);
+ if(flag==1){
+ //Remove
+ p[i].checked=0;
+ r[v].remove(S);
+ }
+ else{
+ p[i].checked=1;
+ checked+=1;
+ }
+ }
+ //Requests complete
+ }
+ Vehicle.used_vehicles=v;
+ if(checked==PickupLength)
+ {
+ v=9999;
+ }
+ }
+ // *length_results_struct = d.Ltime;
+ int sum=0,rts=0;
+
+ for(int i=1;i<=Vehicle.used_vehicles;i++){
+ // printf("%d, ",i);
+ // r[i].print();
+ sum+=r[i].dis;
+ if(r[i].dis!=0){
+ rts+=1;
+ }
+ Vehicle.cost=sum;
+ }
+ // printf("Sum=%d Routes=%d Vehicle.used_vehicles=%d\n",sum,rts,Vehicle.used_vehicles);
+
+ //Storing Initial Solution (S0 is the Initial Solution)
+ for(int i=1;i<=Vehicle.used_vehicles;i++)
+ {
+ S0.cost_total+=r[i].cost();
+ S0.dis_total+=r[i].dis;
+ S0.twv_total+=r[i].twv;
+ S0.cv_total+=r[i].cv;
+ }
+ S0.route_length=Vehicle.used_vehicles;
+ for(int i=1;i<=Vehicle.used_vehicles;i++)
+ {
+ S0.r.push_back(r[i]);
+ }
+ // printf("Size =>> S0.r.size=%ld\n", S0.r.size());
+
+
+ //Starting Neighborhoods
+ // printf("\nNeighborhoods From now\n");
+ int sol_count=TabuSearch();
+
+ //Copying back the results
+ // path_element->results , path_length { we need to send (results, length_results) backk ;
+ int nodes_count;
+ nodes_count= CustomerLength;
+ *results = (path_element *) malloc(sizeof(path_element) * (nodes_count + 5*VehicleLength));
+ int length_results=0;
+
+
+
+ int *cost, *cost_nodes;
+ cost = (int *)malloc(1000*sizeof(int));
+ cost_nodes = (int *)malloc(1000*sizeof(int));
+ //Cost Calculation
+
+ int copy_length=0;
+ // TAKE AN ARRAY EMBED EVERYTHING
+ for(int itr_route=0;itr_route<T[sol_count].route_length;itr_route++)
+ {
+ cost[copy_length]=d.id;
+ copy_length++;
+ for(int itr_node=0;itr_node<T[sol_count].r[itr_route].path_length;itr_node++)
+ {
+ cost[copy_length]=T[sol_count].r[itr_route].path[itr_node];
+ copy_length++;
+ }
+ cost[copy_length]=d.id;
+ copy_length++;
+ }
+
+ copy_length-=1;
+ int temp_dis=0;
+ for(int i=0;i<copy_length;i++)
+ {
+ if(i==0)
+ {
+ cost_nodes[0]=0;
+ temp_dis=0;
+ }
+ else
+ {
+ //Depot to first node
+ if(cost[i-1]==d.id && cost[i]!=d.id )
+ {
+ temp_dis=0;
+ temp_dis+=sqrt(((c[cost[i]].x-d.x)*(c[cost[i]].x-d.x))+((c[cost[i]].y-d.y)*(c[cost[i]].y-d.y)));
+ if(temp_dis < c[cost[i]].Etime)
+ {
+ temp_dis=c[cost[i]].Etime;
+ }
+
+ cost_nodes[i]=temp_dis;
+ }
+
+ //Between nodes
+ else if(cost[i-1]!=d.id && cost[i]!=d.id)
+ {
+ temp_dis+=sqrt(((c[cost[i]].x-c[cost[i-1]].x)*(c[cost[i]].x-c[cost[i-1]].x))+((c[cost[i]].y-c[cost[i-1]].y)*(c[cost[i]].y-c [cost[i-1]].y)));
+
+ if(temp_dis < c[cost[i]].Etime)
+ {
+ temp_dis=c[cost[i]].Etime;
+ }
+
+ temp_dis+=c[cost[i-1]].Stime;
+ cost_nodes[i]=temp_dis;
+ }
+ else if(cost[i]==d.id && cost[i-1]!=d.id)
+ {
+ temp_dis+=sqrt(((d.x-c[cost[i-1]].x)*(d.x-c[cost[i-1]].x))+((d.y-c[cost[i-1]].y)*(d.y-c[cost[i-1]].y)));
+ cost_nodes[i]=temp_dis;
+ temp_dis=0;
+ }
+ else if(cost[i]==d.id && cost[i-1]==d.id)
+ {
+ cost_nodes[i]=0;
+ temp_dis=0;
+ }
+ }
+ //Last node to deopt
+ }
+
+ //Done cost calculation
+
+
+ for(int itr_route=0; itr_route<T[sol_count].route_length; itr_route++)
+ {
+ (*results)[length_results].seq = length_results;
+ (*results)[length_results].rid = itr_route+1;
+ (*results)[length_results].nid = d.id;
+ (*results)[length_results].cost = cost_nodes[length_results];
+ length_results++;
+
+ //Loop for path elements.
+ for(int itr_node=0;itr_node < T[sol_count].r[itr_route].path_length;itr_node++)
+ {
+ (*results)[length_results].seq = length_results;
+ (*results)[length_results].rid = itr_route+1;
+ (*results)[length_results].nid = T[sol_count].r[itr_route].path[itr_node];
+ (*results)[length_results].cost = cost_nodes[length_results];
+ length_results++;
+ }
+
+ (*results)[length_results].seq = length_results;
+ (*results)[length_results].rid = itr_route+1;
+ (*results)[length_results].nid = d.id;
+ (*results)[length_results].cost = cost_nodes[length_results];
+ length_results++;
+
+ }
+
+ *length_results_struct = length_results;
+ free(c);
+ free(p);
+ free(r);
+
+//Copying is done till here
+
+ return 0;
+}
+int n=0,maxItr=30;
+
+
+
+/* TABU search helps us to store the solutions after every different move. The overview of TABU search will be a list containing list of solutions*/
+
+int TabuSearch()
+{
+ // printf("TABU Called\n");
+ Solution S,SBest;
+ double CBest;
+ //Pseudo Code
+ /*
+
+ **********Before*********
+ int n=0; //Counter
+
+ Create Tabu List Vector of Solutions std::vector<Solution> T;
+
+ **********After**********
+ Solution S,S0,SBest; //S0 is initial
+ S=S0;
+ Double CBest,SBest;
+ CBest = S.getCost();
+ SBest = S0;
+ n=0; //Counter
+ while(1)
+ {
+ S = S.getBextofNeighborhood();
+ if(S==NULL)
+ break;
+ if(S.getCost() < CBest){
+ SBest = S;
+ CBest = S.getCost();
+ }
+ T.push_back(S);
+ n++;
+ if(n>maxItr)
+ break;
+ }
+
+ */
+
+ S=S0;
+ CBest = S.getCost();
+ SBest = S0;
+ T.clear();
+ T.push_back(S0);
+ while(1)
+ {
+ S = S.getBestofNeighborhood(S,c,d,p,CustomerLength,PickupLength);
+ if(S.getCost()==0)
+ break;
+ if (S.getCost() < CBest){
+ SBest = S;
+ CBest = S.getCost();
+ T.push_back(S);
+ }
+ else if(S.getCost() == CBest )
+ {
+ // printf("\n****************Repeated Solution****************\n");
+ int k= ((12)*maxItr)/100;
+ maxItr = maxItr-k;
+ // printf("Maxitr after repeating %d k =%d\n",maxItr,k);
+ }
+ n++;
+ if (n > maxItr)
+ break;
+ }
+#if 0
+ printf("Size of Tabu=%ld &&& n=%d maxItr=%d\n",T.size(),n,maxItr);
+ for(unsigned int itr=0;itr<T.size();itr++)
+ {
+ T[itr].dump();
+ }
+#endif
+ return T.size()-1;
+}
+
diff --git a/src/common/src/CMakeLists.txt b/src/vrppdtw/test/CMakeLists.txt
similarity index 100%
copy from src/common/src/CMakeLists.txt
copy to src/vrppdtw/test/CMakeLists.txt
diff --git a/src/vrppdtw/test/pdp-any-00.data b/src/vrppdtw/test/pdp-any-00.data
new file mode 100644
index 0000000..9347f06
--- /dev/null
+++ b/src/vrppdtw/test/pdp-any-00.data
@@ -0,0 +1,120 @@
+drop table if exists customer cascade;
+create table customer (
+ id integer not null primary key,
+ x integer,
+ y integer,
+ demand integer,
+ etime integer,
+ ltime integer,
+ stime integer,
+ pindex integer,
+ dindex integer
+ );
+copy customer (id,x,y,demand,etime,ltime, stime,pindex, dindex) from stdin;
+0 40 50 0 0 1236 0 0 0
+1 45 68 -10 912 967 90 11 0
+2 45 70 -20 825 870 90 6 0
+3 42 66 10 65 146 90 0 75
+4 42 68 -10 727 782 90 9 0
+5 42 65 10 15 67 90 0 7
+6 40 69 20 621 702 90 0 2
+7 40 66 -10 170 225 90 5 0
+8 38 68 20 255 324 90 0 10
+9 38 70 10 534 605 90 0 4
+10 35 66 -20 357 410 90 8 0
+11 35 69 10 448 505 90 0 1
+12 25 85 -20 652 721 90 18 0
+13 22 75 30 30 92 90 0 17
+14 22 85 -40 567 620 90 16 0
+15 20 80 -10 384 429 90 19 0
+16 20 85 40 475 528 90 0 14
+17 18 75 -30 99 148 90 13 0
+18 15 75 20 179 254 90 0 12
+19 15 80 10 278 345 90 0 15
+20 30 50 10 10 73 90 0 24
+21 30 52 -10 914 965 90 30 0
+22 28 52 -20 812 883 90 28 0
+23 28 55 10 732 777 0 0 103
+24 25 50 -10 65 144 90 20 0
+25 25 52 40 169 224 90 0 27
+26 25 55 -10 622 701 90 29 0
+27 23 52 -40 261 316 90 25 0
+28 23 55 20 546 593 90 0 22
+29 20 50 10 358 405 90 0 26
+30 20 55 10 449 504 90 0 21
+31 10 35 -30 200 237 90 32 0
+32 10 40 30 31 100 90 0 31
+33 8 40 40 87 158 90 0 37
+34 8 45 -30 751 816 90 38 0
+35 5 35 10 283 344 90 0 39
+36 5 45 10 665 716 0 0 105
+37 2 40 -40 383 434 90 33 0
+38 0 40 30 479 522 90 0 34
+39 0 45 -10 567 624 90 35 0
+40 35 30 -20 264 321 90 42 0
+41 35 32 -10 166 235 90 43 0
+42 33 32 20 68 149 90 0 40
+43 33 35 10 16 80 90 0 41
+44 32 30 10 359 412 90 0 46
+45 30 30 10 541 600 90 0 48
+46 30 32 -10 448 509 90 44 0
+47 30 35 -10 1054 1127 90 49 0
+48 28 30 -10 632 693 90 45 0
+49 28 35 10 1001 1066 90 0 47
+50 26 32 10 815 880 90 0 52
+51 25 30 10 725 786 0 0 101
+52 25 35 -10 912 969 90 50 0
+53 44 5 20 286 347 90 0 58
+54 42 10 40 186 257 90 0 60
+55 42 15 -40 95 158 90 57 0
+56 40 5 30 385 436 90 0 59
+57 40 15 40 35 87 90 0 55
+58 38 5 -20 471 534 90 53 0
+59 38 15 -30 651 740 90 56 0
+60 35 5 -40 562 629 90 54 0
+61 50 30 -10 531 610 90 67 0
+62 50 35 20 262 317 90 0 68
+63 50 40 50 171 218 90 0 74
+64 48 30 10 632 693 0 0 102
+65 48 40 10 76 129 90 0 72
+66 47 35 10 826 875 90 0 69
+67 47 40 10 12 77 90 0 61
+68 45 30 -20 734 777 90 62 0
+69 45 35 -10 916 969 90 66 0
+70 95 30 -30 387 456 90 81 0
+71 95 35 20 293 360 90 0 77
+72 53 30 -10 450 505 90 65 0
+73 92 30 -10 478 551 90 76 0
+74 53 35 -50 353 412 90 63 0
+75 45 65 -10 997 1068 90 3 0
+76 90 35 10 203 260 90 0 73
+77 88 30 -20 574 643 90 71 0
+78 88 35 20 109 170 0 0 104
+79 87 30 10 668 731 90 0 80
+80 85 25 -10 769 820 90 79 0
+81 85 35 30 47 124 90 0 70
+82 75 55 20 369 420 90 0 85
+83 72 55 -20 265 338 90 87 0
+84 70 58 20 458 523 90 0 89
+85 68 60 -20 555 612 90 82 0
+86 66 55 10 173 238 90 0 91
+87 65 55 20 85 144 90 0 83
+88 65 60 -10 645 708 90 90 0
+89 63 58 -20 737 802 90 84 0
+90 60 55 10 20 84 90 0 88
+91 60 60 -10 836 889 90 86 0
+92 67 85 20 368 441 90 0 93
+93 65 85 -20 475 518 90 92 0
+94 65 82 -10 285 336 90 96 0
+95 62 80 -20 196 239 90 98 0
+96 60 80 10 95 156 90 0 94
+97 60 85 30 561 622 0 0 106
+98 58 75 20 30 84 90 0 95
+99 55 80 -20 743 820 90 100 0
+100 55 85 20 647 726 90 0 99
+101 25 30 -10 725 786 90 51 0
+102 48 30 -10 632 693 90 64 0
+103 28 55 -10 732 777 90 23 0
+104 88 35 -20 109 170 90 78 0
+105 5 45 -10 665 716 90 36 0
+106 60 85 -30 561 622 90 97 0
diff --git a/src/vrppdtw/test/pdp-any-01.result b/src/vrppdtw/test/pdp-any-01.result
new file mode 100644
index 0000000..a50f605
--- /dev/null
+++ b/src/vrppdtw/test/pdp-any-01.result
@@ -0,0 +1,146 @@
+0|1|0|0
+1|1|71|293
+2|1|77|664
+3|1|79|758
+4|1|80|859
+5|1|49|1091
+6|1|47|1183
+7|1|0|1201
+8|2|0|0
+9|2|78|109
+10|2|104|109
+11|2|36|755
+12|2|105|755
+13|2|51|870
+14|2|101|870
+15|2|50|962
+16|2|52|1055
+17|2|0|1076
+18|3|0|0
+19|3|76|203
+20|3|73|568
+21|3|6|723
+22|3|2|915
+23|3|0|935
+24|4|0|0
+25|4|54|186
+26|4|56|475
+27|4|60|652
+28|4|59|752
+29|4|66|916
+30|4|69|1008
+31|4|0|1023
+32|5|0|0
+33|5|53|286
+34|5|58|561
+35|5|23|822
+36|5|103|822
+37|5|0|835
+38|6|0|0
+39|6|5|15
+40|6|7|260
+41|6|38|569
+42|6|34|841
+43|6|0|873
+44|7|0|0
+45|7|81|47
+46|7|25|259
+47|7|27|351
+48|7|70|516
+49|7|100|737
+50|7|99|833
+51|7|0|866
+52|8|0|0
+53|8|42|68
+54|8|63|261
+55|8|40|369
+56|8|74|477
+57|8|45|631
+58|8|48|723
+59|8|0|746
+60|9|0|0
+61|9|43|16
+62|9|41|256
+63|9|97|651
+64|9|106|651
+65|9|0|691
+66|10|0|0
+67|10|98|30
+68|10|96|185
+69|10|95|286
+70|10|94|379
+71|10|0|419
+72|11|0|0
+73|11|18|179
+74|11|92|458
+75|11|93|565
+76|11|12|742
+77|11|0|780
+78|12|0|0
+79|12|57|35
+80|12|55|185
+81|12|82|459
+82|12|84|554
+83|12|85|646
+84|12|89|827
+85|12|0|851
+86|13|0|0
+87|13|33|87
+88|13|35|373
+89|13|37|473
+90|13|30|586
+91|13|39|698
+92|13|21|1004
+93|13|0|1014
+94|14|0|0
+95|14|32|31
+96|14|31|290
+97|14|64|722
+98|14|102|722
+99|14|0|743
+100|15|0|0
+101|15|13|30
+102|15|17|189
+103|15|19|368
+104|15|15|474
+105|15|11|582
+106|15|9|675
+107|15|4|817
+108|15|1|1002
+109|15|0|1020
+110|16|0|0
+111|16|86|173
+112|16|29|448
+113|16|16|573
+114|16|14|665
+115|16|26|785
+116|16|91|926
+117|16|0|948
+118|17|0|0
+119|17|87|85
+120|17|83|355
+121|17|28|636
+122|17|22|902
+123|17|0|914
+124|18|0|0
+125|18|90|20
+126|18|65|166
+127|18|72|540
+128|18|88|735
+129|18|0|761
+130|19|0|0
+131|19|20|10
+132|19|24|155
+133|19|8|345
+134|19|10|447
+135|19|0|463
+136|20|0|0
+137|20|67|12
+138|20|3|155
+139|20|62|352
+140|20|44|460
+141|20|46|552
+142|20|61|662
+143|20|68|824
+144|20|75|1087
+145|20|0|0
diff --git a/src/vrppdtw/test/pdp-any-01.test.sql b/src/vrppdtw/test/pdp-any-01.test.sql
new file mode 100644
index 0000000..8f8dc19
--- /dev/null
+++ b/src/vrppdtw/test/pdp-any-01.test.sql
@@ -0,0 +1,3 @@
+select * from pgr_gsoc_vrppdtw(
+ 'select * from customer order by id'::text, 25,200
+ );
diff --git a/src/vrppdtw/test/test.conf b/src/vrppdtw/test/test.conf
new file mode 100644
index 0000000..c4d9a93
--- /dev/null
+++ b/src/vrppdtw/test/test.conf
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+
+%main::tests = (
+ 'any' => {
+ 'comment' => 'VRPPDTW: test for any versions.',
+ 'data' => ['pdp-any-00.data'],
+ 'tests' => [qw(pdp-any-01)]
+ },
+# 'vpg-vpgis' => {}, # for version specific tests
+# '8-1' => {}, # for pg 8.x and postgis 1.x
+# '9.2-2.1' => {}, # for pg 9.2 and postgis 2.1
+ );
+
+1;
+
+
+
diff --git a/tools/build-extension-update-files b/tools/build-extension-update-files
new file mode 100755
index 0000000..ffad204
--- /dev/null
+++ b/tools/build-extension-update-files
@@ -0,0 +1,276 @@
+#!/usr/bin/perl -w
+eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
+ if 0; #$running_under_some_shell
+
+# -------------------------------------------------------------
+# Usage: build-extension-update-files <version> [<pgrouting-src-dir>]
+#
+# Author: Stephen Woodbridge
+# Date: 2015-07-25
+# License: MIT-X
+# -------------------------------------------------------------
+# Description
+#
+# This script read a file from lib/pgrouting--<version>.sig
+# that should be the .sig for the current version of the extension.
+# lib/pgrouting--<version>.sig
+#
+# It then looks in tools/sigs/pgrouting--<old_version>.sig and
+# creates an update script for each version found. The update scripts
+# are written to:
+# build/lib/pgrouting--<old_version>--<current_version>.sql
+# and "sudo make install" will install them as part of the extension.
+#
+# Algorithm
+# 1. check if lib/pgrouting--<version>.sig exists and load it
+# 2. get a list of version signatures from tools/sigs/*
+# 3. foreach old version sig file
+# 4. generate an update file in lib/
+#
+# This is part of the automated pgRouting extension update
+# system that PostgreSQL require a collection of files that define
+# how to update an old version of pgRouting to the current version
+# using "ALTER EXTENSION pgrouting UPDATE TO <version>;"
+# The lib/pgrouting--<current_version>.sig and the update scripts
+# are automatically generated when when cmake is run. You don't
+# need to run this script manually.
+#
+# See also tools/mk-signature-file
+# ------------------------------------------------------------
+
+use strict;
+use Data::Dumper;
+use File::Find ();
+
+my $DEBUG = 0;
+
+use vars qw/*name *dir *prune/;
+*name = *File::Find::name;
+*dir = *File::Find::dir;
+*prune = *File::Find::prune;
+
+
+sub Usage {
+ die "Usage: build-extension-update-files <version> [<pgrouting-src-dir>]\n";
+}
+
+# get the commandline options
+# these are typically set by cmake
+my $version = shift @ARGV || Usage();
+my $src_dir = shift @ARGV || '.';
+
+# define the input file names and verify they exist.
+my $SIG = "lib/pgrouting--$version.sig";
+my $SQL = "lib/pgrouting--$version.sql";
+die "ERROR: Failed to find '$SIG'\n" unless -f $SIG;
+die "ERROR: Failed to find '$SQL'\n" unless -f $SQL;
+
+# collect a list of the old version .sig files
+my @old_files = ();
+
+# read and parse the current version .sig file
+my $new_hash = read_sig_file( $SIG );
+
+# assume we are in the build dir, but we might be up one level
+# if we are somewhere else we will fail to find the files
+my $sig_dir = 'tools/sigs/';
+$sig_dir = '../tools/sigs/' if -d '../tools/sigs';
+$sig_dir = $src_dir . '/tools/sigs/' if -d $src_dir . '/tools/sigs';
+
+# search for the old version .sig files in $sig_dir
+# and save the /path/file.sig into @old_files
+File::Find::find({wanted => \&wanted}, $sig_dir);
+
+# foreach old files
+for my $old_file ( sort @old_files ) {
+ # read and parse the .sig
+ my $old_hash = read_sig_file( $old_file );
+ # and generate and write the update script file
+ generate_upgrade_script( $new_hash, $old_hash);
+}
+
+exit 0;
+
+
+sub wanted {
+ /^.*\.sig\z/s &&
+ push @old_files, $name;
+}
+
+# read and parse the .sig file and store the results into hash
+sub read_sig_file {
+ my $file = shift;
+
+ my %hash = ();
+
+ open(IN, $file) || die "ERROR: Failed to open '$file'\n";
+
+ my $state = 0;
+ while (my $line = <IN>) {
+ if ($line =~ /^#VERSION pgrouting (\d+\.\d+\.\d+)\s*$/i) {
+ $hash{VERSION} = $1;
+ }
+ elsif ($line =~ /^#TYPES\s*/i) {
+ $state = 1;
+ next;
+ }
+ elsif ($line =~ /^#FUNCTIONS\s*/i) {
+ $state = 2;
+ next;
+ }
+ elsif ($line =~ /^#/) {
+ next;
+ }
+ $line =~ s/\s*$//;
+ if ($state == 1) {
+ push @{$hash{types}}, $line;
+ }
+ elsif ($state == 2) {
+ push @{$hash{funcs}}, $line;
+ }
+ }
+ close(IN);
+
+ return \%hash;
+}
+
+# analyze the old .sig hash as compared to the new .sig hash
+# and create an update script file for its version.
+sub generate_upgrade_script {
+ my ($new, $old) = @_;
+
+ my $err = 0;
+ my @types2remove = ();
+ my @commands = ();
+
+ # fetch the VERSION numbers
+ my $n_ver = $new->{VERSION};
+ my $o_ver = $old->{VERSION};
+
+ # analyze types
+
+ my $ntype = $new->{types};
+ my $otype = $old->{types};
+
+ # create a hash like <name> => <column_list> for new types
+ my %ntype_h = ();
+ for my $x (@{$ntype}) {
+ $x =~ m/(\w+)(\([^\)]+\))$/;
+ $ntype_h{lc($1)} = lc($2);
+ }
+
+ # check if old type exists with different column types
+ for my $x (@{$otype}) {
+ $x =~ m/(\w+)(\([^\)]+\))$/;
+ my $name = lc($1);
+ my $cols = lc($2);
+ if ($ntype_h{$name}) {
+ if ($ntype_h{$name} ne $cols) {
+ warn "WARNING: old type '$name$cols' changed to '$name$ntype_h{$name}' !\n";
+ $err = 1;
+ }
+ else {
+ push @types2remove, $name;
+ }
+ }
+ }
+
+
+ # analyze function sigs
+
+ my $nsig = $new->{funcs};
+ my $osig = $old->{funcs};
+
+ # create an unique hash map of the new signatures
+ # to quickly determine if an old signature exists or not
+ # in the new signatures.
+ my %fmap = map { $_ => 1 } @{$nsig};
+
+ for my $x (@{$osig}) {
+
+ # see if the old signature is in the new signature map
+ my $exists = $fmap{$x} || '0';
+ print "$exists\t$x\n" if $DEBUG;
+
+ # if the function does NOT exist in the current version
+ # then it needs to be removed from the extension
+ if (! $exists) {
+ print "ALTER EXTENSION pgrouting DROP FUNCTION $x;\n" if $DEBUG;
+ push @commands, "ALTER EXTENSION pgrouting DROP FUNCTION $x;\n";
+ }
+
+ # otherwise we only need to drop in case an argument name change
+ # so it will not fail on create or replace function
+ print "DROP FUNCTION IF EXISTS $x;\n" if $DEBUG;
+ push @commands, "DROP FUNCTION IF EXISTS $x;\n";
+ }
+
+ # UGH! someone change the definition of the TYPE or reused an existing
+ # TYPE name which is VERY BAD because other poeple might be dependent
+ # on the old TYPE so we can DROP TYPE <type> CASCADE; or we might drop
+ # a user's function. So juse DIE and maybe someone can resolve this
+ die "ERROR: pgrouting TYPE changed! Cannot continue!\n" if $err;
+
+ write_script($o_ver, $n_ver, \@types2remove, join('', @commands));
+}
+
+
+# we have all the data we need, so write the extension update script
+sub write_script {
+ my ($o_ver, $n_ver, $types, $cmds) = @_;
+
+ # open the extension update script or die if we can't
+ open(OUT, ">lib/pgrouting--$o_ver--$n_ver.sql")
+ || die "ERROR: failed to create 'lib/pgrouting-pgrouting--$o_ver--$n_ver.sql' : $!\n";
+
+ # write out the header and the commands to clean up the old extension
+ print OUT <<EOF;
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-- pgRouting extension upgrade from $o_ver to $n_ver
+-- generated by tools/build-extension-update-files
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-- remove functions no longer in the $n_ver extension
+$cmds
+
+-- now install the new extension
+
+EOF
+
+ # open the new extension.sql file
+ # and load it into an array
+ open(IN, $SQL) ||
+ die "ERROR: Failed to find '$SQL' : $!\n";
+ my @file = <IN>;
+ close(IN);
+
+ # comment out the TYPEs that the new extension defines
+ # that already existed in the old extension
+ # so they will not abort the script
+ remove_types( \@file, $types );
+
+ # append the new extension SQL to the update script
+ print OUT @file;
+ close(OUT);
+}
+
+
+sub remove_types {
+ my ($data, $types) = @_;
+
+ for my $type (@{$types}) {
+ my $state = 1;
+ for my $x (@{$data}) {
+ if ($state == 1) {
+ next unless $x =~ m/create\s+type\s+$type\b/i;
+ $x = "-- $x";
+ $state = 2
+ unless $x =~ m/create\s+type\s+$type\s+as\s*\([^\)]+\)/i;
+ }
+ elsif ($state == 2) {
+ $x = "-- $x";
+ last if $x =~ /\)\s*;/;
+ }
+ }
+ }
+}
+
diff --git a/tools/cpplint.py b/tools/cpplint.py
new file mode 100755
index 0000000..756dafb
--- /dev/null
+++ b/tools/cpplint.py
@@ -0,0 +1,6321 @@
+#Copyright (c) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Does google-lint on c++ files.
+
+The goal of this script is to identify places in the code that *may*
+be in non-compliance with google style. It does not attempt to fix
+up these problems -- the point is to educate. It does also not
+attempt to find all problems, or to ensure that everything it does
+find is legitimately a problem.
+
+In particular, we can get very confused by /* and // inside strings!
+We do a small hack, which is to ignore //'s with "'s after them on the
+same line, but it is far from perfect (in either direction).
+"""
+
+import codecs
+import copy
+import getopt
+import math # for log
+import os
+import re
+import sre_compile
+import string
+import sys
+import unicodedata
+
+
+_USAGE = """
+Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
+ [--counting=total|toplevel|detailed] [--root=subdir]
+ [--linelength=digits]
+ <file> [file] ...
+
+ The style guidelines this tries to follow are those in
+ http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
+
+ Every problem is given a confidence score from 1-5, with 5 meaning we are
+ certain of the problem, and 1 meaning it could be a legitimate construct.
+ This will miss some errors, and is not a substitute for a code review.
+
+ To suppress false-positive errors of a certain category, add a
+ 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
+ suppresses errors of all categories on that line.
+
+ The files passed in will be linted; at least one file must be provided.
+ Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the
+ extensions with the --extensions flag.
+
+ Flags:
+
+ output=vs7
+ By default, the output is formatted to ease emacs parsing. Visual Studio
+ compatible output (vs7) may also be used. Other formats are unsupported.
+
+ verbose=#
+ Specify a number 0-5 to restrict errors to certain verbosity levels.
+
+ filter=-x,+y,...
+ Specify a comma-separated list of category-filters to apply: only
+ error messages whose category names pass the filters will be printed.
+ (Category names are printed with the message and look like
+ "[whitespace/indent]".) Filters are evaluated left to right.
+ "-FOO" and "FOO" means "do not print categories that start with FOO".
+ "+FOO" means "do print categories that start with FOO".
+
+ Examples: --filter=-whitespace,+whitespace/braces
+ --filter=whitespace,runtime/printf,+runtime/printf_format
+ --filter=-,+build/include_what_you_use
+
+ To see a list of all the categories used in cpplint, pass no arg:
+ --filter=
+
+ counting=total|toplevel|detailed
+ The total number of errors found is always printed. If
+ 'toplevel' is provided, then the count of errors in each of
+ the top-level categories like 'build' and 'whitespace' will
+ also be printed. If 'detailed' is provided, then a count
+ is provided for each category like 'build/class'.
+
+ root=subdir
+ The root directory used for deriving header guard CPP variable.
+ By default, the header guard CPP variable is calculated as the relative
+ path to the directory that contains .git, .hg, or .svn. When this flag
+ is specified, the relative path is calculated from the specified
+ directory. If the specified directory does not exist, this flag is
+ ignored.
+
+ Examples:
+ Assuming that src/.git exists, the header guard CPP variables for
+ src/chrome/browser/ui/browser.h are:
+
+ No flag => CHROME_BROWSER_UI_BROWSER_H_
+ --root=chrome => BROWSER_UI_BROWSER_H_
+ --root=chrome/browser => UI_BROWSER_H_
+
+ linelength=digits
+ This is the allowed line length for the project. The default value is
+ 80 characters.
+
+ Examples:
+ --linelength=120
+
+ extensions=extension,extension,...
+ The allowed file extensions that cpplint will check
+
+ Examples:
+ --extensions=hpp,cpp
+
+ cpplint.py supports per-directory configurations specified in CPPLINT.cfg
+ files. CPPLINT.cfg file can contain a number of key=value pairs.
+ Currently the following options are supported:
+
+ set noparent
+ filter=+filter1,-filter2,...
+ exclude_files=regex
+ linelength=80
+
+ "set noparent" option prevents cpplint from traversing directory tree
+ upwards looking for more .cfg files in parent directories. This option
+ is usually placed in the top-level project directory.
+
+ The "filter" option is similar in function to --filter flag. It specifies
+ message filters in addition to the |_DEFAULT_FILTERS| and those specified
+ through --filter command-line flag.
+
+ "exclude_files" allows to specify a regular expression to be matched against
+ a file name. If the expression matches, the file is skipped and not run
+ through liner.
+
+ "linelength" allows to specify the allowed line length for the project.
+
+ CPPLINT.cfg has an effect on files in the same directory and all
+ sub-directories, unless overridden by a nested configuration file.
+
+ Example file:
+ filter=-build/include_order,+build/include_alpha
+ exclude_files=.*\.cc
+
+ The above example disables build/include_order warning and enables
+ build/include_alpha as well as excludes all .cc from being
+ processed by linter, in the current directory (where the .cfg
+ file is located) and all sub-directories.
+"""
+
+# We categorize each error message we print. Here are the categories.
+# We want an explicit list so we can list them all in cpplint --filter=.
+# If you add a new error message with a new category, add it to the list
+# here! cpplint_unittest.py should tell you if you forget to do this.
+_ERROR_CATEGORIES = [
+ 'build/class',
+ 'build/c++11',
+ 'build/deprecated',
+ 'build/endif_comment',
+ 'build/explicit_make_pair',
+ 'build/forward_decl',
+ 'build/header_guard',
+ 'build/include',
+ 'build/include_alpha',
+ 'build/include_order',
+ 'build/include_what_you_use',
+ 'build/namespaces',
+ 'build/printf_format',
+ 'build/storage_class',
+ 'legal/copyright',
+ 'readability/alt_tokens',
+ 'readability/braces',
+ 'readability/casting',
+ 'readability/check',
+ 'readability/constructors',
+ 'readability/fn_size',
+ 'readability/function',
+ 'readability/inheritance',
+ 'readability/multiline_comment',
+ 'readability/multiline_string',
+ 'readability/namespace',
+ 'readability/nolint',
+ 'readability/nul',
+ 'readability/strings',
+ 'readability/todo',
+ 'readability/utf8',
+ 'runtime/arrays',
+ 'runtime/casting',
+ 'runtime/explicit',
+ 'runtime/int',
+ 'runtime/init',
+ 'runtime/invalid_increment',
+ 'runtime/member_string_references',
+ 'runtime/memset',
+ 'runtime/indentation_namespace',
+ 'runtime/operator',
+ 'runtime/printf',
+ 'runtime/printf_format',
+ 'runtime/references',
+ 'runtime/string',
+ 'runtime/threadsafe_fn',
+ 'runtime/vlog',
+ 'whitespace/blank_line',
+ 'whitespace/braces',
+ 'whitespace/comma',
+ 'whitespace/comments',
+ 'whitespace/empty_conditional_body',
+ 'whitespace/empty_loop_body',
+ 'whitespace/end_of_line',
+ 'whitespace/ending_newline',
+ 'whitespace/forcolon',
+ 'whitespace/indent',
+ 'whitespace/line_length',
+ 'whitespace/newline',
+ 'whitespace/operators',
+ 'whitespace/parens',
+ 'whitespace/semicolon',
+ 'whitespace/tab',
+ 'whitespace/todo',
+ ]
+
+# These error categories are no longer enforced by cpplint, but for backwards-
+# compatibility they may still appear in NOLINT comments.
+_LEGACY_ERROR_CATEGORIES = [
+ 'readability/streams',
+ ]
+
+# The default state of the category filter. This is overridden by the --filter=
+# flag. By default all errors are on, so only add here categories that should be
+# off by default (i.e., categories that must be enabled by the --filter= flags).
+# All entries here should start with a '-' or '+', as in the --filter= flag.
+_DEFAULT_FILTERS = ['-build/include_alpha']
+
+# We used to check for high-bit characters, but after much discussion we
+# decided those were OK, as long as they were in UTF-8 and didn't represent
+# hard-coded international strings, which belong in a separate i18n file.
+
+# C++ headers
+_CPP_HEADERS = frozenset([
+ # Legacy
+ 'algobase.h',
+ 'algo.h',
+ 'alloc.h',
+ 'builtinbuf.h',
+ 'bvector.h',
+ 'complex.h',
+ 'defalloc.h',
+ 'deque.h',
+ 'editbuf.h',
+ 'fstream.h',
+ 'function.h',
+ 'hash_map',
+ 'hash_map.h',
+ 'hash_set',
+ 'hash_set.h',
+ 'hashtable.h',
+ 'heap.h',
+ 'indstream.h',
+ 'iomanip.h',
+ 'iostream.h',
+ 'istream.h',
+ 'iterator.h',
+ 'list.h',
+ 'map.h',
+ 'multimap.h',
+ 'multiset.h',
+ 'ostream.h',
+ 'pair.h',
+ 'parsestream.h',
+ 'pfstream.h',
+ 'procbuf.h',
+ 'pthread_alloc',
+ 'pthread_alloc.h',
+ 'rope',
+ 'rope.h',
+ 'ropeimpl.h',
+ 'set.h',
+ 'slist',
+ 'slist.h',
+ 'stack.h',
+ 'stdiostream.h',
+ 'stl_alloc.h',
+ 'stl_relops.h',
+ 'streambuf.h',
+ 'stream.h',
+ 'strfile.h',
+ 'strstream.h',
+ 'tempbuf.h',
+ 'tree.h',
+ 'type_traits.h',
+ 'vector.h',
+ # 17.6.1.2 C++ library headers
+ 'algorithm',
+ 'array',
+ 'atomic',
+ 'bitset',
+ 'chrono',
+ 'codecvt',
+ 'complex',
+ 'condition_variable',
+ 'deque',
+ 'exception',
+ 'forward_list',
+ 'fstream',
+ 'functional',
+ 'future',
+ 'initializer_list',
+ 'iomanip',
+ 'ios',
+ 'iosfwd',
+ 'iostream',
+ 'istream',
+ 'iterator',
+ 'limits',
+ 'list',
+ 'locale',
+ 'map',
+ 'memory',
+ 'mutex',
+ 'new',
+ 'numeric',
+ 'ostream',
+ 'queue',
+ 'random',
+ 'ratio',
+ 'regex',
+ 'set',
+ 'sstream',
+ 'stack',
+ 'stdexcept',
+ 'streambuf',
+ 'string',
+ 'strstream',
+ 'system_error',
+ 'thread',
+ 'tuple',
+ 'typeindex',
+ 'typeinfo',
+ 'type_traits',
+ 'unordered_map',
+ 'unordered_set',
+ 'utility',
+ 'valarray',
+ 'vector',
+ # 17.6.1.2 C++ headers for C library facilities
+ 'cassert',
+ 'ccomplex',
+ 'cctype',
+ 'cerrno',
+ 'cfenv',
+ 'cfloat',
+ 'cinttypes',
+ 'ciso646',
+ 'climits',
+ 'clocale',
+ 'cmath',
+ 'csetjmp',
+ 'csignal',
+ 'cstdalign',
+ 'cstdarg',
+ 'cstdbool',
+ 'cstddef',
+ 'cstdint',
+ 'cstdio',
+ 'cstdlib',
+ 'cstring',
+ 'ctgmath',
+ 'ctime',
+ 'cuchar',
+ 'cwchar',
+ 'cwctype',
+ ])
+
+
+# These headers are excluded from [build/include] and [build/include_order]
+# checks:
+# - Anything not following google file name conventions (containing an
+# uppercase character, such as Python.h or nsStringAPI.h, for example).
+# - Lua headers.
+_THIRD_PARTY_HEADERS_PATTERN = re.compile(
+ r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
+
+
+# Assertion macros. These are defined in base/logging.h and
+# testing/base/gunit.h. Note that the _M versions need to come first
+# for substring matching to work.
+_CHECK_MACROS = [
+ 'DCHECK', 'CHECK',
+ 'EXPECT_TRUE_M', 'EXPECT_TRUE',
+ 'ASSERT_TRUE_M', 'ASSERT_TRUE',
+ 'EXPECT_FALSE_M', 'EXPECT_FALSE',
+ 'ASSERT_FALSE_M', 'ASSERT_FALSE',
+ ]
+
+# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
+_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
+
+for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
+ ('>=', 'GE'), ('>', 'GT'),
+ ('<=', 'LE'), ('<', 'LT')]:
+ _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
+ _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
+ _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
+ _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
+ _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
+ _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
+
+for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
+ ('>=', 'LT'), ('>', 'LE'),
+ ('<=', 'GT'), ('<', 'GE')]:
+ _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
+ _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
+ _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
+ _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
+
+# Alternative tokens and their replacements. For full list, see section 2.5
+# Alternative tokens [lex.digraph] in the C++ standard.
+#
+# Digraphs (such as '%:') are not included here since it's a mess to
+# match those on a word boundary.
+_ALT_TOKEN_REPLACEMENT = {
+ 'and': '&&',
+ 'bitor': '|',
+ 'or': '||',
+ 'xor': '^',
+ 'compl': '~',
+ 'bitand': '&',
+ 'and_eq': '&=',
+ 'or_eq': '|=',
+ 'xor_eq': '^=',
+ 'not': '!',
+ 'not_eq': '!='
+ }
+
+# Compile regular expression that matches all the above keywords. The "[ =()]"
+# bit is meant to avoid matching these keywords outside of boolean expressions.
+#
+# False positives include C-style multi-line comments and multi-line strings
+# but those have always been troublesome for cpplint.
+_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
+ r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
+
+
+# These constants define types of headers for use with
+# _IncludeState.CheckNextIncludeOrder().
+_C_SYS_HEADER = 1
+_CPP_SYS_HEADER = 2
+_LIKELY_MY_HEADER = 3
+_POSSIBLE_MY_HEADER = 4
+_OTHER_HEADER = 5
+
+# These constants define the current inline assembly state
+_NO_ASM = 0 # Outside of inline assembly block
+_INSIDE_ASM = 1 # Inside inline assembly block
+_END_ASM = 2 # Last line of inline assembly block
+_BLOCK_ASM = 3 # The whole block is an inline assembly block
+
+# Match start of assembly blocks
+_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
+ r'(?:\s+(volatile|__volatile__))?'
+ r'\s*[{(]')
+
+
+_regexp_compile_cache = {}
+
+# {str, set(int)}: a map from error categories to sets of linenumbers
+# on which those errors are expected and should be suppressed.
+_error_suppressions = {}
+
+# The root directory used for deriving header guard CPP variable.
+# This is set by --root flag.
+_root = None
+
+# The allowed line length of files.
+# This is set by --linelength flag.
+_line_length = 80
+
+# The allowed extensions for file names
+# This is set by --extensions flag.
+_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh', 'c', 'hpp'])
+
+def ParseNolintSuppressions(filename, raw_line, linenum, error):
+ """Updates the global list of error-suppressions.
+
+ Parses any NOLINT comments on the current line, updating the global
+ error_suppressions store. Reports an error if the NOLINT comment
+ was malformed.
+
+ Args:
+ filename: str, the name of the input file.
+ raw_line: str, the line of input text, with comments.
+ linenum: int, the number of the current line.
+ error: function, an error handler.
+ """
+ matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
+ if matched:
+ if matched.group(1):
+ suppressed_line = linenum + 1
+ else:
+ suppressed_line = linenum
+ category = matched.group(2)
+ if category in (None, '(*)'): # => "suppress all"
+ _error_suppressions.setdefault(None, set()).add(suppressed_line)
+ else:
+ if category.startswith('(') and category.endswith(')'):
+ category = category[1:-1]
+ if category in _ERROR_CATEGORIES:
+ _error_suppressions.setdefault(category, set()).add(suppressed_line)
+ elif category not in _LEGACY_ERROR_CATEGORIES:
+ error(filename, linenum, 'readability/nolint', 5,
+ 'Unknown NOLINT error category: %s' % category)
+
+
+def ResetNolintSuppressions():
+ """Resets the set of NOLINT suppressions to empty."""
+ _error_suppressions.clear()
+
+
+def IsErrorSuppressedByNolint(category, linenum):
+ """Returns true if the specified error category is suppressed on this line.
+
+ Consults the global error_suppressions map populated by
+ ParseNolintSuppressions/ResetNolintSuppressions.
+
+ Args:
+ category: str, the category of the error.
+ linenum: int, the current line number.
+ Returns:
+ bool, True iff the error should be suppressed due to a NOLINT comment.
+ """
+ return (linenum in _error_suppressions.get(category, set()) or
+ linenum in _error_suppressions.get(None, set()))
+
+
+def Match(pattern, s):
+ """Matches the string with the pattern, caching the compiled regexp."""
+ # The regexp compilation caching is inlined in both Match and Search for
+ # performance reasons; factoring it out into a separate function turns out
+ # to be noticeably expensive.
+ if pattern not in _regexp_compile_cache:
+ _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+ return _regexp_compile_cache[pattern].match(s)
+
+
+def ReplaceAll(pattern, rep, s):
+ """Replaces instances of pattern in a string with a replacement.
+
+ The compiled regex is kept in a cache shared by Match and Search.
+
+ Args:
+ pattern: regex pattern
+ rep: replacement text
+ s: search string
+
+ Returns:
+ string with replacements made (or original string if no replacements)
+ """
+ if pattern not in _regexp_compile_cache:
+ _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+ return _regexp_compile_cache[pattern].sub(rep, s)
+
+
+def Search(pattern, s):
+ """Searches the string for the pattern, caching the compiled regexp."""
+ if pattern not in _regexp_compile_cache:
+ _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+ return _regexp_compile_cache[pattern].search(s)
+
+
+class _IncludeState(object):
+ """Tracks line numbers for includes, and the order in which includes appear.
+
+ include_list contains list of lists of (header, line number) pairs.
+ It's a lists of lists rather than just one flat list to make it
+ easier to update across preprocessor boundaries.
+
+ Call CheckNextIncludeOrder() once for each header in the file, passing
+ in the type constants defined above. Calls in an illegal order will
+ raise an _IncludeError with an appropriate error message.
+
+ """
+ # self._section will move monotonically through this set. If it ever
+ # needs to move backwards, CheckNextIncludeOrder will raise an error.
+ _INITIAL_SECTION = 0
+ _MY_H_SECTION = 1
+ _C_SECTION = 2
+ _CPP_SECTION = 3
+ _OTHER_H_SECTION = 4
+
+ _TYPE_NAMES = {
+ _C_SYS_HEADER: 'C system header',
+ _CPP_SYS_HEADER: 'C++ system header',
+ _LIKELY_MY_HEADER: 'header this file implements',
+ _POSSIBLE_MY_HEADER: 'header this file may implement',
+ _OTHER_HEADER: 'other header',
+ }
+ _SECTION_NAMES = {
+ _INITIAL_SECTION: "... nothing. (This can't be an error.)",
+ _MY_H_SECTION: 'a header this file implements',
+ _C_SECTION: 'C system header',
+ _CPP_SECTION: 'C++ system header',
+ _OTHER_H_SECTION: 'other header',
+ }
+
+ def __init__(self):
+ self.include_list = [[]]
+ self.ResetSection('')
+
+ def FindHeader(self, header):
+ """Check if a header has already been included.
+
+ Args:
+ header: header to check.
+ Returns:
+ Line number of previous occurrence, or -1 if the header has not
+ been seen before.
+ """
+ for section_list in self.include_list:
+ for f in section_list:
+ if f[0] == header:
+ return f[1]
+ return -1
+
+ def ResetSection(self, directive):
+ """Reset section checking for preprocessor directive.
+
+ Args:
+ directive: preprocessor directive (e.g. "if", "else").
+ """
+ # The name of the current section.
+ self._section = self._INITIAL_SECTION
+ # The path of last found header.
+ self._last_header = ''
+
+ # Update list of includes. Note that we never pop from the
+ # include list.
+ if directive in ('if', 'ifdef', 'ifndef'):
+ self.include_list.append([])
+ elif directive in ('else', 'elif'):
+ self.include_list[-1] = []
+
+ def SetLastHeader(self, header_path):
+ self._last_header = header_path
+
+ def CanonicalizeAlphabeticalOrder(self, header_path):
+ """Returns a path canonicalized for alphabetical comparison.
+
+ - replaces "-" with "_" so they both cmp the same.
+ - removes '-inl' since we don't require them to be after the main header.
+ - lowercase everything, just in case.
+
+ Args:
+ header_path: Path to be canonicalized.
+
+ Returns:
+ Canonicalized path.
+ """
+ return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
+
+ def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
+ """Check if a header is in alphabetical order with the previous header.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ header_path: Canonicalized header to be checked.
+
+ Returns:
+ Returns true if the header is in alphabetical order.
+ """
+ # If previous section is different from current section, _last_header will
+ # be reset to empty string, so it's always less than current header.
+ #
+ # If previous line was a blank line, assume that the headers are
+ # intentionally sorted the way they are.
+ if (self._last_header > header_path and
+ Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
+ return False
+ return True
+
+ def CheckNextIncludeOrder(self, header_type):
+ """Returns a non-empty error message if the next header is out of order.
+
+ This function also updates the internal state to be ready to check
+ the next include.
+
+ Args:
+ header_type: One of the _XXX_HEADER constants defined above.
+
+ Returns:
+ The empty string if the header is in the right order, or an
+ error message describing what's wrong.
+
+ """
+ error_message = ('Found %s after %s' %
+ (self._TYPE_NAMES[header_type],
+ self._SECTION_NAMES[self._section]))
+
+ last_section = self._section
+
+ if header_type == _C_SYS_HEADER:
+ if self._section <= self._C_SECTION:
+ self._section = self._C_SECTION
+ else:
+ self._last_header = ''
+ return error_message
+ elif header_type == _CPP_SYS_HEADER:
+ if self._section <= self._CPP_SECTION:
+ self._section = self._CPP_SECTION
+ else:
+ self._last_header = ''
+ return error_message
+ elif header_type == _LIKELY_MY_HEADER:
+ if self._section <= self._MY_H_SECTION:
+ self._section = self._MY_H_SECTION
+ else:
+ self._section = self._OTHER_H_SECTION
+ elif header_type == _POSSIBLE_MY_HEADER:
+ if self._section <= self._MY_H_SECTION:
+ self._section = self._MY_H_SECTION
+ else:
+ # This will always be the fallback because we're not sure
+ # enough that the header is associated with this file.
+ self._section = self._OTHER_H_SECTION
+ else:
+ assert header_type == _OTHER_HEADER
+ self._section = self._OTHER_H_SECTION
+
+ if last_section != self._section:
+ self._last_header = ''
+
+ return ''
+
+
+class _CppLintState(object):
+ """Maintains module-wide state.."""
+
+ def __init__(self):
+ self.verbose_level = 1 # global setting.
+ self.error_count = 0 # global count of reported errors
+ # filters to apply when emitting error messages
+ self.filters = _DEFAULT_FILTERS[:]
+ # backup of filter list. Used to restore the state after each file.
+ self._filters_backup = self.filters[:]
+ self.counting = 'total' # In what way are we counting errors?
+ self.errors_by_category = {} # string to int dict storing error counts
+
+ # output format:
+ # "emacs" - format that emacs can parse (default)
+ # "vs7" - format that Microsoft Visual Studio 7 can parse
+ self.output_format = 'emacs'
+
+ def SetOutputFormat(self, output_format):
+ """Sets the output format for errors."""
+ self.output_format = output_format
+
+ def SetVerboseLevel(self, level):
+ """Sets the module's verbosity, and returns the previous setting."""
+ last_verbose_level = self.verbose_level
+ self.verbose_level = level
+ return last_verbose_level
+
+ def SetCountingStyle(self, counting_style):
+ """Sets the module's counting options."""
+ self.counting = counting_style
+
+ def SetFilters(self, filters):
+ """Sets the error-message filters.
+
+ These filters are applied when deciding whether to emit a given
+ error message.
+
+ Args:
+ filters: A string of comma-separated filters (eg "+whitespace/indent").
+ Each filter should start with + or -; else we die.
+
+ Raises:
+ ValueError: The comma-separated filters did not all start with '+' or '-'.
+ E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
+ """
+ # Default filters always have less priority than the flag ones.
+ self.filters = _DEFAULT_FILTERS[:]
+ self.AddFilters(filters)
+
+ def AddFilters(self, filters):
+ """ Adds more filters to the existing list of error-message filters. """
+ for filt in filters.split(','):
+ clean_filt = filt.strip()
+ if clean_filt:
+ self.filters.append(clean_filt)
+ for filt in self.filters:
+ if not (filt.startswith('+') or filt.startswith('-')):
+ raise ValueError('Every filter in --filters must start with + or -'
+ ' (%s does not)' % filt)
+
+ def BackupFilters(self):
+ """ Saves the current filter list to backup storage."""
+ self._filters_backup = self.filters[:]
+
+ def RestoreFilters(self):
+ """ Restores filters previously backed up."""
+ self.filters = self._filters_backup[:]
+
+ def ResetErrorCounts(self):
+ """Sets the module's error statistic back to zero."""
+ self.error_count = 0
+ self.errors_by_category = {}
+
+ def IncrementErrorCount(self, category):
+ """Bumps the module's error statistic."""
+ self.error_count += 1
+ if self.counting in ('toplevel', 'detailed'):
+ if self.counting != 'detailed':
+ category = category.split('/')[0]
+ if category not in self.errors_by_category:
+ self.errors_by_category[category] = 0
+ self.errors_by_category[category] += 1
+
+ def PrintErrorCounts(self):
+ """Print a summary of errors by category, and the total."""
+ for category, count in self.errors_by_category.iteritems():
+ sys.stderr.write('Category \'%s\' errors found: %d\n' %
+ (category, count))
+ sys.stderr.write('Total errors found: %d\n' % self.error_count)
+
+_cpplint_state = _CppLintState()
+
+
+def _OutputFormat():
+ """Gets the module's output format."""
+ return _cpplint_state.output_format
+
+
+def _SetOutputFormat(output_format):
+ """Sets the module's output format."""
+ _cpplint_state.SetOutputFormat(output_format)
+
+
+def _VerboseLevel():
+ """Returns the module's verbosity setting."""
+ return _cpplint_state.verbose_level
+
+
+def _SetVerboseLevel(level):
+ """Sets the module's verbosity, and returns the previous setting."""
+ return _cpplint_state.SetVerboseLevel(level)
+
+
+def _SetCountingStyle(level):
+ """Sets the module's counting options."""
+ _cpplint_state.SetCountingStyle(level)
+
+
+def _Filters():
+ """Returns the module's list of output filters, as a list."""
+ return _cpplint_state.filters
+
+
+def _SetFilters(filters):
+ """Sets the module's error-message filters.
+
+ These filters are applied when deciding whether to emit a given
+ error message.
+
+ Args:
+ filters: A string of comma-separated filters (eg "whitespace/indent").
+ Each filter should start with + or -; else we die.
+ """
+ _cpplint_state.SetFilters(filters)
+
+def _AddFilters(filters):
+ """Adds more filter overrides.
+
+ Unlike _SetFilters, this function does not reset the current list of filters
+ available.
+
+ Args:
+ filters: A string of comma-separated filters (eg "whitespace/indent").
+ Each filter should start with + or -; else we die.
+ """
+ _cpplint_state.AddFilters(filters)
+
+def _BackupFilters():
+ """ Saves the current filter list to backup storage."""
+ _cpplint_state.BackupFilters()
+
+def _RestoreFilters():
+ """ Restores filters previously backed up."""
+ _cpplint_state.RestoreFilters()
+
+class _FunctionState(object):
+ """Tracks current function name and the number of lines in its body."""
+
+ _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
+ _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
+
+ def __init__(self):
+ self.in_a_function = False
+ self.lines_in_function = 0
+ self.current_function = ''
+
+ def Begin(self, function_name):
+ """Start analyzing function body.
+
+ Args:
+ function_name: The name of the function being tracked.
+ """
+ self.in_a_function = True
+ self.lines_in_function = 0
+ self.current_function = function_name
+
+ def Count(self):
+ """Count line in current function body."""
+ if self.in_a_function:
+ self.lines_in_function += 1
+
+ def Check(self, error, filename, linenum):
+ """Report if too many lines in function body.
+
+ Args:
+ error: The function to call with any errors found.
+ filename: The name of the current file.
+ linenum: The number of the line to check.
+ """
+ if Match(r'T(EST|est)', self.current_function):
+ base_trigger = self._TEST_TRIGGER
+ else:
+ base_trigger = self._NORMAL_TRIGGER
+ trigger = base_trigger * 2**_VerboseLevel()
+
+ if self.lines_in_function > trigger:
+ error_level = int(math.log(self.lines_in_function / base_trigger, 2))
+ # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
+ if error_level > 5:
+ error_level = 5
+ error(filename, linenum, 'readability/fn_size', error_level,
+ 'Small and focused functions are preferred:'
+ ' %s has %d non-comment lines'
+ ' (error triggered by exceeding %d lines).' % (
+ self.current_function, self.lines_in_function, trigger))
+
+ def End(self):
+ """Stop analyzing function body."""
+ self.in_a_function = False
+
+
+class _IncludeError(Exception):
+ """Indicates a problem with the include order in a file."""
+ pass
+
+
+class FileInfo(object):
+ """Provides utility functions for filenames.
+
+ FileInfo provides easy access to the components of a file's path
+ relative to the project root.
+ """
+
+ def __init__(self, filename):
+ self._filename = filename
+
+ def FullName(self):
+ """Make Windows paths like Unix."""
+ return os.path.abspath(self._filename).replace('\\', '/')
+
+ def RepositoryName(self):
+ """FullName after removing the local path to the repository.
+
+ If we have a real absolute path name here we can try to do something smart:
+ detecting the root of the checkout and truncating /path/to/checkout from
+ the name so that we get header guards that don't include things like
+ "C:\Documents and Settings\..." or "/home/username/..." in them and thus
+ people on different computers who have checked the source out to different
+ locations won't see bogus errors.
+ """
+ fullname = self.FullName()
+
+ if os.path.exists(fullname):
+ project_dir = os.path.dirname(fullname)
+
+ if os.path.exists(os.path.join(project_dir, ".svn")):
+ # If there's a .svn file in the current directory, we recursively look
+ # up the directory tree for the top of the SVN checkout
+ root_dir = project_dir
+ one_up_dir = os.path.dirname(root_dir)
+ while os.path.exists(os.path.join(one_up_dir, ".svn")):
+ root_dir = os.path.dirname(root_dir)
+ one_up_dir = os.path.dirname(one_up_dir)
+
+ prefix = os.path.commonprefix([root_dir, project_dir])
+ return fullname[len(prefix) + 1:]
+
+ # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
+ # searching up from the current path.
+ root_dir = os.path.dirname(fullname)
+ while (root_dir != os.path.dirname(root_dir) and
+ not os.path.exists(os.path.join(root_dir, ".git")) and
+ not os.path.exists(os.path.join(root_dir, ".hg")) and
+ not os.path.exists(os.path.join(root_dir, ".svn"))):
+ root_dir = os.path.dirname(root_dir)
+
+ if (os.path.exists(os.path.join(root_dir, ".git")) or
+ os.path.exists(os.path.join(root_dir, ".hg")) or
+ os.path.exists(os.path.join(root_dir, ".svn"))):
+ prefix = os.path.commonprefix([root_dir, project_dir])
+ return fullname[len(prefix) + 1:]
+
+ # Don't know what to do; header guard warnings may be wrong...
+ return fullname
+
+ def Split(self):
+ """Splits the file into the directory, basename, and extension.
+
+ For 'chrome/browser/browser.cc', Split() would
+ return ('chrome/browser', 'browser', '.cc')
+
+ Returns:
+ A tuple of (directory, basename, extension).
+ """
+
+ googlename = self.RepositoryName()
+ project, rest = os.path.split(googlename)
+ return (project,) + os.path.splitext(rest)
+
+ def BaseName(self):
+ """File base name - text after the final slash, before the final period."""
+ return self.Split()[1]
+
+ def Extension(self):
+ """File extension - text following the final period."""
+ return self.Split()[2]
+
+ def NoExtension(self):
+ """File has no source file extension."""
+ return '/'.join(self.Split()[0:2])
+
+ def IsSource(self):
+ """File has a source file extension."""
+ return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
+
+
+def _ShouldPrintError(category, confidence, linenum):
+ """If confidence >= verbose, category passes filter and is not suppressed."""
+
+ # There are three ways we might decide not to print an error message:
+ # a "NOLINT(category)" comment appears in the source,
+ # the verbosity level isn't high enough, or the filters filter it out.
+ if IsErrorSuppressedByNolint(category, linenum):
+ return False
+
+ if confidence < _cpplint_state.verbose_level:
+ return False
+
+ is_filtered = False
+ for one_filter in _Filters():
+ if one_filter.startswith('-'):
+ if category.startswith(one_filter[1:]):
+ is_filtered = True
+ elif one_filter.startswith('+'):
+ if category.startswith(one_filter[1:]):
+ is_filtered = False
+ else:
+ assert False # should have been checked for in SetFilter.
+ if is_filtered:
+ return False
+
+ return True
+
+
+def Error(filename, linenum, category, confidence, message):
+ """Logs the fact we've found a lint error.
+
+ We log where the error was found, and also our confidence in the error,
+ that is, how certain we are this is a legitimate style regression, and
+ not a misidentification or a use that's sometimes justified.
+
+ False positives can be suppressed by the use of
+ "cpplint(category)" comments on the offending line. These are
+ parsed into _error_suppressions.
+
+ Args:
+ filename: The name of the file containing the error.
+ linenum: The number of the line containing the error.
+ category: A string used to describe the "category" this bug
+ falls under: "whitespace", say, or "runtime". Categories
+ may have a hierarchy separated by slashes: "whitespace/indent".
+ confidence: A number from 1-5 representing a confidence score for
+ the error, with 5 meaning that we are certain of the problem,
+ and 1 meaning that it could be a legitimate construct.
+ message: The error message.
+ """
+ if _ShouldPrintError(category, confidence, linenum):
+ _cpplint_state.IncrementErrorCount(category)
+ if _cpplint_state.output_format == 'vs7':
+ sys.stderr.write('%s(%s): %s [%s] [%d]\n' % (
+ filename, linenum, message, category, confidence))
+ elif _cpplint_state.output_format == 'eclipse':
+ sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % (
+ filename, linenum, message, category, confidence))
+ else:
+ sys.stderr.write('%s:%s: %s [%s] [%d]\n' % (
+ filename, linenum, message, category, confidence))
+
+
+# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
+_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
+ r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
+# Match a single C style comment on the same line.
+_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
+# Matches multi-line C style comments.
+# This RE is a little bit more complicated than one might expect, because we
+# have to take care of space removals tools so we can handle comments inside
+# statements better.
+# The current rule is: We only clear spaces from both sides when we're at the
+# end of the line. Otherwise, we try to remove spaces from the right side,
+# if this doesn't work we try on left side but only if there's a non-character
+# on the right.
+_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
+ r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
+ _RE_PATTERN_C_COMMENTS + r'\s+|' +
+ r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
+ _RE_PATTERN_C_COMMENTS + r')')
+
+
+def IsCppString(line):
+ """Does line terminate so, that the next symbol is in string constant.
+
+ This function does not consider single-line nor multi-line comments.
+
+ Args:
+ line: is a partial line of code starting from the 0..n.
+
+ Returns:
+ True, if next character appended to 'line' is inside a
+ string constant.
+ """
+
+ line = line.replace(r'\\', 'XX') # after this, \\" does not match to \"
+ return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
+
+
+def CleanseRawStrings(raw_lines):
+ """Removes C++11 raw strings from lines.
+
+ Before:
+ static const char kData[] = R"(
+ multi-line string
+ )";
+
+ After:
+ static const char kData[] = ""
+ (replaced by blank line)
+ "";
+
+ Args:
+ raw_lines: list of raw lines.
+
+ Returns:
+ list of lines with C++11 raw strings replaced by empty strings.
+ """
+
+ delimiter = None
+ lines_without_raw_strings = []
+ for line in raw_lines:
+ if delimiter:
+ # Inside a raw string, look for the end
+ end = line.find(delimiter)
+ if end >= 0:
+ # Found the end of the string, match leading space for this
+ # line and resume copying the original lines, and also insert
+ # a "" on the last line.
+ leading_space = Match(r'^(\s*)\S', line)
+ line = leading_space.group(1) + '""' + line[end + len(delimiter):]
+ delimiter = None
+ else:
+ # Haven't found the end yet, append a blank line.
+ line = '""'
+
+ # Look for beginning of a raw string, and replace them with
+ # empty strings. This is done in a loop to handle multiple raw
+ # strings on the same line.
+ while delimiter is None:
+ # Look for beginning of a raw string.
+ # See 2.14.15 [lex.string] for syntax.
+ matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
+ if matched:
+ delimiter = ')' + matched.group(2) + '"'
+
+ end = matched.group(3).find(delimiter)
+ if end >= 0:
+ # Raw string ended on same line
+ line = (matched.group(1) + '""' +
+ matched.group(3)[end + len(delimiter):])
+ delimiter = None
+ else:
+ # Start of a multi-line raw string
+ line = matched.group(1) + '""'
+ else:
+ break
+
+ lines_without_raw_strings.append(line)
+
+ # TODO(unknown): if delimiter is not None here, we might want to
+ # emit a warning for unterminated string.
+ return lines_without_raw_strings
+
+
+def FindNextMultiLineCommentStart(lines, lineix):
+ """Find the beginning marker for a multiline comment."""
+ while lineix < len(lines):
+ if lines[lineix].strip().startswith('/*'):
+ # Only return this marker if the comment goes beyond this line
+ if lines[lineix].strip().find('*/', 2) < 0:
+ return lineix
+ lineix += 1
+ return len(lines)
+
+
+def FindNextMultiLineCommentEnd(lines, lineix):
+ """We are inside a comment, find the end marker."""
+ while lineix < len(lines):
+ if lines[lineix].strip().endswith('*/'):
+ return lineix
+ lineix += 1
+ return len(lines)
+
+
+def RemoveMultiLineCommentsFromRange(lines, begin, end):
+ """Clears a range of lines for multi-line comments."""
+ # Having // dummy comments makes the lines non-empty, so we will not get
+ # unnecessary blank line warnings later in the code.
+ for i in range(begin, end):
+ lines[i] = '/**/'
+
+
+def RemoveMultiLineComments(filename, lines, error):
+ """Removes multiline (c-style) comments from lines."""
+ lineix = 0
+ while lineix < len(lines):
+ lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
+ if lineix_begin >= len(lines):
+ return
+ lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
+ if lineix_end >= len(lines):
+ error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
+ 'Could not find end of multi-line comment')
+ return
+ RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
+ lineix = lineix_end + 1
+
+
+def CleanseComments(line):
+ """Removes //-comments and single-line C-style /* */ comments.
+
+ Args:
+ line: A line of C++ source.
+
+ Returns:
+ The line with single-line comments removed.
+ """
+ commentpos = line.find('//')
+ if commentpos != -1 and not IsCppString(line[:commentpos]):
+ line = line[:commentpos].rstrip()
+ # get rid of /* ... */
+ return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
+
+
+class CleansedLines(object):
+ """Holds 4 copies of all lines with different preprocessing applied to them.
+
+ 1) elided member contains lines without strings and comments.
+ 2) lines member contains lines without comments.
+ 3) raw_lines member contains all the lines without processing.
+ 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
+ strings removed.
+ All these members are of <type 'list'>, and of the same length.
+ """
+
+ def __init__(self, lines):
+ self.elided = []
+ self.lines = []
+ self.raw_lines = lines
+ self.num_lines = len(lines)
+ self.lines_without_raw_strings = CleanseRawStrings(lines)
+ for linenum in range(len(self.lines_without_raw_strings)):
+ self.lines.append(CleanseComments(
+ self.lines_without_raw_strings[linenum]))
+ elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
+ self.elided.append(CleanseComments(elided))
+
+ def NumLines(self):
+ """Returns the number of lines represented."""
+ return self.num_lines
+
+ @staticmethod
+ def _CollapseStrings(elided):
+ """Collapses strings and chars on a line to simple "" or '' blocks.
+
+ We nix strings first so we're not fooled by text like '"http://"'
+
+ Args:
+ elided: The line being processed.
+
+ Returns:
+ The line with collapsed strings.
+ """
+ if _RE_PATTERN_INCLUDE.match(elided):
+ return elided
+
+ # Remove escaped characters first to make quote/single quote collapsing
+ # basic. Things that look like escaped characters shouldn't occur
+ # outside of strings and chars.
+ elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
+
+ # Replace quoted strings and digit separators. Both single quotes
+ # and double quotes are processed in the same loop, otherwise
+ # nested quotes wouldn't work.
+ collapsed = ''
+ while True:
+ # Find the first quote character
+ match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
+ if not match:
+ collapsed += elided
+ break
+ head, quote, tail = match.groups()
+
+ if quote == '"':
+ # Collapse double quoted strings
+ second_quote = tail.find('"')
+ if second_quote >= 0:
+ collapsed += head + '""'
+ elided = tail[second_quote + 1:]
+ else:
+ # Unmatched double quote, don't bother processing the rest
+ # of the line since this is probably a multiline string.
+ collapsed += elided
+ break
+ else:
+ # Found single quote, check nearby text to eliminate digit separators.
+ #
+ # There is no special handling for floating point here, because
+ # the integer/fractional/exponent parts would all be parsed
+ # correctly as long as there are digits on both sides of the
+ # separator. So we are fine as long as we don't see something
+ # like "0.'3" (gcc 4.9.0 will not allow this literal).
+ if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
+ match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
+ collapsed += head + match_literal.group(1).replace("'", '')
+ elided = match_literal.group(2)
+ else:
+ second_quote = tail.find('\'')
+ if second_quote >= 0:
+ collapsed += head + "''"
+ elided = tail[second_quote + 1:]
+ else:
+ # Unmatched single quote
+ collapsed += elided
+ break
+
+ return collapsed
+
+
+def FindEndOfExpressionInLine(line, startpos, stack):
+ """Find the position just after the end of current parenthesized expression.
+
+ Args:
+ line: a CleansedLines line.
+ startpos: start searching at this position.
+ stack: nesting stack at startpos.
+
+ Returns:
+ On finding matching end: (index just after matching end, None)
+ On finding an unclosed expression: (-1, None)
+ Otherwise: (-1, new stack at end of this line)
+ """
+ for i in xrange(startpos, len(line)):
+ char = line[i]
+ if char in '([{':
+ # Found start of parenthesized expression, push to expression stack
+ stack.append(char)
+ elif char == '<':
+ # Found potential start of template argument list
+ if i > 0 and line[i - 1] == '<':
+ # Left shift operator
+ if stack and stack[-1] == '<':
+ stack.pop()
+ if not stack:
+ return (-1, None)
+ elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
+ # operator<, don't add to stack
+ continue
+ else:
+ # Tentative start of template argument list
+ stack.append('<')
+ elif char in ')]}':
+ # Found end of parenthesized expression.
+ #
+ # If we are currently expecting a matching '>', the pending '<'
+ # must have been an operator. Remove them from expression stack.
+ while stack and stack[-1] == '<':
+ stack.pop()
+ if not stack:
+ return (-1, None)
+ if ((stack[-1] == '(' and char == ')') or
+ (stack[-1] == '[' and char == ']') or
+ (stack[-1] == '{' and char == '}')):
+ stack.pop()
+ if not stack:
+ return (i + 1, None)
+ else:
+ # Mismatched parentheses
+ return (-1, None)
+ elif char == '>':
+ # Found potential end of template argument list.
+
+ # Ignore "->" and operator functions
+ if (i > 0 and
+ (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
+ continue
+
+ # Pop the stack if there is a matching '<'. Otherwise, ignore
+ # this '>' since it must be an operator.
+ if stack:
+ if stack[-1] == '<':
+ stack.pop()
+ if not stack:
+ return (i + 1, None)
+ elif char == ';':
+ # Found something that look like end of statements. If we are currently
+ # expecting a '>', the matching '<' must have been an operator, since
+ # template argument list should not contain statements.
+ while stack and stack[-1] == '<':
+ stack.pop()
+ if not stack:
+ return (-1, None)
+
+ # Did not find end of expression or unbalanced parentheses on this line
+ return (-1, stack)
+
+
+def CloseExpression(clean_lines, linenum, pos):
+ """If input points to ( or { or [ or <, finds the position that closes it.
+
+ If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
+ linenum/pos that correspond to the closing of the expression.
+
+ TODO(unknown): cpplint spends a fair bit of time matching parentheses.
+ Ideally we would want to index all opening and closing parentheses once
+ and have CloseExpression be just a simple lookup, but due to preprocessor
+ tricks, this is not so easy.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ pos: A position on the line.
+
+ Returns:
+ A tuple (line, linenum, pos) pointer *past* the closing brace, or
+ (line, len(lines), -1) if we never find a close. Note we ignore
+ strings and comments when matching; and the line we return is the
+ 'cleansed' line at linenum.
+ """
+
+ line = clean_lines.elided[linenum]
+ if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
+ return (line, clean_lines.NumLines(), -1)
+
+ # Check first line
+ (end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
+ if end_pos > -1:
+ return (line, linenum, end_pos)
+
+ # Continue scanning forward
+ while stack and linenum < clean_lines.NumLines() - 1:
+ linenum += 1
+ line = clean_lines.elided[linenum]
+ (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
+ if end_pos > -1:
+ return (line, linenum, end_pos)
+
+ # Did not find end of expression before end of file, give up
+ return (line, clean_lines.NumLines(), -1)
+
+
+def FindStartOfExpressionInLine(line, endpos, stack):
+ """Find position at the matching start of current expression.
+
+ This is almost the reverse of FindEndOfExpressionInLine, but note
+ that the input position and returned position differs by 1.
+
+ Args:
+ line: a CleansedLines line.
+ endpos: start searching at this position.
+ stack: nesting stack at endpos.
+
+ Returns:
+ On finding matching start: (index at matching start, None)
+ On finding an unclosed expression: (-1, None)
+ Otherwise: (-1, new stack at beginning of this line)
+ """
+ i = endpos
+ while i >= 0:
+ char = line[i]
+ if char in ')]}':
+ # Found end of expression, push to expression stack
+ stack.append(char)
+ elif char == '>':
+ # Found potential end of template argument list.
+ #
+ # Ignore it if it's a "->" or ">=" or "operator>"
+ if (i > 0 and
+ (line[i - 1] == '-' or
+ Match(r'\s>=\s', line[i - 1:]) or
+ Search(r'\boperator\s*$', line[0:i]))):
+ i -= 1
+ else:
+ stack.append('>')
+ elif char == '<':
+ # Found potential start of template argument list
+ if i > 0 and line[i - 1] == '<':
+ # Left shift operator
+ i -= 1
+ else:
+ # If there is a matching '>', we can pop the expression stack.
+ # Otherwise, ignore this '<' since it must be an operator.
+ if stack and stack[-1] == '>':
+ stack.pop()
+ if not stack:
+ return (i, None)
+ elif char in '([{':
+ # Found start of expression.
+ #
+ # If there are any unmatched '>' on the stack, they must be
+ # operators. Remove those.
+ while stack and stack[-1] == '>':
+ stack.pop()
+ if not stack:
+ return (-1, None)
+ if ((char == '(' and stack[-1] == ')') or
+ (char == '[' and stack[-1] == ']') or
+ (char == '{' and stack[-1] == '}')):
+ stack.pop()
+ if not stack:
+ return (i, None)
+ else:
+ # Mismatched parentheses
+ return (-1, None)
+ elif char == ';':
+ # Found something that look like end of statements. If we are currently
+ # expecting a '<', the matching '>' must have been an operator, since
+ # template argument list should not contain statements.
+ while stack and stack[-1] == '>':
+ stack.pop()
+ if not stack:
+ return (-1, None)
+
+ i -= 1
+
+ return (-1, stack)
+
+
+def ReverseCloseExpression(clean_lines, linenum, pos):
+ """If input points to ) or } or ] or >, finds the position that opens it.
+
+ If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
+ linenum/pos that correspond to the opening of the expression.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ pos: A position on the line.
+
+ Returns:
+ A tuple (line, linenum, pos) pointer *at* the opening brace, or
+ (line, 0, -1) if we never find the matching opening brace. Note
+ we ignore strings and comments when matching; and the line we
+ return is the 'cleansed' line at linenum.
+ """
+ line = clean_lines.elided[linenum]
+ if line[pos] not in ')}]>':
+ return (line, 0, -1)
+
+ # Check last line
+ (start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
+ if start_pos > -1:
+ return (line, linenum, start_pos)
+
+ # Continue scanning backward
+ while stack and linenum > 0:
+ linenum -= 1
+ line = clean_lines.elided[linenum]
+ (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
+ if start_pos > -1:
+ return (line, linenum, start_pos)
+
+ # Did not find start of expression before beginning of file, give up
+ return (line, 0, -1)
+
+
+def CheckForCopyright(filename, lines, error):
+ """Logs an error if no Copyright message appears at the top of the file."""
+
+ # We'll say it should occur by line 10. Don't forget there's a
+ # dummy line at the front.
+ for line in xrange(1, min(len(lines), 11)):
+ if re.search(r'Copyright', lines[line], re.I): break
+ else: # means no copyright line was found
+ error(filename, 0, 'legal/copyright', 5,
+ 'No copyright message found. '
+ 'You should have a line: "Copyright [year] <Copyright Owner>"')
+
+
+def GetIndentLevel(line):
+ """Return the number of leading spaces in line.
+
+ Args:
+ line: A string to check.
+
+ Returns:
+ An integer count of leading spaces, possibly zero.
+ """
+ indent = Match(r'^( *)\S', line)
+ if indent:
+ return len(indent.group(1))
+ else:
+ return 0
+
+
+def GetHeaderGuardCPPVariable(filename):
+ """Returns the CPP variable that should be used as a header guard.
+
+ Args:
+ filename: The name of a C++ header file.
+
+ Returns:
+ The CPP variable that should be used as a header guard in the
+ named file.
+
+ """
+
+ # Restores original filename in case that cpplint is invoked from Emacs's
+ # flymake.
+ filename = re.sub(r'_flymake\.h$', '.h', filename)
+ filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
+ # Replace 'c++' with 'cpp'.
+ filename = filename.replace('C++', 'cpp').replace('c++', 'cpp')
+
+ fileinfo = FileInfo(filename)
+ file_path_from_root = fileinfo.RepositoryName()
+ if _root:
+ file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
+ return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
+
+
+def CheckForHeaderGuard(filename, clean_lines, error):
+ """Checks that the file contains a header guard.
+
+ Logs an error if no #ifndef header guard is present. For other
+ headers, checks that the full pathname is used.
+
+ Args:
+ filename: The name of the C++ header file.
+ clean_lines: A CleansedLines instance containing the file.
+ error: The function to call with any errors found.
+ """
+
+ # Don't check for header guards if there are error suppression
+ # comments somewhere in this file.
+ #
+ # Because this is silencing a warning for a nonexistent line, we
+ # only support the very specific NOLINT(build/header_guard) syntax,
+ # and not the general NOLINT or NOLINT(*) syntax.
+ raw_lines = clean_lines.lines_without_raw_strings
+ for i in raw_lines:
+ if Search(r'//\s*NOLINT\(build/header_guard\)', i):
+ return
+
+ cppvar = GetHeaderGuardCPPVariable(filename)
+
+ ifndef = ''
+ ifndef_linenum = 0
+ define = ''
+ endif = ''
+ endif_linenum = 0
+ for linenum, line in enumerate(raw_lines):
+ linesplit = line.split()
+ if len(linesplit) >= 2:
+ # find the first occurrence of #ifndef and #define, save arg
+ if not ifndef and linesplit[0] == '#ifndef':
+ # set ifndef to the header guard presented on the #ifndef line.
+ ifndef = linesplit[1]
+ ifndef_linenum = linenum
+ if not define and linesplit[0] == '#define':
+ define = linesplit[1]
+ # find the last occurrence of #endif, save entire line
+ if line.startswith('#endif'):
+ endif = line
+ endif_linenum = linenum
+
+ if not ifndef or not define or ifndef != define:
+ error(filename, 0, 'build/header_guard', 5,
+ 'No #ifndef header guard found, suggested CPP variable is: %s' %
+ cppvar)
+ return
+
+ # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
+ # for backward compatibility.
+ if ifndef != cppvar:
+ error_level = 0
+ if ifndef != cppvar + '_':
+ error_level = 5
+
+ ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
+ error)
+ error(filename, ifndef_linenum, 'build/header_guard', error_level,
+ '#ifndef header guard has wrong style, please use: %s' % cppvar)
+
+ # Check for "//" comments on endif line.
+ ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
+ error)
+ match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
+ if match:
+ if match.group(1) == '_':
+ # Issue low severity warning for deprecated double trailing underscore
+ error(filename, endif_linenum, 'build/header_guard', 0,
+ '#endif line should be "#endif // %s"' % cppvar)
+ return
+
+ # Didn't find the corresponding "//" comment. If this file does not
+ # contain any "//" comments at all, it could be that the compiler
+ # only wants "/**/" comments, look for those instead.
+ no_single_line_comments = True
+ for i in xrange(1, len(raw_lines) - 1):
+ line = raw_lines[i]
+ if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
+ no_single_line_comments = False
+ break
+
+ if no_single_line_comments:
+ match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
+ if match:
+ if match.group(1) == '_':
+ # Low severity warning for double trailing underscore
+ error(filename, endif_linenum, 'build/header_guard', 0,
+ '#endif line should be "#endif /* %s */"' % cppvar)
+ return
+
+ # Didn't find anything
+ error(filename, endif_linenum, 'build/header_guard', 5,
+ '#endif line should be "#endif // %s"' % cppvar)
+
+
+def CheckHeaderFileIncluded(filename, include_state, error):
+ """Logs an error if a .cc file does not include its header."""
+
+ # Do not check test files
+ if filename.endswith('_test.cc') or filename.endswith('_unittest.cc'):
+ return
+
+ fileinfo = FileInfo(filename)
+ headerfile = filename[0:len(filename) - 2] + 'h'
+ if not os.path.exists(headerfile):
+ return
+ headername = FileInfo(headerfile).RepositoryName()
+ first_include = 0
+ for section_list in include_state.include_list:
+ for f in section_list:
+ if headername in f[0] or f[0] in headername:
+ return
+ if not first_include:
+ first_include = f[1]
+
+ error(filename, first_include, 'build/include', 5,
+ '%s should include its header file %s' % (fileinfo.RepositoryName(),
+ headername))
+
+
+def CheckForBadCharacters(filename, lines, error):
+ """Logs an error for each line containing bad characters.
+
+ Two kinds of bad characters:
+
+ 1. Unicode replacement characters: These indicate that either the file
+ contained invalid UTF-8 (likely) or Unicode replacement characters (which
+ it shouldn't). Note that it's possible for this to throw off line
+ numbering if the invalid UTF-8 occurred adjacent to a newline.
+
+ 2. NUL bytes. These are problematic for some tools.
+
+ Args:
+ filename: The name of the current file.
+ lines: An array of strings, each representing a line of the file.
+ error: The function to call with any errors found.
+ """
+ for linenum, line in enumerate(lines):
+ if u'\ufffd' in line:
+ error(filename, linenum, 'readability/utf8', 5,
+ 'Line contains invalid UTF-8 (or Unicode replacement character).')
+ if '\0' in line:
+ error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
+
+
+def CheckForNewlineAtEOF(filename, lines, error):
+ """Logs an error if there is no newline char at the end of the file.
+
+ Args:
+ filename: The name of the current file.
+ lines: An array of strings, each representing a line of the file.
+ error: The function to call with any errors found.
+ """
+
+ # The array lines() was created by adding two newlines to the
+ # original file (go figure), then splitting on \n.
+ # To verify that the file ends in \n, we just have to make sure the
+ # last-but-two element of lines() exists and is empty.
+ if len(lines) < 3 or lines[-2]:
+ error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
+ 'Could not find a newline character at the end of the file.')
+
+
+def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
+ """Logs an error if we see /* ... */ or "..." that extend past one line.
+
+ /* ... */ comments are legit inside macros, for one line.
+ Otherwise, we prefer // comments, so it's ok to warn about the
+ other. Likewise, it's ok for strings to extend across multiple
+ lines, as long as a line continuation character (backslash)
+ terminates each line. Although not currently prohibited by the C++
+ style guide, it's ugly and unnecessary. We don't do well with either
+ in this lint program, so we warn about both.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Remove all \\ (escaped backslashes) from the line. They are OK, and the
+ # second (escaped) slash may trigger later \" detection erroneously.
+ line = line.replace('\\\\', '')
+
+ if line.count('/*') > line.count('*/'):
+ error(filename, linenum, 'readability/multiline_comment', 5,
+ 'Complex multi-line /*...*/-style comment found. '
+ 'Lint may give bogus warnings. '
+ 'Consider replacing these with //-style comments, '
+ 'with #if 0...#endif, '
+ 'or with more clearly structured multi-line comments.')
+
+ if (line.count('"') - line.count('\\"')) % 2:
+ error(filename, linenum, 'readability/multiline_string', 5,
+ 'Multi-line string ("...") found. This lint script doesn\'t '
+ 'do well with such strings, and may give bogus warnings. '
+ 'Use C++11 raw strings or concatenation instead.')
+
+
+# (non-threadsafe name, thread-safe alternative, validation pattern)
+#
+# The validation pattern is used to eliminate false positives such as:
+# _rand(); // false positive due to substring match.
+# ->rand(); // some member function rand().
+# ACMRandom rand(seed); // some variable named rand.
+# ISAACRandom rand(); // another variable named rand.
+#
+# Basically we require the return value of these functions to be used
+# in some expression context on the same line by matching on some
+# operator before the function name. This eliminates constructors and
+# member function calls.
+_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
+_THREADING_LIST = (
+ ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
+ ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
+ ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
+ ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
+ ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
+ ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
+ ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
+ ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
+ ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
+ ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
+ ('strtok(', 'strtok_r(',
+ _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
+ ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
+ )
+
+
+def CheckPosixThreading(filename, clean_lines, linenum, error):
+ """Checks for calls to thread-unsafe functions.
+
+ Much code has been originally written without consideration of
+ multi-threading. Also, engineers are relying on their old experience;
+ they have learned posix before threading extensions were added. These
+ tests guide the engineers to use thread-safe functions (when using
+ posix directly).
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+ for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
+ # Additional pattern matching check to confirm that this is the
+ # function we are looking for
+ if Search(pattern, line):
+ error(filename, linenum, 'runtime/threadsafe_fn', 2,
+ 'Consider using ' + multithread_safe_func +
+ '...) instead of ' + single_thread_func +
+ '...) for improved thread safety.')
+
+
+def CheckVlogArguments(filename, clean_lines, linenum, error):
+ """Checks that VLOG() is only used for defining a logging level.
+
+ For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
+ VLOG(FATAL) are not.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+ if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
+ error(filename, linenum, 'runtime/vlog', 5,
+ 'VLOG() should be used with numeric verbosity level. '
+ 'Use LOG() if you want symbolic severity levels.')
+
+# Matches invalid increment: *count++, which moves pointer instead of
+# incrementing a value.
+_RE_PATTERN_INVALID_INCREMENT = re.compile(
+ r'^\s*\*\w+(\+\+|--);')
+
+
+def CheckInvalidIncrement(filename, clean_lines, linenum, error):
+ """Checks for invalid increment *count++.
+
+ For example following function:
+ void increment_counter(int* count) {
+ *count++;
+ }
+ is invalid, because it effectively does count++, moving pointer, and should
+ be replaced with ++*count, (*count)++ or *count += 1.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+ if _RE_PATTERN_INVALID_INCREMENT.match(line):
+ error(filename, linenum, 'runtime/invalid_increment', 5,
+ 'Changing pointer instead of value (or unused value of operator*).')
+
+
+def IsMacroDefinition(clean_lines, linenum):
+ if Search(r'^#define', clean_lines[linenum]):
+ return True
+
+ if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
+ return True
+
+ return False
+
+
+def IsForwardClassDeclaration(clean_lines, linenum):
+ return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
+
+
+class _BlockInfo(object):
+ """Stores information about a generic block of code."""
+
+ def __init__(self, seen_open_brace):
+ self.seen_open_brace = seen_open_brace
+ self.open_parentheses = 0
+ self.inline_asm = _NO_ASM
+ self.check_namespace_indentation = False
+
+ def CheckBegin(self, filename, clean_lines, linenum, error):
+ """Run checks that applies to text up to the opening brace.
+
+ This is mostly for checking the text after the class identifier
+ and the "{", usually where the base class is specified. For other
+ blocks, there isn't much to check, so we always pass.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ pass
+
+ def CheckEnd(self, filename, clean_lines, linenum, error):
+ """Run checks that applies to text after the closing brace.
+
+ This is mostly used for checking end of namespace comments.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ pass
+
+ def IsBlockInfo(self):
+ """Returns true if this block is a _BlockInfo.
+
+ This is convenient for verifying that an object is an instance of
+ a _BlockInfo, but not an instance of any of the derived classes.
+
+ Returns:
+ True for this class, False for derived classes.
+ """
+ return self.__class__ == _BlockInfo
+
+
+class _ExternCInfo(_BlockInfo):
+ """Stores information about an 'extern "C"' block."""
+
+ def __init__(self):
+ _BlockInfo.__init__(self, True)
+
+
+class _ClassInfo(_BlockInfo):
+ """Stores information about a class."""
+
+ def __init__(self, name, class_or_struct, clean_lines, linenum):
+ _BlockInfo.__init__(self, False)
+ self.name = name
+ self.starting_linenum = linenum
+ self.is_derived = False
+ self.check_namespace_indentation = True
+ if class_or_struct == 'struct':
+ self.access = 'public'
+ self.is_struct = True
+ else:
+ self.access = 'private'
+ self.is_struct = False
+
+ # Remember initial indentation level for this class. Using raw_lines here
+ # instead of elided to account for leading comments.
+ self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
+
+ # Try to find the end of the class. This will be confused by things like:
+ # class A {
+ # } *x = { ...
+ #
+ # But it's still good enough for CheckSectionSpacing.
+ self.last_line = 0
+ depth = 0
+ for i in range(linenum, clean_lines.NumLines()):
+ line = clean_lines.elided[i]
+ depth += line.count('{') - line.count('}')
+ if not depth:
+ self.last_line = i
+ break
+
+ def CheckBegin(self, filename, clean_lines, linenum, error):
+ # Look for a bare ':'
+ if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
+ self.is_derived = True
+
+ def CheckEnd(self, filename, clean_lines, linenum, error):
+ # If there is a DISALLOW macro, it should appear near the end of
+ # the class.
+ seen_last_thing_in_class = False
+ for i in xrange(linenum - 1, self.starting_linenum, -1):
+ match = Search(
+ r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
+ self.name + r'\)',
+ clean_lines.elided[i])
+ if match:
+ if seen_last_thing_in_class:
+ error(filename, i, 'readability/constructors', 3,
+ match.group(1) + ' should be the last thing in the class')
+ break
+
+ if not Match(r'^\s*$', clean_lines.elided[i]):
+ seen_last_thing_in_class = True
+
+ # Check that closing brace is aligned with beginning of the class.
+ # Only do this if the closing brace is indented by only whitespaces.
+ # This means we will not check single-line class definitions.
+ indent = Match(r'^( *)\}', clean_lines.elided[linenum])
+ if indent and len(indent.group(1)) != self.class_indent:
+ if self.is_struct:
+ parent = 'struct ' + self.name
+ else:
+ parent = 'class ' + self.name
+ error(filename, linenum, 'whitespace/indent', 3,
+ 'Closing brace should be aligned with beginning of %s' % parent)
+
+
+class _NamespaceInfo(_BlockInfo):
+ """Stores information about a namespace."""
+
+ def __init__(self, name, linenum):
+ _BlockInfo.__init__(self, False)
+ self.name = name or ''
+ self.starting_linenum = linenum
+ self.check_namespace_indentation = True
+
+ def CheckEnd(self, filename, clean_lines, linenum, error):
+ """Check end of namespace comments."""
+ line = clean_lines.raw_lines[linenum]
+
+ # Check how many lines is enclosed in this namespace. Don't issue
+ # warning for missing namespace comments if there aren't enough
+ # lines. However, do apply checks if there is already an end of
+ # namespace comment and it's incorrect.
+ #
+ # TODO(unknown): We always want to check end of namespace comments
+ # if a namespace is large, but sometimes we also want to apply the
+ # check if a short namespace contained nontrivial things (something
+ # other than forward declarations). There is currently no logic on
+ # deciding what these nontrivial things are, so this check is
+ # triggered by namespace size only, which works most of the time.
+ if (linenum - self.starting_linenum < 10
+ and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)):
+ return
+
+ # Look for matching comment at end of namespace.
+ #
+ # Note that we accept C style "/* */" comments for terminating
+ # namespaces, so that code that terminate namespaces inside
+ # preprocessor macros can be cpplint clean.
+ #
+ # We also accept stuff like "// end of namespace <name>." with the
+ # period at the end.
+ #
+ # Besides these, we don't accept anything else, otherwise we might
+ # get false negatives when existing comment is a substring of the
+ # expected namespace.
+ if self.name:
+ # Named namespace
+ if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) +
+ r'[\*/\.\\\s]*$'),
+ line):
+ error(filename, linenum, 'readability/namespace', 5,
+ 'Namespace should be terminated with "// namespace %s"' %
+ self.name)
+ else:
+ # Anonymous namespace
+ if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
+ # If "// namespace anonymous" or "// anonymous namespace (more text)",
+ # mention "// anonymous namespace" as an acceptable form
+ if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line):
+ error(filename, linenum, 'readability/namespace', 5,
+ 'Anonymous namespace should be terminated with "// namespace"'
+ ' or "// anonymous namespace"')
+ else:
+ error(filename, linenum, 'readability/namespace', 5,
+ 'Anonymous namespace should be terminated with "// namespace"')
+
+
+class _PreprocessorInfo(object):
+ """Stores checkpoints of nesting stacks when #if/#else is seen."""
+
+ def __init__(self, stack_before_if):
+ # The entire nesting stack before #if
+ self.stack_before_if = stack_before_if
+
+ # The entire nesting stack up to #else
+ self.stack_before_else = []
+
+ # Whether we have already seen #else or #elif
+ self.seen_else = False
+
+
+class NestingState(object):
+ """Holds states related to parsing braces."""
+
+ def __init__(self):
+ # Stack for tracking all braces. An object is pushed whenever we
+ # see a "{", and popped when we see a "}". Only 3 types of
+ # objects are possible:
+ # - _ClassInfo: a class or struct.
+ # - _NamespaceInfo: a namespace.
+ # - _BlockInfo: some other type of block.
+ self.stack = []
+
+ # Top of the previous stack before each Update().
+ #
+ # Because the nesting_stack is updated at the end of each line, we
+ # had to do some convoluted checks to find out what is the current
+ # scope at the beginning of the line. This check is simplified by
+ # saving the previous top of nesting stack.
+ #
+ # We could save the full stack, but we only need the top. Copying
+ # the full nesting stack would slow down cpplint by ~10%.
+ self.previous_stack_top = []
+
+ # Stack of _PreprocessorInfo objects.
+ self.pp_stack = []
+
+ def SeenOpenBrace(self):
+ """Check if we have seen the opening brace for the innermost block.
+
+ Returns:
+ True if we have seen the opening brace, False if the innermost
+ block is still expecting an opening brace.
+ """
+ return (not self.stack) or self.stack[-1].seen_open_brace
+
+ def InNamespaceBody(self):
+ """Check if we are currently one level inside a namespace body.
+
+ Returns:
+ True if top of the stack is a namespace block, False otherwise.
+ """
+ return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
+
+ def InExternC(self):
+ """Check if we are currently one level inside an 'extern "C"' block.
+
+ Returns:
+ True if top of the stack is an extern block, False otherwise.
+ """
+ return self.stack and isinstance(self.stack[-1], _ExternCInfo)
+
+ def InClassDeclaration(self):
+ """Check if we are currently one level inside a class or struct declaration.
+
+ Returns:
+ True if top of the stack is a class/struct, False otherwise.
+ """
+ return self.stack and isinstance(self.stack[-1], _ClassInfo)
+
+ def InAsmBlock(self):
+ """Check if we are currently one level inside an inline ASM block.
+
+ Returns:
+ True if the top of the stack is a block containing inline ASM.
+ """
+ return self.stack and self.stack[-1].inline_asm != _NO_ASM
+
+ def InTemplateArgumentList(self, clean_lines, linenum, pos):
+ """Check if current position is inside template argument list.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ pos: position just after the suspected template argument.
+ Returns:
+ True if (linenum, pos) is inside template arguments.
+ """
+ while linenum < clean_lines.NumLines():
+ # Find the earliest character that might indicate a template argument
+ line = clean_lines.elided[linenum]
+ match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
+ if not match:
+ linenum += 1
+ pos = 0
+ continue
+ token = match.group(1)
+ pos += len(match.group(0))
+
+ # These things do not look like template argument list:
+ # class Suspect {
+ # class Suspect x; }
+ if token in ('{', '}', ';'): return False
+
+ # These things look like template argument list:
+ # template <class Suspect>
+ # template <class Suspect = default_value>
+ # template <class Suspect[]>
+ # template <class Suspect...>
+ if token in ('>', '=', '[', ']', '.'): return True
+
+ # Check if token is an unmatched '<'.
+ # If not, move on to the next character.
+ if token != '<':
+ pos += 1
+ if pos >= len(line):
+ linenum += 1
+ pos = 0
+ continue
+
+ # We can't be sure if we just find a single '<', and need to
+ # find the matching '>'.
+ (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
+ if end_pos < 0:
+ # Not sure if template argument list or syntax error in file
+ return False
+ linenum = end_line
+ pos = end_pos
+ return False
+
+ def UpdatePreprocessor(self, line):
+ """Update preprocessor stack.
+
+ We need to handle preprocessors due to classes like this:
+ #ifdef SWIG
+ struct ResultDetailsPageElementExtensionPoint {
+ #else
+ struct ResultDetailsPageElementExtensionPoint : public Extension {
+ #endif
+
+ We make the following assumptions (good enough for most files):
+ - Preprocessor condition evaluates to true from #if up to first
+ #else/#elif/#endif.
+
+ - Preprocessor condition evaluates to false from #else/#elif up
+ to #endif. We still perform lint checks on these lines, but
+ these do not affect nesting stack.
+
+ Args:
+ line: current line to check.
+ """
+ if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
+ # Beginning of #if block, save the nesting stack here. The saved
+ # stack will allow us to restore the parsing state in the #else case.
+ self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
+ elif Match(r'^\s*#\s*(else|elif)\b', line):
+ # Beginning of #else block
+ if self.pp_stack:
+ if not self.pp_stack[-1].seen_else:
+ # This is the first #else or #elif block. Remember the
+ # whole nesting stack up to this point. This is what we
+ # keep after the #endif.
+ self.pp_stack[-1].seen_else = True
+ self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
+
+ # Restore the stack to how it was before the #if
+ self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
+ else:
+ # TODO(unknown): unexpected #else, issue warning?
+ pass
+ elif Match(r'^\s*#\s*endif\b', line):
+ # End of #if or #else blocks.
+ if self.pp_stack:
+ # If we saw an #else, we will need to restore the nesting
+ # stack to its former state before the #else, otherwise we
+ # will just continue from where we left off.
+ if self.pp_stack[-1].seen_else:
+ # Here we can just use a shallow copy since we are the last
+ # reference to it.
+ self.stack = self.pp_stack[-1].stack_before_else
+ # Drop the corresponding #if
+ self.pp_stack.pop()
+ else:
+ # TODO(unknown): unexpected #endif, issue warning?
+ pass
+
+ # TODO(unknown): Update() is too long, but we will refactor later.
+ def Update(self, filename, clean_lines, linenum, error):
+ """Update nesting state with current line.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Remember top of the previous nesting stack.
+ #
+ # The stack is always pushed/popped and not modified in place, so
+ # we can just do a shallow copy instead of copy.deepcopy. Using
+ # deepcopy would slow down cpplint by ~28%.
+ if self.stack:
+ self.previous_stack_top = self.stack[-1]
+ else:
+ self.previous_stack_top = None
+
+ # Update pp_stack
+ self.UpdatePreprocessor(line)
+
+ # Count parentheses. This is to avoid adding struct arguments to
+ # the nesting stack.
+ if self.stack:
+ inner_block = self.stack[-1]
+ depth_change = line.count('(') - line.count(')')
+ inner_block.open_parentheses += depth_change
+
+ # Also check if we are starting or ending an inline assembly block.
+ if inner_block.inline_asm in (_NO_ASM, _END_ASM):
+ if (depth_change != 0 and
+ inner_block.open_parentheses == 1 and
+ _MATCH_ASM.match(line)):
+ # Enter assembly block
+ inner_block.inline_asm = _INSIDE_ASM
+ else:
+ # Not entering assembly block. If previous line was _END_ASM,
+ # we will now shift to _NO_ASM state.
+ inner_block.inline_asm = _NO_ASM
+ elif (inner_block.inline_asm == _INSIDE_ASM and
+ inner_block.open_parentheses == 0):
+ # Exit assembly block
+ inner_block.inline_asm = _END_ASM
+
+ # Consume namespace declaration at the beginning of the line. Do
+ # this in a loop so that we catch same line declarations like this:
+ # namespace proto2 { namespace bridge { class MessageSet; } }
+ while True:
+ # Match start of namespace. The "\b\s*" below catches namespace
+ # declarations even if it weren't followed by a whitespace, this
+ # is so that we don't confuse our namespace checker. The
+ # missing spaces will be flagged by CheckSpacing.
+ namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
+ if not namespace_decl_match:
+ break
+
+ new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
+ self.stack.append(new_namespace)
+
+ line = namespace_decl_match.group(2)
+ if line.find('{') != -1:
+ new_namespace.seen_open_brace = True
+ line = line[line.find('{') + 1:]
+
+ # Look for a class declaration in whatever is left of the line
+ # after parsing namespaces. The regexp accounts for decorated classes
+ # such as in:
+ # class LOCKABLE API Object {
+ # };
+ class_decl_match = Match(
+ r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
+ r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))'
+ r'(.*)$', line)
+ if (class_decl_match and
+ (not self.stack or self.stack[-1].open_parentheses == 0)):
+ # We do not want to accept classes that are actually template arguments:
+ # template <class Ignore1,
+ # class Ignore2 = Default<Args>,
+ # template <Args> class Ignore3>
+ # void Function() {};
+ #
+ # To avoid template argument cases, we scan forward and look for
+ # an unmatched '>'. If we see one, assume we are inside a
+ # template argument list.
+ end_declaration = len(class_decl_match.group(1))
+ if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
+ self.stack.append(_ClassInfo(
+ class_decl_match.group(3), class_decl_match.group(2),
+ clean_lines, linenum))
+ line = class_decl_match.group(4)
+
+ # If we have not yet seen the opening brace for the innermost block,
+ # run checks here.
+ if not self.SeenOpenBrace():
+ self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
+
+ # Update access control if we are inside a class/struct
+ if self.stack and isinstance(self.stack[-1], _ClassInfo):
+ classinfo = self.stack[-1]
+ access_match = Match(
+ r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
+ r':(?:[^:]|$)',
+ line)
+ if access_match:
+ classinfo.access = access_match.group(2)
+
+ # Check that access keywords are indented +1 space. Skip this
+ # check if the keywords are not preceded by whitespaces.
+ indent = access_match.group(1)
+ if (len(indent) != classinfo.class_indent + 1 and
+ Match(r'^\s*$', indent)):
+ if classinfo.is_struct:
+ parent = 'struct ' + classinfo.name
+ else:
+ parent = 'class ' + classinfo.name
+ slots = ''
+ if access_match.group(3):
+ slots = access_match.group(3)
+ error(filename, linenum, 'whitespace/indent', 3,
+ '%s%s: should be indented +1 space inside %s' % (
+ access_match.group(2), slots, parent))
+
+ # Consume braces or semicolons from what's left of the line
+ while True:
+ # Match first brace, semicolon, or closed parenthesis.
+ matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
+ if not matched:
+ break
+
+ token = matched.group(1)
+ if token == '{':
+ # If namespace or class hasn't seen a opening brace yet, mark
+ # namespace/class head as complete. Push a new block onto the
+ # stack otherwise.
+ if not self.SeenOpenBrace():
+ self.stack[-1].seen_open_brace = True
+ elif Match(r'^extern\s*"[^"]*"\s*\{', line):
+ self.stack.append(_ExternCInfo())
+ else:
+ self.stack.append(_BlockInfo(True))
+ if _MATCH_ASM.match(line):
+ self.stack[-1].inline_asm = _BLOCK_ASM
+
+ elif token == ';' or token == ')':
+ # If we haven't seen an opening brace yet, but we already saw
+ # a semicolon, this is probably a forward declaration. Pop
+ # the stack for these.
+ #
+ # Similarly, if we haven't seen an opening brace yet, but we
+ # already saw a closing parenthesis, then these are probably
+ # function arguments with extra "class" or "struct" keywords.
+ # Also pop these stack for these.
+ if not self.SeenOpenBrace():
+ self.stack.pop()
+ else: # token == '}'
+ # Perform end of block checks and pop the stack.
+ if self.stack:
+ self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
+ self.stack.pop()
+ line = matched.group(2)
+
+ def InnermostClass(self):
+ """Get class info on the top of the stack.
+
+ Returns:
+ A _ClassInfo object if we are inside a class, or None otherwise.
+ """
+ for i in range(len(self.stack), 0, -1):
+ classinfo = self.stack[i - 1]
+ if isinstance(classinfo, _ClassInfo):
+ return classinfo
+ return None
+
+ def CheckCompletedBlocks(self, filename, error):
+ """Checks that all classes and namespaces have been completely parsed.
+
+ Call this when all lines in a file have been processed.
+ Args:
+ filename: The name of the current file.
+ error: The function to call with any errors found.
+ """
+ # Note: This test can result in false positives if #ifdef constructs
+ # get in the way of brace matching. See the testBuildClass test in
+ # cpplint_unittest.py for an example of this.
+ for obj in self.stack:
+ if isinstance(obj, _ClassInfo):
+ error(filename, obj.starting_linenum, 'build/class', 5,
+ 'Failed to find complete declaration of class %s' %
+ obj.name)
+ elif isinstance(obj, _NamespaceInfo):
+ error(filename, obj.starting_linenum, 'build/namespaces', 5,
+ 'Failed to find complete declaration of namespace %s' %
+ obj.name)
+
+
+def CheckForNonStandardConstructs(filename, clean_lines, linenum,
+ nesting_state, error):
+ r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
+
+ Complain about several constructs which gcc-2 accepts, but which are
+ not standard C++. Warning about these in lint is one way to ease the
+ transition to new compilers.
+ - put storage class first (e.g. "static const" instead of "const static").
+ - "%lld" instead of %qd" in printf-type functions.
+ - "%1$d" is non-standard in printf-type functions.
+ - "\%" is an undefined character escape sequence.
+ - text after #endif is not allowed.
+ - invalid inner-style forward declaration.
+ - >? and <? operators, and their >?= and <?= cousins.
+
+ Additionally, check for constructor/destructor style violations and reference
+ members, as it is very convenient to do so while checking for
+ gcc-2 compliance.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: A callable to which errors are reported, which takes 4 arguments:
+ filename, line number, error level, and message
+ """
+
+ # Remove comments from the line, but leave in strings for now.
+ line = clean_lines.lines[linenum]
+
+ if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
+ error(filename, linenum, 'runtime/printf_format', 3,
+ '%q in format strings is deprecated. Use %ll instead.')
+
+ if Search(r'printf\s*\(.*".*%\d+\$', line):
+ error(filename, linenum, 'runtime/printf_format', 2,
+ '%N$ formats are unconventional. Try rewriting to avoid them.')
+
+ # Remove escaped backslashes before looking for undefined escapes.
+ line = line.replace('\\\\', '')
+
+ if Search(r'("|\').*\\(%|\[|\(|{)', line):
+ error(filename, linenum, 'build/printf_format', 3,
+ '%, [, (, and { are undefined character escapes. Unescape them.')
+
+ # For the rest, work with both comments and strings removed.
+ line = clean_lines.elided[linenum]
+
+ if Search(r'\b(const|volatile|void|char|short|int|long'
+ r'|float|double|signed|unsigned'
+ r'|schar|u?int8|u?int16|u?int32|u?int64)'
+ r'\s+(register|static|extern|typedef)\b',
+ line):
+ error(filename, linenum, 'build/storage_class', 5,
+ 'Storage class (static, extern, typedef, etc) should be first.')
+
+ if Match(r'\s*#\s*endif\s*[^/\s]+', line):
+ error(filename, linenum, 'build/endif_comment', 5,
+ 'Uncommented text after #endif is non-standard. Use a comment.')
+
+ if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
+ error(filename, linenum, 'build/forward_decl', 5,
+ 'Inner-style forward declarations are invalid. Remove this line.')
+
+ if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
+ line):
+ error(filename, linenum, 'build/deprecated', 3,
+ '>? and <? (max and min) operators are non-standard and deprecated.')
+
+ if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
+ # TODO(unknown): Could it be expanded safely to arbitrary references,
+ # without triggering too many false positives? The first
+ # attempt triggered 5 warnings for mostly benign code in the regtest, hence
+ # the restriction.
+ # Here's the original regexp, for the reference:
+ # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
+ # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
+ error(filename, linenum, 'runtime/member_string_references', 2,
+ 'const string& members are dangerous. It is much better to use '
+ 'alternatives, such as pointers or simple constants.')
+
+ # Everything else in this function operates on class declarations.
+ # Return early if the top of the nesting stack is not a class, or if
+ # the class head is not completed yet.
+ classinfo = nesting_state.InnermostClass()
+ if not classinfo or not classinfo.seen_open_brace:
+ return
+
+ # The class may have been declared with namespace or classname qualifiers.
+ # The constructor and destructor will not have those qualifiers.
+ base_classname = classinfo.name.split('::')[-1]
+
+ # Look for single-argument constructors that aren't marked explicit.
+ # Technically a valid construct, but against style. Also look for
+ # non-single-argument constructors which are also technically valid, but
+ # strongly suggest something is wrong.
+ explicit_constructor_match = Match(
+ r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*'
+ r'\(((?:[^()]|\([^()]*\))*)\)'
+ % re.escape(base_classname),
+ line)
+
+ if explicit_constructor_match:
+ is_marked_explicit = explicit_constructor_match.group(1)
+
+ if not explicit_constructor_match.group(2):
+ constructor_args = []
+ else:
+ constructor_args = explicit_constructor_match.group(2).split(',')
+
+ # collapse arguments so that commas in template parameter lists and function
+ # argument parameter lists don't split arguments in two
+ i = 0
+ while i < len(constructor_args):
+ constructor_arg = constructor_args[i]
+ while (constructor_arg.count('<') > constructor_arg.count('>') or
+ constructor_arg.count('(') > constructor_arg.count(')')):
+ constructor_arg += ',' + constructor_args[i + 1]
+ del constructor_args[i + 1]
+ constructor_args[i] = constructor_arg
+ i += 1
+
+ defaulted_args = [arg for arg in constructor_args if '=' in arg]
+ noarg_constructor = (not constructor_args or # empty arg list
+ # 'void' arg specifier
+ (len(constructor_args) == 1 and
+ constructor_args[0].strip() == 'void'))
+ onearg_constructor = ((len(constructor_args) == 1 and # exactly one arg
+ not noarg_constructor) or
+ # all but at most one arg defaulted
+ (len(constructor_args) >= 1 and
+ not noarg_constructor and
+ len(defaulted_args) >= len(constructor_args) - 1))
+ initializer_list_constructor = bool(
+ onearg_constructor and
+ Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
+ copy_constructor = bool(
+ onearg_constructor and
+ Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
+ % re.escape(base_classname), constructor_args[0].strip()))
+
+ if (not is_marked_explicit and
+ onearg_constructor and
+ not initializer_list_constructor and
+ not copy_constructor):
+ if defaulted_args:
+ error(filename, linenum, 'runtime/explicit', 5,
+ 'Constructors callable with one argument '
+ 'should be marked explicit.')
+ else:
+ error(filename, linenum, 'runtime/explicit', 5,
+ 'Single-parameter constructors should be marked explicit.')
+ elif is_marked_explicit and not onearg_constructor:
+ if noarg_constructor:
+ error(filename, linenum, 'runtime/explicit', 5,
+ 'Zero-parameter constructors should not be marked explicit.')
+ else:
+ error(filename, linenum, 'runtime/explicit', 0,
+ 'Constructors that require multiple arguments '
+ 'should not be marked explicit.')
+
+
+def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
+ """Checks for the correctness of various spacing around function calls.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Since function calls often occur inside if/for/while/switch
+ # expressions - which have their own, more liberal conventions - we
+ # first see if we should be looking inside such an expression for a
+ # function call, to which we can apply more strict standards.
+ fncall = line # if there's no control flow construct, look at whole line
+ for pattern in (r'\bif\s*\((.*)\)\s*{',
+ r'\bfor\s*\((.*)\)\s*{',
+ r'\bwhile\s*\((.*)\)\s*[{;]',
+ r'\bswitch\s*\((.*)\)\s*{'):
+ match = Search(pattern, line)
+ if match:
+ fncall = match.group(1) # look inside the parens for function calls
+ break
+
+ # Except in if/for/while/switch, there should never be space
+ # immediately inside parens (eg "f( 3, 4 )"). We make an exception
+ # for nested parens ( (a+b) + c ). Likewise, there should never be
+ # a space before a ( when it's a function argument. I assume it's a
+ # function argument when the char before the whitespace is legal in
+ # a function name (alnum + _) and we're not starting a macro. Also ignore
+ # pointers and references to arrays and functions coz they're too tricky:
+ # we use a very simple way to recognize these:
+ # " (something)(maybe-something)" or
+ # " (something)(maybe-something," or
+ # " (something)[something]"
+ # Note that we assume the contents of [] to be short enough that
+ # they'll never need to wrap.
+ if ( # Ignore control structures.
+ not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
+ fncall) and
+ # Ignore pointers/references to functions.
+ not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
+ # Ignore pointers/references to arrays.
+ not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
+ if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call
+ error(filename, linenum, 'whitespace/parens', 4,
+ 'Extra space after ( in function call')
+ elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
+ error(filename, linenum, 'whitespace/parens', 2,
+ 'Extra space after (')
+ if (Search(r'\w\s+\(', fncall) and
+ not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
+ not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
+ not Search(r'\bcase\s+\(', fncall)):
+ # TODO(unknown): Space after an operator function seem to be a common
+ # error, silence those for now by restricting them to highest verbosity.
+ if Search(r'\boperator_*\b', line):
+ error(filename, linenum, 'whitespace/parens', 0,
+ 'Extra space before ( in function call')
+ else:
+ error(filename, linenum, 'whitespace/parens', 4,
+ 'Extra space before ( in function call')
+ # If the ) is followed only by a newline or a { + newline, assume it's
+ # part of a control statement (if/while/etc), and don't complain
+ if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
+ # If the closing parenthesis is preceded by only whitespaces,
+ # try to give a more descriptive error message.
+ if Search(r'^\s+\)', fncall):
+ error(filename, linenum, 'whitespace/parens', 2,
+ 'Closing ) should be moved to the previous line')
+ else:
+ error(filename, linenum, 'whitespace/parens', 2,
+ 'Extra space before )')
+
+
+def IsBlankLine(line):
+ """Returns true if the given line is blank.
+
+ We consider a line to be blank if the line is empty or consists of
+ only white spaces.
+
+ Args:
+ line: A line of a string.
+
+ Returns:
+ True, if the given line is blank.
+ """
+ return not line or line.isspace()
+
+
+def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
+ error):
+ is_namespace_indent_item = (
+ len(nesting_state.stack) > 1 and
+ nesting_state.stack[-1].check_namespace_indentation and
+ isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and
+ nesting_state.previous_stack_top == nesting_state.stack[-2])
+
+ if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
+ clean_lines.elided, line):
+ CheckItemIndentationInNamespace(filename, clean_lines.elided,
+ line, error)
+
+
+def CheckForFunctionLengths(filename, clean_lines, linenum,
+ function_state, error):
+ """Reports for long function bodies.
+
+ For an overview why this is done, see:
+ http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
+
+ Uses a simplistic algorithm assuming other style guidelines
+ (especially spacing) are followed.
+ Only checks unindented functions, so class members are unchecked.
+ Trivial bodies are unchecked, so constructors with huge initializer lists
+ may be missed.
+ Blank/comment lines are not counted so as to avoid encouraging the removal
+ of vertical space and comments just to get through a lint check.
+ NOLINT *on the last line of a function* disables this check.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ function_state: Current function name and lines in body so far.
+ error: The function to call with any errors found.
+ """
+ lines = clean_lines.lines
+ line = lines[linenum]
+ joined_line = ''
+
+ starting_func = False
+ regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ...
+ match_result = Match(regexp, line)
+ if match_result:
+ # If the name is all caps and underscores, figure it's a macro and
+ # ignore it, unless it's TEST or TEST_F.
+ function_name = match_result.group(1).split()[-1]
+ if function_name == 'TEST' or function_name == 'TEST_F' or (
+ not Match(r'[A-Z_]+$', function_name)):
+ starting_func = True
+
+ if starting_func:
+ body_found = False
+ for start_linenum in xrange(linenum, clean_lines.NumLines()):
+ start_line = lines[start_linenum]
+ joined_line += ' ' + start_line.lstrip()
+ if Search(r'(;|})', start_line): # Declarations and trivial functions
+ body_found = True
+ break # ... ignore
+ elif Search(r'{', start_line):
+ body_found = True
+ function = Search(r'((\w|:)*)\(', line).group(1)
+ if Match(r'TEST', function): # Handle TEST... macros
+ parameter_regexp = Search(r'(\(.*\))', joined_line)
+ if parameter_regexp: # Ignore bad syntax
+ function += parameter_regexp.group(1)
+ else:
+ function += '()'
+ function_state.Begin(function)
+ break
+ if not body_found:
+ # No body for the function (or evidence of a non-function) was found.
+ error(filename, linenum, 'readability/fn_size', 5,
+ 'Lint failed to find start of function body.')
+ elif Match(r'^\}\s*$', line): # function end
+ function_state.Check(error, filename, linenum)
+ function_state.End()
+ elif not Match(r'^\s*$', line):
+ function_state.Count() # Count non-blank/non-comment lines.
+
+
+_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
+
+
+def CheckComment(line, filename, linenum, next_line_start, error):
+ """Checks for common mistakes in comments.
+
+ Args:
+ line: The line in question.
+ filename: The name of the current file.
+ linenum: The number of the line to check.
+ next_line_start: The first non-whitespace column of the next line.
+ error: The function to call with any errors found.
+ """
+ commentpos = line.find('//')
+ if commentpos != -1:
+ # Check if the // may be in quotes. If so, ignore it
+ # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
+ if (line.count('"', 0, commentpos) -
+ line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes
+ # Allow one space for new scopes, two spaces otherwise:
+ if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
+ ((commentpos >= 1 and
+ line[commentpos-1] not in string.whitespace) or
+ (commentpos >= 2 and
+ line[commentpos-2] not in string.whitespace))):
+ error(filename, linenum, 'whitespace/comments', 2,
+ 'At least two spaces is best between code and comments')
+
+ # Checks for common mistakes in TODO comments.
+ comment = line[commentpos:]
+ match = _RE_PATTERN_TODO.match(comment)
+ if match:
+ # One whitespace is correct; zero whitespace is handled elsewhere.
+ leading_whitespace = match.group(1)
+ if len(leading_whitespace) > 1:
+ error(filename, linenum, 'whitespace/todo', 2,
+ 'Too many spaces before TODO')
+
+ username = match.group(2)
+ if not username:
+ error(filename, linenum, 'readability/todo', 2,
+ 'Missing username in TODO; it should look like '
+ '"// TODO(my_username): Stuff."')
+
+ middle_whitespace = match.group(3)
+ # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
+ if middle_whitespace != ' ' and middle_whitespace != '':
+ error(filename, linenum, 'whitespace/todo', 2,
+ 'TODO(my_username) should be followed by a space')
+
+ # If the comment contains an alphanumeric character, there
+ # should be a space somewhere between it and the // unless
+ # it's a /// or //! Doxygen comment.
+ if (Match(r'//[^ ]*\w', comment) and
+ not Match(r'(///|//\!)(\s+|$)', comment)):
+ error(filename, linenum, 'whitespace/comments', 4,
+ 'Should have a space between // and comment')
+
+
+def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
+ """Checks for improper use of DISALLOW* macros.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum] # get rid of comments and strings
+
+ matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|'
+ r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
+ if not matched:
+ return
+ if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo):
+ if nesting_state.stack[-1].access != 'private':
+ error(filename, linenum, 'readability/constructors', 3,
+ '%s must be in the private: section' % matched.group(1))
+
+ else:
+ # Found DISALLOW* macro outside a class declaration, or perhaps it
+ # was used inside a function when it should have been part of the
+ # class declaration. We could issue a warning here, but it
+ # probably resulted in a compiler error already.
+ pass
+
+
+def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
+ """Checks for the correctness of various spacing issues in the code.
+
+ Things we check for: spaces around operators, spaces after
+ if/for/while/switch, no spaces around parens in function calls, two
+ spaces between code and comment, don't start a block with a blank
+ line, don't end a function with a blank line, don't add a blank line
+ after public/protected/private, don't have too many blank lines in a row.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: The function to call with any errors found.
+ """
+
+ # Don't use "elided" lines here, otherwise we can't check commented lines.
+ # Don't want to use "raw" either, because we don't want to check inside C++11
+ # raw strings,
+ raw = clean_lines.lines_without_raw_strings
+ line = raw[linenum]
+
+ # Before nixing comments, check if the line is blank for no good
+ # reason. This includes the first line after a block is opened, and
+ # blank lines at the end of a function (ie, right before a line like '}'
+ #
+ # Skip all the blank line checks if we are immediately inside a
+ # namespace body. In other words, don't issue blank line warnings
+ # for this block:
+ # namespace {
+ #
+ # }
+ #
+ # A warning about missing end of namespace comments will be issued instead.
+ #
+ # Also skip blank line checks for 'extern "C"' blocks, which are formatted
+ # like namespaces.
+ if (IsBlankLine(line) and
+ not nesting_state.InNamespaceBody() and
+ not nesting_state.InExternC()):
+ elided = clean_lines.elided
+ prev_line = elided[linenum - 1]
+ prevbrace = prev_line.rfind('{')
+ # TODO(unknown): Don't complain if line before blank line, and line after,
+ # both start with alnums and are indented the same amount.
+ # This ignores whitespace at the start of a namespace block
+ # because those are not usually indented.
+ if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
+ # OK, we have a blank line at the start of a code block. Before we
+ # complain, we check if it is an exception to the rule: The previous
+ # non-empty line has the parameters of a function header that are indented
+ # 4 spaces (because they did not fit in a 80 column line when placed on
+ # the same line as the function name). We also check for the case where
+ # the previous line is indented 6 spaces, which may happen when the
+ # initializers of a constructor do not fit into a 80 column line.
+ exception = False
+ if Match(r' {6}\w', prev_line): # Initializer list?
+ # We are looking for the opening column of initializer list, which
+ # should be indented 4 spaces to cause 6 space indentation afterwards.
+ search_position = linenum-2
+ while (search_position >= 0
+ and Match(r' {6}\w', elided[search_position])):
+ search_position -= 1
+ exception = (search_position >= 0
+ and elided[search_position][:5] == ' :')
+ else:
+ # Search for the function arguments or an initializer list. We use a
+ # simple heuristic here: If the line is indented 4 spaces; and we have a
+ # closing paren, without the opening paren, followed by an opening brace
+ # or colon (for initializer lists) we assume that it is the last line of
+ # a function header. If we have a colon indented 4 spaces, it is an
+ # initializer list.
+ exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
+ prev_line)
+ or Match(r' {4}:', prev_line))
+
+ if not exception:
+ error(filename, linenum, 'whitespace/blank_line', 2,
+ 'Redundant blank line at the start of a code block '
+ 'should be deleted.')
+ # Ignore blank lines at the end of a block in a long if-else
+ # chain, like this:
+ # if (condition1) {
+ # // Something followed by a blank line
+ #
+ # } else if (condition2) {
+ # // Something else
+ # }
+ if linenum + 1 < clean_lines.NumLines():
+ next_line = raw[linenum + 1]
+ if (next_line
+ and Match(r'\s*}', next_line)
+ and next_line.find('} else ') == -1):
+ error(filename, linenum, 'whitespace/blank_line', 3,
+ 'Redundant blank line at the end of a code block '
+ 'should be deleted.')
+
+ matched = Match(r'\s*(public|protected|private):', prev_line)
+ if matched:
+ error(filename, linenum, 'whitespace/blank_line', 3,
+ 'Do not leave a blank line after "%s:"' % matched.group(1))
+
+ # Next, check comments
+ next_line_start = 0
+ if linenum + 1 < clean_lines.NumLines():
+ next_line = raw[linenum + 1]
+ next_line_start = len(next_line) - len(next_line.lstrip())
+ CheckComment(line, filename, linenum, next_line_start, error)
+
+ # get rid of comments and strings
+ line = clean_lines.elided[linenum]
+
+ # You shouldn't have spaces before your brackets, except maybe after
+ # 'delete []' or 'return []() {};'
+ if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
+ error(filename, linenum, 'whitespace/braces', 5,
+ 'Extra space before [')
+
+ # In range-based for, we wanted spaces before and after the colon, but
+ # not around "::" tokens that might appear.
+ if (Search(r'for *\(.*[^:]:[^: ]', line) or
+ Search(r'for *\(.*[^: ]:[^:]', line)):
+ error(filename, linenum, 'whitespace/forcolon', 2,
+ 'Missing space around colon in range-based for loop')
+
+
+def CheckOperatorSpacing(filename, clean_lines, linenum, error):
+ """Checks for horizontal spacing around operators.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Don't try to do spacing checks for operator methods. Do this by
+ # replacing the troublesome characters with something else,
+ # preserving column position for all other characters.
+ #
+ # The replacement is done repeatedly to avoid false positives from
+ # operators that call operators.
+ while True:
+ match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
+ if match:
+ line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
+ else:
+ break
+
+ # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
+ # Otherwise not. Note we only check for non-spaces on *both* sides;
+ # sometimes people put non-spaces on one side when aligning ='s among
+ # many lines (not that this is behavior that I approve of...)
+ if ((Search(r'[\w.]=', line) or
+ Search(r'=[\w.]', line))
+ and not Search(r'\b(if|while|for) ', line)
+ # Operators taken from [lex.operators] in C++11 standard.
+ and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
+ and not Search(r'operator=', line)):
+ error(filename, linenum, 'whitespace/operators', 4,
+ 'Missing spaces around =')
+
+ # It's ok not to have spaces around binary operators like + - * /, but if
+ # there's too little whitespace, we get concerned. It's hard to tell,
+ # though, so we punt on this one for now. TODO.
+
+ # You should always have whitespace around binary operators.
+ #
+ # Check <= and >= first to avoid false positives with < and >, then
+ # check non-include lines for spacing around < and >.
+ #
+ # If the operator is followed by a comma, assume it's be used in a
+ # macro context and don't do any checks. This avoids false
+ # positives.
+ #
+ # Note that && is not included here. Those are checked separately
+ # in CheckRValueReference
+ match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
+ if match:
+ error(filename, linenum, 'whitespace/operators', 3,
+ 'Missing spaces around %s' % match.group(1))
+ elif not Match(r'#.*include', line):
+ # Look for < that is not surrounded by spaces. This is only
+ # triggered if both sides are missing spaces, even though
+ # technically should should flag if at least one side is missing a
+ # space. This is done to avoid some false positives with shifts.
+ match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
+ if match:
+ (_, _, end_pos) = CloseExpression(
+ clean_lines, linenum, len(match.group(1)))
+ if end_pos <= -1:
+ error(filename, linenum, 'whitespace/operators', 3,
+ 'Missing spaces around <')
+
+ # Look for > that is not surrounded by spaces. Similar to the
+ # above, we only trigger if both sides are missing spaces to avoid
+ # false positives with shifts.
+ match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
+ if match:
+ (_, _, start_pos) = ReverseCloseExpression(
+ clean_lines, linenum, len(match.group(1)))
+ if start_pos <= -1:
+ error(filename, linenum, 'whitespace/operators', 3,
+ 'Missing spaces around >')
+
+ # We allow no-spaces around << when used like this: 10<<20, but
+ # not otherwise (particularly, not when used as streams)
+ #
+ # We also allow operators following an opening parenthesis, since
+ # those tend to be macros that deal with operators.
+ match = Search(r'(operator|[^\s(<])(?:L|UL|ULL|l|ul|ull)?<<([^\s,=<])', line)
+ if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
+ not (match.group(1) == 'operator' and match.group(2) == ';')):
+ error(filename, linenum, 'whitespace/operators', 3,
+ 'Missing spaces around <<')
+
+ # We allow no-spaces around >> for almost anything. This is because
+ # C++11 allows ">>" to close nested templates, which accounts for
+ # most cases when ">>" is not followed by a space.
+ #
+ # We still warn on ">>" followed by alpha character, because that is
+ # likely due to ">>" being used for right shifts, e.g.:
+ # value >> alpha
+ #
+ # When ">>" is used to close templates, the alphanumeric letter that
+ # follows would be part of an identifier, and there should still be
+ # a space separating the template type and the identifier.
+ # type<type<type>> alpha
+ match = Search(r'>>[a-zA-Z_]', line)
+ if match:
+ error(filename, linenum, 'whitespace/operators', 3,
+ 'Missing spaces around >>')
+
+ # There shouldn't be space around unary operators
+ match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
+ if match:
+ error(filename, linenum, 'whitespace/operators', 4,
+ 'Extra space for operator %s' % match.group(1))
+
+
+def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
+ """Checks for horizontal spacing around parentheses.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # No spaces after an if, while, switch, or for
+ match = Search(r' (if\(|for\(|while\(|switch\()', line)
+ if match:
+ error(filename, linenum, 'whitespace/parens', 5,
+ 'Missing space before ( in %s' % match.group(1))
+
+ # For if/for/while/switch, the left and right parens should be
+ # consistent about how many spaces are inside the parens, and
+ # there should either be zero or one spaces inside the parens.
+ # We don't want: "if ( foo)" or "if ( foo )".
+ # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
+ match = Search(r'\b(if|for|while|switch)\s*'
+ r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
+ line)
+ if match:
+ if len(match.group(2)) != len(match.group(4)):
+ if not (match.group(3) == ';' and
+ len(match.group(2)) == 1 + len(match.group(4)) or
+ not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
+ error(filename, linenum, 'whitespace/parens', 5,
+ 'Mismatching spaces inside () in %s' % match.group(1))
+ if len(match.group(2)) not in [0, 1]:
+ error(filename, linenum, 'whitespace/parens', 5,
+ 'Should have zero or one spaces inside ( and ) in %s' %
+ match.group(1))
+
+
+def CheckCommaSpacing(filename, clean_lines, linenum, error):
+ """Checks for horizontal spacing near commas and semicolons.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ raw = clean_lines.lines_without_raw_strings
+ line = clean_lines.elided[linenum]
+
+ # You should always have a space after a comma (either as fn arg or operator)
+ #
+ # This does not apply when the non-space character following the
+ # comma is another comma, since the only time when that happens is
+ # for empty macro arguments.
+ #
+ # We run this check in two passes: first pass on elided lines to
+ # verify that lines contain missing whitespaces, second pass on raw
+ # lines to confirm that those missing whitespaces are not due to
+ # elided comments.
+ if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
+ Search(r',[^,\s]', raw[linenum])):
+ error(filename, linenum, 'whitespace/comma', 3,
+ 'Missing space after ,')
+
+ # You should always have a space after a semicolon
+ # except for few corner cases
+ # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
+ # space after ;
+ if Search(r';[^\s};\\)/]', line):
+ error(filename, linenum, 'whitespace/semicolon', 3,
+ 'Missing space after ;')
+
+
+def CheckBracesSpacing(filename, clean_lines, linenum, error):
+ """Checks for horizontal spacing near commas.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Except after an opening paren, or after another opening brace (in case of
+ # an initializer list, for instance), you should have spaces before your
+ # braces. And since you should never have braces at the beginning of a line,
+ # this is an easy test.
+ match = Match(r'^(.*[^ ({>]){', line)
+ if match:
+ # Try a bit harder to check for brace initialization. This
+ # happens in one of the following forms:
+ # Constructor() : initializer_list_{} { ... }
+ # Constructor{}.MemberFunction()
+ # Type variable{};
+ # FunctionCall(type{}, ...);
+ # LastArgument(..., type{});
+ # LOG(INFO) << type{} << " ...";
+ # map_of_type[{...}] = ...;
+ # ternary = expr ? new type{} : nullptr;
+ # OuterTemplate<InnerTemplateConstructor<Type>{}>
+ #
+ # We check for the character following the closing brace, and
+ # silence the warning if it's one of those listed above, i.e.
+ # "{.;,)<>]:".
+ #
+ # To account for nested initializer list, we allow any number of
+ # closing braces up to "{;,)<". We can't simply silence the
+ # warning on first sight of closing brace, because that would
+ # cause false negatives for things that are not initializer lists.
+ # Silence this: But not this:
+ # Outer{ if (...) {
+ # Inner{...} if (...){ // Missing space before {
+ # }; }
+ #
+ # There is a false negative with this approach if people inserted
+ # spurious semicolons, e.g. "if (cond){};", but we will catch the
+ # spurious semicolon with a separate check.
+ (endline, endlinenum, endpos) = CloseExpression(
+ clean_lines, linenum, len(match.group(1)))
+ trailing_text = ''
+ if endpos > -1:
+ trailing_text = endline[endpos:]
+ for offset in xrange(endlinenum + 1,
+ min(endlinenum + 3, clean_lines.NumLines() - 1)):
+ trailing_text += clean_lines.elided[offset]
+ if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text):
+ error(filename, linenum, 'whitespace/braces', 5,
+ 'Missing space before {')
+
+ # Make sure '} else {' has spaces.
+ if Search(r'}else', line):
+ error(filename, linenum, 'whitespace/braces', 5,
+ 'Missing space before else')
+
+ # You shouldn't have a space before a semicolon at the end of the line.
+ # There's a special case for "for" since the style guide allows space before
+ # the semicolon there.
+ if Search(r':\s*;\s*$', line):
+ error(filename, linenum, 'whitespace/semicolon', 5,
+ 'Semicolon defining empty statement. Use {} instead.')
+ elif Search(r'^\s*;\s*$', line):
+ error(filename, linenum, 'whitespace/semicolon', 5,
+ 'Line contains only semicolon. If this should be an empty statement, '
+ 'use {} instead.')
+ elif (Search(r'\s+;\s*$', line) and
+ not Search(r'\bfor\b', line)):
+ error(filename, linenum, 'whitespace/semicolon', 5,
+ 'Extra space before last semicolon. If this should be an empty '
+ 'statement, use {} instead.')
+
+
+def IsDecltype(clean_lines, linenum, column):
+ """Check if the token ending on (linenum, column) is decltype().
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: the number of the line to check.
+ column: end column of the token to check.
+ Returns:
+ True if this token is decltype() expression, False otherwise.
+ """
+ (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
+ if start_col < 0:
+ return False
+ if Search(r'\bdecltype\s*$', text[0:start_col]):
+ return True
+ return False
+
+
+def IsTemplateParameterList(clean_lines, linenum, column):
+ """Check if the token ending on (linenum, column) is the end of template<>.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: the number of the line to check.
+ column: end column of the token to check.
+ Returns:
+ True if this token is end of a template parameter list, False otherwise.
+ """
+ (_, startline, startpos) = ReverseCloseExpression(
+ clean_lines, linenum, column)
+ if (startpos > -1 and
+ Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])):
+ return True
+ return False
+
+
+def IsRValueType(typenames, clean_lines, nesting_state, linenum, column):
+ """Check if the token ending on (linenum, column) is a type.
+
+ Assumes that text to the right of the column is "&&" or a function
+ name.
+
+ Args:
+ typenames: set of type names from template-argument-list.
+ clean_lines: A CleansedLines instance containing the file.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ linenum: the number of the line to check.
+ column: end column of the token to check.
+ Returns:
+ True if this token is a type, False if we are not sure.
+ """
+ prefix = clean_lines.elided[linenum][0:column]
+
+ # Get one word to the left. If we failed to do so, this is most
+ # likely not a type, since it's unlikely that the type name and "&&"
+ # would be split across multiple lines.
+ match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix)
+ if not match:
+ return False
+
+ # Check text following the token. If it's "&&>" or "&&," or "&&...", it's
+ # most likely a rvalue reference used inside a template.
+ suffix = clean_lines.elided[linenum][column:]
+ if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix):
+ return True
+
+ # Check for known types and end of templates:
+ # int&& variable
+ # vector<int>&& variable
+ #
+ # Because this function is called recursively, we also need to
+ # recognize pointer and reference types:
+ # int* Function()
+ # int& Function()
+ if (match.group(2) in typenames or
+ match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool',
+ 'short', 'int', 'long', 'signed', 'unsigned',
+ 'float', 'double', 'void', 'auto', '>', '*', '&']):
+ return True
+
+ # If we see a close parenthesis, look for decltype on the other side.
+ # decltype would unambiguously identify a type, anything else is
+ # probably a parenthesized expression and not a type.
+ if match.group(2) == ')':
+ return IsDecltype(
+ clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1)
+
+ # Check for casts and cv-qualifiers.
+ # match.group(1) remainder
+ # -------------- ---------
+ # const_cast< type&&
+ # const type&&
+ # type const&&
+ if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|'
+ r'reinterpret_cast\s*<|\w+\s)\s*$',
+ match.group(1)):
+ return True
+
+ # Look for a preceding symbol that might help differentiate the context.
+ # These are the cases that would be ambiguous:
+ # match.group(1) remainder
+ # -------------- ---------
+ # Call ( expression &&
+ # Declaration ( type&&
+ # sizeof ( type&&
+ # if ( expression &&
+ # while ( expression &&
+ # for ( type&&
+ # for( ; expression &&
+ # statement ; type&&
+ # block { type&&
+ # constructor { expression &&
+ start = linenum
+ line = match.group(1)
+ match_symbol = None
+ while start >= 0:
+ # We want to skip over identifiers and commas to get to a symbol.
+ # Commas are skipped so that we can find the opening parenthesis
+ # for function parameter lists.
+ match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line)
+ if match_symbol:
+ break
+ start -= 1
+ line = clean_lines.elided[start]
+
+ if not match_symbol:
+ # Probably the first statement in the file is an rvalue reference
+ return True
+
+ if match_symbol.group(2) == '}':
+ # Found closing brace, probably an indicate of this:
+ # block{} type&&
+ return True
+
+ if match_symbol.group(2) == ';':
+ # Found semicolon, probably one of these:
+ # for(; expression &&
+ # statement; type&&
+
+ # Look for the previous 'for(' in the previous lines.
+ before_text = match_symbol.group(1)
+ for i in xrange(start - 1, max(start - 6, 0), -1):
+ before_text = clean_lines.elided[i] + before_text
+ if Search(r'for\s*\([^{};]*$', before_text):
+ # This is the condition inside a for-loop
+ return False
+
+ # Did not find a for-init-statement before this semicolon, so this
+ # is probably a new statement and not a condition.
+ return True
+
+ if match_symbol.group(2) == '{':
+ # Found opening brace, probably one of these:
+ # block{ type&& = ... ; }
+ # constructor{ expression && expression }
+
+ # Look for a closing brace or a semicolon. If we see a semicolon
+ # first, this is probably a rvalue reference.
+ line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1]
+ end = start
+ depth = 1
+ while True:
+ for ch in line:
+ if ch == ';':
+ return True
+ elif ch == '{':
+ depth += 1
+ elif ch == '}':
+ depth -= 1
+ if depth == 0:
+ return False
+ end += 1
+ if end >= clean_lines.NumLines():
+ break
+ line = clean_lines.elided[end]
+ # Incomplete program?
+ return False
+
+ if match_symbol.group(2) == '(':
+ # Opening parenthesis. Need to check what's to the left of the
+ # parenthesis. Look back one extra line for additional context.
+ before_text = match_symbol.group(1)
+ if linenum > 1:
+ before_text = clean_lines.elided[linenum - 1] + before_text
+ before_text = match_symbol.group(1)
+
+ # Patterns that are likely to be types:
+ # [](type&&
+ # for (type&&
+ # sizeof(type&&
+ # operator=(type&&
+ #
+ if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text):
+ return True
+
+ # Patterns that are likely to be expressions:
+ # if (expression &&
+ # while (expression &&
+ # : initializer(expression &&
+ # , initializer(expression &&
+ # ( FunctionCall(expression &&
+ # + FunctionCall(expression &&
+ # + (expression &&
+ #
+ # The last '+' represents operators such as '+' and '-'.
+ if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text):
+ return False
+
+ # Something else. Check that tokens to the left look like
+ # return_type function_name
+ match_func = Match(r'^(.*\S.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$',
+ match_symbol.group(1))
+ if match_func:
+ # Check for constructors, which don't have return types.
+ if Search(r'\b(?:explicit|inline)$', match_func.group(1)):
+ return True
+ implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix)
+ if (implicit_constructor and
+ implicit_constructor.group(1) == implicit_constructor.group(2)):
+ return True
+ return IsRValueType(typenames, clean_lines, nesting_state, linenum,
+ len(match_func.group(1)))
+
+ # Nothing before the function name. If this is inside a block scope,
+ # this is probably a function call.
+ return not (nesting_state.previous_stack_top and
+ nesting_state.previous_stack_top.IsBlockInfo())
+
+ if match_symbol.group(2) == '>':
+ # Possibly a closing bracket, check that what's on the other side
+ # looks like the start of a template.
+ return IsTemplateParameterList(
+ clean_lines, start, len(match_symbol.group(1)))
+
+ # Some other symbol, usually something like "a=b&&c". This is most
+ # likely not a type.
+ return False
+
+
+def IsDeletedOrDefault(clean_lines, linenum):
+ """Check if current constructor or operator is deleted or default.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ Returns:
+ True if this is a deleted or default constructor.
+ """
+ open_paren = clean_lines.elided[linenum].find('(')
+ if open_paren < 0:
+ return False
+ (close_line, _, close_paren) = CloseExpression(
+ clean_lines, linenum, open_paren)
+ if close_paren < 0:
+ return False
+ return Match(r'\s*=\s*(?:delete|default)\b', close_line[close_paren:])
+
+
+def IsRValueAllowed(clean_lines, linenum, typenames):
+ """Check if RValue reference is allowed on a particular line.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ typenames: set of type names from template-argument-list.
+ Returns:
+ True if line is within the region where RValue references are allowed.
+ """
+ # Allow region marked by PUSH/POP macros
+ for i in xrange(linenum, 0, -1):
+ line = clean_lines.elided[i]
+ if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
+ if not line.endswith('PUSH'):
+ return False
+ for j in xrange(linenum, clean_lines.NumLines(), 1):
+ line = clean_lines.elided[j]
+ if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
+ return line.endswith('POP')
+
+ # Allow operator=
+ line = clean_lines.elided[linenum]
+ if Search(r'\boperator\s*=\s*\(', line):
+ return IsDeletedOrDefault(clean_lines, linenum)
+
+ # Allow constructors
+ match = Match(r'\s*(?:[\w<>]+::)*([\w<>]+)\s*::\s*([\w<>]+)\s*\(', line)
+ if match and match.group(1) == match.group(2):
+ return IsDeletedOrDefault(clean_lines, linenum)
+ if Search(r'\b(?:explicit|inline)\s+[\w<>]+\s*\(', line):
+ return IsDeletedOrDefault(clean_lines, linenum)
+
+ if Match(r'\s*[\w<>]+\s*\(', line):
+ previous_line = 'ReturnType'
+ if linenum > 0:
+ previous_line = clean_lines.elided[linenum - 1]
+ if Match(r'^\s*$', previous_line) or Search(r'[{}:;]\s*$', previous_line):
+ return IsDeletedOrDefault(clean_lines, linenum)
+
+ # Reject types not mentioned in template-argument-list
+ while line:
+ match = Match(r'^.*?(\w+)\s*&&(.*)$', line)
+ if not match:
+ break
+ if match.group(1) not in typenames:
+ return False
+ line = match.group(2)
+
+ # All RValue types that were in template-argument-list should have
+ # been removed by now. Those were allowed, assuming that they will
+ # be forwarded.
+ #
+ # If there are no remaining RValue types left (i.e. types that were
+ # not found in template-argument-list), flag those as not allowed.
+ return line.find('&&') < 0
+
+
+def GetTemplateArgs(clean_lines, linenum):
+ """Find list of template arguments associated with this function declaration.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: Line number containing the start of the function declaration,
+ usually one line after the end of the template-argument-list.
+ Returns:
+ Set of type names, or empty set if this does not appear to have
+ any template parameters.
+ """
+ # Find start of function
+ func_line = linenum
+ while func_line > 0:
+ line = clean_lines.elided[func_line]
+ if Match(r'^\s*$', line):
+ return set()
+ if line.find('(') >= 0:
+ break
+ func_line -= 1
+ if func_line == 0:
+ return set()
+
+ # Collapse template-argument-list into a single string
+ argument_list = ''
+ match = Match(r'^(\s*template\s*)<', clean_lines.elided[func_line])
+ if match:
+ # template-argument-list on the same line as function name
+ start_col = len(match.group(1))
+ _, end_line, end_col = CloseExpression(clean_lines, func_line, start_col)
+ if end_col > -1 and end_line == func_line:
+ start_col += 1 # Skip the opening bracket
+ argument_list = clean_lines.elided[func_line][start_col:end_col]
+
+ elif func_line > 1:
+ # template-argument-list one line before function name
+ match = Match(r'^(.*)>\s*$', clean_lines.elided[func_line - 1])
+ if match:
+ end_col = len(match.group(1))
+ _, start_line, start_col = ReverseCloseExpression(
+ clean_lines, func_line - 1, end_col)
+ if start_col > -1:
+ start_col += 1 # Skip the opening bracket
+ while start_line < func_line - 1:
+ argument_list += clean_lines.elided[start_line][start_col:]
+ start_col = 0
+ start_line += 1
+ argument_list += clean_lines.elided[func_line - 1][start_col:end_col]
+
+ if not argument_list:
+ return set()
+
+ # Extract type names
+ typenames = set()
+ while True:
+ match = Match(r'^[,\s]*(?:typename|class)(?:\.\.\.)?\s+(\w+)(.*)$',
+ argument_list)
+ if not match:
+ break
+ typenames.add(match.group(1))
+ argument_list = match.group(2)
+ return typenames
+
+
+def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error):
+ """Check for rvalue references.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: The function to call with any errors found.
+ """
+ # Find lines missing spaces around &&.
+ # TODO(unknown): currently we don't check for rvalue references
+ # with spaces surrounding the && to avoid false positives with
+ # boolean expressions.
+ line = clean_lines.elided[linenum]
+ match = Match(r'^(.*\S)&&', line)
+ if not match:
+ match = Match(r'(.*)&&\S', line)
+ if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)):
+ return
+
+ # Either poorly formed && or an rvalue reference, check the context
+ # to get a more accurate error message. Mostly we want to determine
+ # if what's to the left of "&&" is a type or not.
+ typenames = GetTemplateArgs(clean_lines, linenum)
+ and_pos = len(match.group(1))
+ if IsRValueType(typenames, clean_lines, nesting_state, linenum, and_pos):
+ if not IsRValueAllowed(clean_lines, linenum, typenames):
+ error(filename, linenum, 'build/c++11', 3,
+ 'RValue references are an unapproved C++ feature.')
+ else:
+ error(filename, linenum, 'whitespace/operators', 3,
+ 'Missing spaces around &&')
+
+
+def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
+ """Checks for additional blank line issues related to sections.
+
+ Currently the only thing checked here is blank line before protected/private.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ class_info: A _ClassInfo objects.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ # Skip checks if the class is small, where small means 25 lines or less.
+ # 25 lines seems like a good cutoff since that's the usual height of
+ # terminals, and any class that can't fit in one screen can't really
+ # be considered "small".
+ #
+ # Also skip checks if we are on the first line. This accounts for
+ # classes that look like
+ # class Foo { public: ... };
+ #
+ # If we didn't find the end of the class, last_line would be zero,
+ # and the check will be skipped by the first condition.
+ if (class_info.last_line - class_info.starting_linenum <= 24 or
+ linenum <= class_info.starting_linenum):
+ return
+
+ matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
+ if matched:
+ # Issue warning if the line before public/protected/private was
+ # not a blank line, but don't do this if the previous line contains
+ # "class" or "struct". This can happen two ways:
+ # - We are at the beginning of the class.
+ # - We are forward-declaring an inner class that is semantically
+ # private, but needed to be public for implementation reasons.
+ # Also ignores cases where the previous line ends with a backslash as can be
+ # common when defining classes in C macros.
+ prev_line = clean_lines.lines[linenum - 1]
+ if (not IsBlankLine(prev_line) and
+ not Search(r'\b(class|struct)\b', prev_line) and
+ not Search(r'\\$', prev_line)):
+ # Try a bit harder to find the beginning of the class. This is to
+ # account for multi-line base-specifier lists, e.g.:
+ # class Derived
+ # : public Base {
+ end_class_head = class_info.starting_linenum
+ for i in range(class_info.starting_linenum, linenum):
+ if Search(r'\{\s*$', clean_lines.lines[i]):
+ end_class_head = i
+ break
+ if end_class_head < linenum - 1:
+ error(filename, linenum, 'whitespace/blank_line', 3,
+ '"%s:" should be preceded by a blank line' % matched.group(1))
+
+
+def GetPreviousNonBlankLine(clean_lines, linenum):
+ """Return the most recent non-blank line and its line number.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file contents.
+ linenum: The number of the line to check.
+
+ Returns:
+ A tuple with two elements. The first element is the contents of the last
+ non-blank line before the current line, or the empty string if this is the
+ first non-blank line. The second is the line number of that line, or -1
+ if this is the first non-blank line.
+ """
+
+ prevlinenum = linenum - 1
+ while prevlinenum >= 0:
+ prevline = clean_lines.elided[prevlinenum]
+ if not IsBlankLine(prevline): # if not a blank line...
+ return (prevline, prevlinenum)
+ prevlinenum -= 1
+ return ('', -1)
+
+
+def CheckBraces(filename, clean_lines, linenum, error):
+ """Looks for misplaced braces (e.g. at the end of line).
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+
+ line = clean_lines.elided[linenum] # get rid of comments and strings
+
+ if Match(r'\s*{\s*$', line):
+ # We allow an open brace to start a line in the case where someone is using
+ # braces in a block to explicitly create a new scope, which is commonly used
+ # to control the lifetime of stack-allocated variables. Braces are also
+ # used for brace initializers inside function calls. We don't detect this
+ # perfectly: we just don't complain if the last non-whitespace character on
+ # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
+ # previous line starts a preprocessor block.
+ prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+ if (not Search(r'[,;:}{(]\s*$', prevline) and
+ not Match(r'\s*#', prevline)):
+ error(filename, linenum, 'whitespace/braces', 4,
+ '{ should almost always be at the end of the previous line')
+
+ # An else clause should be on the same line as the preceding closing brace.
+ if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
+ prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+ if Match(r'\s*}\s*$', prevline):
+ error(filename, linenum, 'whitespace/newline', 4,
+ 'An else should appear on the same line as the preceding }')
+
+ # If braces come on one side of an else, they should be on both.
+ # However, we have to worry about "else if" that spans multiple lines!
+ if Search(r'else if\s*\(', line): # could be multi-line if
+ brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
+ # find the ( after the if
+ pos = line.find('else if')
+ pos = line.find('(', pos)
+ if pos > 0:
+ (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
+ brace_on_right = endline[endpos:].find('{') != -1
+ if brace_on_left != brace_on_right: # must be brace after if
+ error(filename, linenum, 'readability/braces', 5,
+ 'If an else has a brace on one side, it should have it on both')
+ elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
+ error(filename, linenum, 'readability/braces', 5,
+ 'If an else has a brace on one side, it should have it on both')
+
+ # Likewise, an else should never have the else clause on the same line
+ if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
+ error(filename, linenum, 'whitespace/newline', 4,
+ 'Else clause should never be on same line as else (use 2 lines)')
+
+ # In the same way, a do/while should never be on one line
+ if Match(r'\s*do [^\s{]', line):
+ error(filename, linenum, 'whitespace/newline', 4,
+ 'do/while clauses should not be on a single line')
+
+ # Check single-line if/else bodies. The style guide says 'curly braces are not
+ # required for single-line statements'. We additionally allow multi-line,
+ # single statements, but we reject anything with more than one semicolon in
+ # it. This means that the first semicolon after the if should be at the end of
+ # its line, and the line after that should have an indent level equal to or
+ # lower than the if. We also check for ambiguous if/else nesting without
+ # braces.
+ if_else_match = Search(r'\b(if\s*\(|else\b)', line)
+ if if_else_match and not Match(r'\s*#', line):
+ if_indent = GetIndentLevel(line)
+ endline, endlinenum, endpos = line, linenum, if_else_match.end()
+ if_match = Search(r'\bif\s*\(', line)
+ if if_match:
+ # This could be a multiline if condition, so find the end first.
+ pos = if_match.end() - 1
+ (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
+ # Check for an opening brace, either directly after the if or on the next
+ # line. If found, this isn't a single-statement conditional.
+ if (not Match(r'\s*{', endline[endpos:])
+ and not (Match(r'\s*$', endline[endpos:])
+ and endlinenum < (len(clean_lines.elided) - 1)
+ and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
+ while (endlinenum < len(clean_lines.elided)
+ and ';' not in clean_lines.elided[endlinenum][endpos:]):
+ endlinenum += 1
+ endpos = 0
+ if endlinenum < len(clean_lines.elided):
+ endline = clean_lines.elided[endlinenum]
+ # We allow a mix of whitespace and closing braces (e.g. for one-liner
+ # methods) and a single \ after the semicolon (for macros)
+ endpos = endline.find(';')
+ if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
+ # Semicolon isn't the last character, there's something trailing.
+ # Output a warning if the semicolon is not contained inside
+ # a lambda expression.
+ if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
+ endline):
+ error(filename, linenum, 'readability/braces', 4,
+ 'If/else bodies with multiple statements require braces')
+ elif endlinenum < len(clean_lines.elided) - 1:
+ # Make sure the next line is dedented
+ next_line = clean_lines.elided[endlinenum + 1]
+ next_indent = GetIndentLevel(next_line)
+ # With ambiguous nested if statements, this will error out on the
+ # if that *doesn't* match the else, regardless of whether it's the
+ # inner one or outer one.
+ if (if_match and Match(r'\s*else\b', next_line)
+ and next_indent != if_indent):
+ error(filename, linenum, 'readability/braces', 4,
+ 'Else clause should be indented at the same level as if. '
+ 'Ambiguous nested if/else chains require braces.')
+ elif next_indent > if_indent:
+ error(filename, linenum, 'readability/braces', 4,
+ 'If/else bodies with multiple statements require braces')
+
+
+def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
+ """Looks for redundant trailing semicolon.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+
+ line = clean_lines.elided[linenum]
+
+ # Block bodies should not be followed by a semicolon. Due to C++11
+ # brace initialization, there are more places where semicolons are
+ # required than not, so we use a whitelist approach to check these
+ # rather than a blacklist. These are the places where "};" should
+ # be replaced by just "}":
+ # 1. Some flavor of block following closing parenthesis:
+ # for (;;) {};
+ # while (...) {};
+ # switch (...) {};
+ # Function(...) {};
+ # if (...) {};
+ # if (...) else if (...) {};
+ #
+ # 2. else block:
+ # if (...) else {};
+ #
+ # 3. const member function:
+ # Function(...) const {};
+ #
+ # 4. Block following some statement:
+ # x = 42;
+ # {};
+ #
+ # 5. Block at the beginning of a function:
+ # Function(...) {
+ # {};
+ # }
+ #
+ # Note that naively checking for the preceding "{" will also match
+ # braces inside multi-dimensional arrays, but this is fine since
+ # that expression will not contain semicolons.
+ #
+ # 6. Block following another block:
+ # while (true) {}
+ # {};
+ #
+ # 7. End of namespaces:
+ # namespace {};
+ #
+ # These semicolons seems far more common than other kinds of
+ # redundant semicolons, possibly due to people converting classes
+ # to namespaces. For now we do not warn for this case.
+ #
+ # Try matching case 1 first.
+ match = Match(r'^(.*\)\s*)\{', line)
+ if match:
+ # Matched closing parenthesis (case 1). Check the token before the
+ # matching opening parenthesis, and don't warn if it looks like a
+ # macro. This avoids these false positives:
+ # - macro that defines a base class
+ # - multi-line macro that defines a base class
+ # - macro that defines the whole class-head
+ #
+ # But we still issue warnings for macros that we know are safe to
+ # warn, specifically:
+ # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
+ # - TYPED_TEST
+ # - INTERFACE_DEF
+ # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
+ #
+ # We implement a whitelist of safe macros instead of a blacklist of
+ # unsafe macros, even though the latter appears less frequently in
+ # google code and would have been easier to implement. This is because
+ # the downside for getting the whitelist wrong means some extra
+ # semicolons, while the downside for getting the blacklist wrong
+ # would result in compile errors.
+ #
+ # In addition to macros, we also don't want to warn on
+ # - Compound literals
+ # - Lambdas
+ # - alignas specifier with anonymous structs:
+ closing_brace_pos = match.group(1).rfind(')')
+ opening_parenthesis = ReverseCloseExpression(
+ clean_lines, linenum, closing_brace_pos)
+ if opening_parenthesis[2] > -1:
+ line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
+ macro = Search(r'\b([A-Z_]+)\s*$', line_prefix)
+ func = Match(r'^(.*\])\s*$', line_prefix)
+ if ((macro and
+ macro.group(1) not in (
+ 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
+ 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
+ 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
+ (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
+ Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
+ Search(r'\s+=\s*$', line_prefix)):
+ match = None
+ if (match and
+ opening_parenthesis[1] > 1 and
+ Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
+ # Multi-line lambda-expression
+ match = None
+
+ else:
+ # Try matching cases 2-3.
+ match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
+ if not match:
+ # Try matching cases 4-6. These are always matched on separate lines.
+ #
+ # Note that we can't simply concatenate the previous line to the
+ # current line and do a single match, otherwise we may output
+ # duplicate warnings for the blank line case:
+ # if (cond) {
+ # // blank line
+ # }
+ prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+ if prevline and Search(r'[;{}]\s*$', prevline):
+ match = Match(r'^(\s*)\{', line)
+
+ # Check matching closing brace
+ if match:
+ (endline, endlinenum, endpos) = CloseExpression(
+ clean_lines, linenum, len(match.group(1)))
+ if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
+ # Current {} pair is eligible for semicolon check, and we have found
+ # the redundant semicolon, output warning here.
+ #
+ # Note: because we are scanning forward for opening braces, and
+ # outputting warnings for the matching closing brace, if there are
+ # nested blocks with trailing semicolons, we will get the error
+ # messages in reversed order.
+ error(filename, endlinenum, 'readability/braces', 4,
+ "You don't need a ; after a }")
+
+
+def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
+ """Look for empty loop/conditional body with only a single semicolon.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+
+ # Search for loop keywords at the beginning of the line. Because only
+ # whitespaces are allowed before the keywords, this will also ignore most
+ # do-while-loops, since those lines should start with closing brace.
+ #
+ # We also check "if" blocks here, since an empty conditional block
+ # is likely an error.
+ line = clean_lines.elided[linenum]
+ matched = Match(r'\s*(for|while|if)\s*\(', line)
+ if matched:
+ # Find the end of the conditional expression
+ (end_line, end_linenum, end_pos) = CloseExpression(
+ clean_lines, linenum, line.find('('))
+
+ # Output warning if what follows the condition expression is a semicolon.
+ # No warning for all other cases, including whitespace or newline, since we
+ # have a separate check for semicolons preceded by whitespace.
+ if end_pos >= 0 and Match(r';', end_line[end_pos:]):
+ if matched.group(1) == 'if':
+ error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
+ 'Empty conditional bodies should use {}')
+ else:
+ error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
+ 'Empty loop bodies should use {} or continue')
+
+
+def FindCheckMacro(line):
+ """Find a replaceable CHECK-like macro.
+
+ Args:
+ line: line to search on.
+ Returns:
+ (macro name, start position), or (None, -1) if no replaceable
+ macro is found.
+ """
+ for macro in _CHECK_MACROS:
+ i = line.find(macro)
+ if i >= 0:
+ # Find opening parenthesis. Do a regular expression match here
+ # to make sure that we are matching the expected CHECK macro, as
+ # opposed to some other macro that happens to contain the CHECK
+ # substring.
+ matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
+ if not matched:
+ continue
+ return (macro, len(matched.group(1)))
+ return (None, -1)
+
+
+def CheckCheck(filename, clean_lines, linenum, error):
+ """Checks the use of CHECK and EXPECT macros.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+
+ # Decide the set of replacement macros that should be suggested
+ lines = clean_lines.elided
+ (check_macro, start_pos) = FindCheckMacro(lines[linenum])
+ if not check_macro:
+ return
+
+ # Find end of the boolean expression by matching parentheses
+ (last_line, end_line, end_pos) = CloseExpression(
+ clean_lines, linenum, start_pos)
+ if end_pos < 0:
+ return
+
+ # If the check macro is followed by something other than a
+ # semicolon, assume users will log their own custom error messages
+ # and don't suggest any replacements.
+ if not Match(r'\s*;', last_line[end_pos:]):
+ return
+
+ if linenum == end_line:
+ expression = lines[linenum][start_pos + 1:end_pos - 1]
+ else:
+ expression = lines[linenum][start_pos + 1:]
+ for i in xrange(linenum + 1, end_line):
+ expression += lines[i]
+ expression += last_line[0:end_pos - 1]
+
+ # Parse expression so that we can take parentheses into account.
+ # This avoids false positives for inputs like "CHECK((a < 4) == b)",
+ # which is not replaceable by CHECK_LE.
+ lhs = ''
+ rhs = ''
+ operator = None
+ while expression:
+ matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
+ r'==|!=|>=|>|<=|<|\()(.*)$', expression)
+ if matched:
+ token = matched.group(1)
+ if token == '(':
+ # Parenthesized operand
+ expression = matched.group(2)
+ (end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
+ if end < 0:
+ return # Unmatched parenthesis
+ lhs += '(' + expression[0:end]
+ expression = expression[end:]
+ elif token in ('&&', '||'):
+ # Logical and/or operators. This means the expression
+ # contains more than one term, for example:
+ # CHECK(42 < a && a < b);
+ #
+ # These are not replaceable with CHECK_LE, so bail out early.
+ return
+ elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
+ # Non-relational operator
+ lhs += token
+ expression = matched.group(2)
+ else:
+ # Relational operator
+ operator = token
+ rhs = matched.group(2)
+ break
+ else:
+ # Unparenthesized operand. Instead of appending to lhs one character
+ # at a time, we do another regular expression match to consume several
+ # characters at once if possible. Trivial benchmark shows that this
+ # is more efficient when the operands are longer than a single
+ # character, which is generally the case.
+ matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
+ if not matched:
+ matched = Match(r'^(\s*\S)(.*)$', expression)
+ if not matched:
+ break
+ lhs += matched.group(1)
+ expression = matched.group(2)
+
+ # Only apply checks if we got all parts of the boolean expression
+ if not (lhs and operator and rhs):
+ return
+
+ # Check that rhs do not contain logical operators. We already know
+ # that lhs is fine since the loop above parses out && and ||.
+ if rhs.find('&&') > -1 or rhs.find('||') > -1:
+ return
+
+ # At least one of the operands must be a constant literal. This is
+ # to avoid suggesting replacements for unprintable things like
+ # CHECK(variable != iterator)
+ #
+ # The following pattern matches decimal, hex integers, strings, and
+ # characters (in that order).
+ lhs = lhs.strip()
+ rhs = rhs.strip()
+ match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
+ if Match(match_constant, lhs) or Match(match_constant, rhs):
+ # Note: since we know both lhs and rhs, we can provide a more
+ # descriptive error message like:
+ # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
+ # Instead of:
+ # Consider using CHECK_EQ instead of CHECK(a == b)
+ #
+ # We are still keeping the less descriptive message because if lhs
+ # or rhs gets long, the error message might become unreadable.
+ error(filename, linenum, 'readability/check', 2,
+ 'Consider using %s instead of %s(a %s b)' % (
+ _CHECK_REPLACEMENT[check_macro][operator],
+ check_macro, operator))
+
+
+def CheckAltTokens(filename, clean_lines, linenum, error):
+ """Check alternative keywords being used in boolean expressions.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Avoid preprocessor lines
+ if Match(r'^\s*#', line):
+ return
+
+ # Last ditch effort to avoid multi-line comments. This will not help
+ # if the comment started before the current line or ended after the
+ # current line, but it catches most of the false positives. At least,
+ # it provides a way to workaround this warning for people who use
+ # multi-line comments in preprocessor macros.
+ #
+ # TODO(unknown): remove this once cpplint has better support for
+ # multi-line comments.
+ if line.find('/*') >= 0 or line.find('*/') >= 0:
+ return
+
+ for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
+ error(filename, linenum, 'readability/alt_tokens', 2,
+ 'Use operator %s instead of %s' % (
+ _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
+
+
+def GetLineWidth(line):
+ """Determines the width of the line in column positions.
+
+ Args:
+ line: A string, which may be a Unicode string.
+
+ Returns:
+ The width of the line in column positions, accounting for Unicode
+ combining characters and wide characters.
+ """
+ if isinstance(line, unicode):
+ width = 0
+ for uc in unicodedata.normalize('NFC', line):
+ if unicodedata.east_asian_width(uc) in ('W', 'F'):
+ width += 2
+ elif not unicodedata.combining(uc):
+ width += 1
+ return width
+ else:
+ return len(line)
+
+
+def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
+ error):
+ """Checks rules from the 'C++ style rules' section of cppguide.html.
+
+ Most of these rules are hard to test (naming, comment style), but we
+ do what we can. In particular we check for 2-space indents, line lengths,
+ tab usage, spaces inside code, etc.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ file_extension: The extension (without the dot) of the filename.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: The function to call with any errors found.
+ """
+
+ # Don't use "elided" lines here, otherwise we can't check commented lines.
+ # Don't want to use "raw" either, because we don't want to check inside C++11
+ # raw strings,
+ raw_lines = clean_lines.lines_without_raw_strings
+ line = raw_lines[linenum]
+
+ if line.find('\t') != -1:
+ error(filename, linenum, 'whitespace/tab', 1,
+ 'Tab found; better to use spaces')
+
+ # One or three blank spaces at the beginning of the line is weird; it's
+ # hard to reconcile that with 2-space indents.
+ # NOTE: here are the conditions rob pike used for his tests. Mine aren't
+ # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces
+ # if(RLENGTH > 20) complain = 0;
+ # if(match($0, " +(error|private|public|protected):")) complain = 0;
+ # if(match(prev, "&& *$")) complain = 0;
+ # if(match(prev, "\\|\\| *$")) complain = 0;
+ # if(match(prev, "[\",=><] *$")) complain = 0;
+ # if(match($0, " <<")) complain = 0;
+ # if(match(prev, " +for \\(")) complain = 0;
+ # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
+ scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$'
+ classinfo = nesting_state.InnermostClass()
+ initial_spaces = 0
+ cleansed_line = clean_lines.elided[linenum]
+ while initial_spaces < len(line) and line[initial_spaces] == ' ':
+ initial_spaces += 1
+ if line and line[-1].isspace():
+ error(filename, linenum, 'whitespace/end_of_line', 4,
+ 'Line ends in whitespace. Consider deleting these extra spaces.')
+ # There are certain situations we allow one space, notably for
+ # section labels, and also lines containing multi-line raw strings.
+ elif ((initial_spaces == 1 or initial_spaces == 3) and
+ not Match(scope_or_label_pattern, cleansed_line) and
+ not (clean_lines.raw_lines[linenum] != line and
+ Match(r'^\s*""', line))):
+ error(filename, linenum, 'whitespace/indent', 3,
+ 'Weird number of spaces at line-start. '
+ 'Are you using a 2-space indent?')
+
+ # Check if the line is a header guard.
+ is_header_guard = False
+ if file_extension == 'h' or file_extension == 'hpp':
+ cppvar = GetHeaderGuardCPPVariable(filename)
+ if (line.startswith('#ifndef %s' % cppvar) or
+ line.startswith('#define %s' % cppvar) or
+ line.startswith('#endif // %s' % cppvar)):
+ is_header_guard = True
+ # #include lines and header guards can be long, since there's no clean way to
+ # split them.
+ #
+ # URLs can be long too. It's possible to split these, but it makes them
+ # harder to cut&paste.
+ #
+ # The "$Id:...$" comment may also get very long without it being the
+ # developers fault.
+ if (not line.startswith('#include') and not is_header_guard and
+ not Match(r'^\s*//.*http(s?)://\S*$', line) and
+ not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
+ line_width = GetLineWidth(line)
+ extended_length = int((_line_length * 1.25))
+ if line_width > extended_length:
+ error(filename, linenum, 'whitespace/line_length', 4,
+ 'Lines should very rarely be longer than %i characters' %
+ extended_length)
+ elif line_width > _line_length:
+ error(filename, linenum, 'whitespace/line_length', 2,
+ 'Lines should be <= %i characters long' % _line_length)
+
+ if (cleansed_line.count(';') > 1 and
+ # for loops are allowed two ;'s (and may run over two lines).
+ cleansed_line.find('for') == -1 and
+ (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
+ GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
+ # It's ok to have many commands in a switch case that fits in 1 line
+ not ((cleansed_line.find('case ') != -1 or
+ cleansed_line.find('default:') != -1) and
+ cleansed_line.find('break;') != -1)):
+ error(filename, linenum, 'whitespace/newline', 0,
+ 'More than one command on the same line')
+
+ # Some more style checks
+ CheckBraces(filename, clean_lines, linenum, error)
+ CheckTrailingSemicolon(filename, clean_lines, linenum, error)
+ CheckEmptyBlockBody(filename, clean_lines, linenum, error)
+ CheckAccess(filename, clean_lines, linenum, nesting_state, error)
+ CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
+ CheckOperatorSpacing(filename, clean_lines, linenum, error)
+ CheckParenthesisSpacing(filename, clean_lines, linenum, error)
+ CheckCommaSpacing(filename, clean_lines, linenum, error)
+ CheckBracesSpacing(filename, clean_lines, linenum, error)
+ CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
+ CheckRValueReference(filename, clean_lines, linenum, nesting_state, error)
+ CheckCheck(filename, clean_lines, linenum, error)
+ CheckAltTokens(filename, clean_lines, linenum, error)
+ classinfo = nesting_state.InnermostClass()
+ if classinfo:
+ CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
+
+
+_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
+# Matches the first component of a filename delimited by -s and _s. That is:
+# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
+# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
+# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
+# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
+_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
+
+
+def _DropCommonSuffixes(filename):
+ """Drops common suffixes like _test.cc or -inl.h from filename.
+
+ For example:
+ >>> _DropCommonSuffixes('foo/foo-inl.h')
+ 'foo/foo'
+ >>> _DropCommonSuffixes('foo/bar/foo.cc')
+ 'foo/bar/foo'
+ >>> _DropCommonSuffixes('foo/foo_internal.h')
+ 'foo/foo'
+ >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
+ 'foo/foo_unusualinternal'
+
+ Args:
+ filename: The input filename.
+
+ Returns:
+ The filename with the common suffix removed.
+ """
+ for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
+ 'inl.h', 'impl.h', 'internal.h'):
+ if (filename.endswith(suffix) and len(filename) > len(suffix) and
+ filename[-len(suffix) - 1] in ('-', '_')):
+ return filename[:-len(suffix) - 1]
+ return os.path.splitext(filename)[0]
+
+
+def _IsTestFilename(filename):
+ """Determines if the given filename has a suffix that identifies it as a test.
+
+ Args:
+ filename: The input filename.
+
+ Returns:
+ True if 'filename' looks like a test, False otherwise.
+ """
+ if (filename.endswith('_test.cc') or
+ filename.endswith('_unittest.cc') or
+ filename.endswith('_regtest.cc')):
+ return True
+ else:
+ return False
+
+
+def _ClassifyInclude(fileinfo, include, is_system):
+ """Figures out what kind of header 'include' is.
+
+ Args:
+ fileinfo: The current file cpplint is running over. A FileInfo instance.
+ include: The path to a #included file.
+ is_system: True if the #include used <> rather than "".
+
+ Returns:
+ One of the _XXX_HEADER constants.
+
+ For example:
+ >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
+ _C_SYS_HEADER
+ >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
+ _CPP_SYS_HEADER
+ >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
+ _LIKELY_MY_HEADER
+ >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
+ ... 'bar/foo_other_ext.h', False)
+ _POSSIBLE_MY_HEADER
+ >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
+ _OTHER_HEADER
+ """
+ # This is a list of all standard c++ header files, except
+ # those already checked for above.
+ is_cpp_h = include in _CPP_HEADERS
+
+ if is_system:
+ if is_cpp_h:
+ return _CPP_SYS_HEADER
+ else:
+ return _C_SYS_HEADER
+
+ # If the target file and the include we're checking share a
+ # basename when we drop common extensions, and the include
+ # lives in . , then it's likely to be owned by the target file.
+ target_dir, target_base = (
+ os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
+ include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
+ if target_base == include_base and (
+ include_dir == target_dir or
+ include_dir == os.path.normpath(target_dir + '/../public')):
+ return _LIKELY_MY_HEADER
+
+ # If the target and include share some initial basename
+ # component, it's possible the target is implementing the
+ # include, so it's allowed to be first, but we'll never
+ # complain if it's not there.
+ target_first_component = _RE_FIRST_COMPONENT.match(target_base)
+ include_first_component = _RE_FIRST_COMPONENT.match(include_base)
+ if (target_first_component and include_first_component and
+ target_first_component.group(0) ==
+ include_first_component.group(0)):
+ return _POSSIBLE_MY_HEADER
+
+ return _OTHER_HEADER
+
+
+
+def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
+ """Check rules that are applicable to #include lines.
+
+ Strings on #include lines are NOT removed from elided line, to make
+ certain tasks easier. However, to prevent false positives, checks
+ applicable to #include lines in CheckLanguage must be put here.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ include_state: An _IncludeState instance in which the headers are inserted.
+ error: The function to call with any errors found.
+ """
+ fileinfo = FileInfo(filename)
+ line = clean_lines.lines[linenum]
+
+ # "include" should use the new style "foo/bar.h" instead of just "bar.h"
+ # Only do this check if the included header follows google naming
+ # conventions. If not, assume that it's a 3rd party API that
+ # requires special include conventions.
+ #
+ # We also make an exception for Lua headers, which follow google
+ # naming convention but not the include convention.
+ match = Match(r'#include\s*"([^/]+\.h)"', line)
+ if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
+ error(filename, linenum, 'build/include', 4,
+ 'Include the directory when naming .h files')
+
+ # we shouldn't include a file more than once. actually, there are a
+ # handful of instances where doing so is okay, but in general it's
+ # not.
+ match = _RE_PATTERN_INCLUDE.search(line)
+ if match:
+ include = match.group(2)
+ is_system = (match.group(1) == '<')
+ duplicate_line = include_state.FindHeader(include)
+ if duplicate_line >= 0:
+ error(filename, linenum, 'build/include', 4,
+ '"%s" already included at %s:%s' %
+ (include, filename, duplicate_line))
+ elif (include.endswith('.cc') and
+ os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
+ error(filename, linenum, 'build/include', 4,
+ 'Do not include .cc files from other packages')
+ elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
+ include_state.include_list[-1].append((include, linenum))
+
+ # We want to ensure that headers appear in the right order:
+ # 1) for foo.cc, foo.h (preferred location)
+ # 2) c system files
+ # 3) cpp system files
+ # 4) for foo.cc, foo.h (deprecated location)
+ # 5) other google headers
+ #
+ # We classify each include statement as one of those 5 types
+ # using a number of techniques. The include_state object keeps
+ # track of the highest type seen, and complains if we see a
+ # lower type after that.
+ error_message = include_state.CheckNextIncludeOrder(
+ _ClassifyInclude(fileinfo, include, is_system))
+ if error_message:
+ error(filename, linenum, 'build/include_order', 4,
+ '%s. Should be: %s.h, c system, c++ system, other.' %
+ (error_message, fileinfo.BaseName()))
+ canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
+ if not include_state.IsInAlphabeticalOrder(
+ clean_lines, linenum, canonical_include):
+ error(filename, linenum, 'build/include_alpha', 4,
+ 'Include "%s" not in alphabetical order' % include)
+ include_state.SetLastHeader(canonical_include)
+
+
+
+def _GetTextInside(text, start_pattern):
+ r"""Retrieves all the text between matching open and close parentheses.
+
+ Given a string of lines and a regular expression string, retrieve all the text
+ following the expression and between opening punctuation symbols like
+ (, [, or {, and the matching close-punctuation symbol. This properly nested
+ occurrences of the punctuations, so for the text like
+ printf(a(), b(c()));
+ a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
+ start_pattern must match string having an open punctuation symbol at the end.
+
+ Args:
+ text: The lines to extract text. Its comments and strings must be elided.
+ It can be single line and can span multiple lines.
+ start_pattern: The regexp string indicating where to start extracting
+ the text.
+ Returns:
+ The extracted text.
+ None if either the opening string or ending punctuation could not be found.
+ """
+ # TODO(unknown): Audit cpplint.py to see what places could be profitably
+ # rewritten to use _GetTextInside (and use inferior regexp matching today).
+
+ # Give opening punctuations to get the matching close-punctuations.
+ matching_punctuation = {'(': ')', '{': '}', '[': ']'}
+ closing_punctuation = set(matching_punctuation.itervalues())
+
+ # Find the position to start extracting text.
+ match = re.search(start_pattern, text, re.M)
+ if not match: # start_pattern not found in text.
+ return None
+ start_position = match.end(0)
+
+ assert start_position > 0, (
+ 'start_pattern must ends with an opening punctuation.')
+ assert text[start_position - 1] in matching_punctuation, (
+ 'start_pattern must ends with an opening punctuation.')
+ # Stack of closing punctuations we expect to have in text after position.
+ punctuation_stack = [matching_punctuation[text[start_position - 1]]]
+ position = start_position
+ while punctuation_stack and position < len(text):
+ if text[position] == punctuation_stack[-1]:
+ punctuation_stack.pop()
+ elif text[position] in closing_punctuation:
+ # A closing punctuation without matching opening punctuations.
+ return None
+ elif text[position] in matching_punctuation:
+ punctuation_stack.append(matching_punctuation[text[position]])
+ position += 1
+ if punctuation_stack:
+ # Opening punctuations left without matching close-punctuations.
+ return None
+ # punctuations match.
+ return text[start_position:position - 1]
+
+
+# Patterns for matching call-by-reference parameters.
+#
+# Supports nested templates up to 2 levels deep using this messy pattern:
+# < (?: < (?: < [^<>]*
+# >
+# | [^<>] )*
+# >
+# | [^<>] )*
+# >
+_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]*
+_RE_PATTERN_TYPE = (
+ r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
+ r'(?:\w|'
+ r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
+ r'::)+')
+# A call-by-reference parameter ends with '& identifier'.
+_RE_PATTERN_REF_PARAM = re.compile(
+ r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
+ r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
+# A call-by-const-reference parameter either ends with 'const& identifier'
+# or looks like 'const type& identifier' when 'type' is atomic.
+_RE_PATTERN_CONST_REF_PARAM = (
+ r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
+ r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
+
+
+def CheckLanguage(filename, clean_lines, linenum, file_extension,
+ include_state, nesting_state, error):
+ """Checks rules from the 'C++ language rules' section of cppguide.html.
+
+ Some of these rules are hard to test (function overloading, using
+ uint32 inappropriately), but we do the best we can.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ file_extension: The extension (without the dot) of the filename.
+ include_state: An _IncludeState instance in which the headers are inserted.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: The function to call with any errors found.
+ """
+ # If the line is empty or consists of entirely a comment, no need to
+ # check it.
+ line = clean_lines.elided[linenum]
+ if not line:
+ return
+
+ match = _RE_PATTERN_INCLUDE.search(line)
+ if match:
+ CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
+ return
+
+ # Reset include state across preprocessor directives. This is meant
+ # to silence warnings for conditional includes.
+ match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
+ if match:
+ include_state.ResetSection(match.group(1))
+
+ # Make Windows paths like Unix.
+ fullname = os.path.abspath(filename).replace('\\', '/')
+
+ # Perform other checks now that we are sure that this is not an include line
+ CheckCasts(filename, clean_lines, linenum, error)
+ CheckGlobalStatic(filename, clean_lines, linenum, error)
+ CheckPrintf(filename, clean_lines, linenum, error)
+
+ if file_extension == 'h':
+ # TODO(unknown): check that 1-arg constructors are explicit.
+ # How to tell it's a constructor?
+ # (handled in CheckForNonStandardConstructs for now)
+ # TODO(unknown): check that classes declare or disable copy/assign
+ # (level 1 error)
+ pass
+
+ # Check if people are using the verboten C basic types. The only exception
+ # we regularly allow is "unsigned short port" for port.
+ if Search(r'\bshort port\b', line):
+ if not Search(r'\bunsigned short port\b', line):
+ error(filename, linenum, 'runtime/int', 4,
+ 'Use "unsigned short" for ports, not "short"')
+ else:
+ match = Search(r'\b(short|long(?! +double)|long long)\b', line)
+ if match:
+ error(filename, linenum, 'runtime/int', 4,
+ 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
+
+ # Check if some verboten operator overloading is going on
+ # TODO(unknown): catch out-of-line unary operator&:
+ # class X {};
+ # int operator&(const X& x) { return 42; } // unary operator&
+ # The trick is it's hard to tell apart from binary operator&:
+ # class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
+ if Search(r'\boperator\s*&\s*\(\s*\)', line):
+ error(filename, linenum, 'runtime/operator', 4,
+ 'Unary operator& is dangerous. Do not use it.')
+
+ # Check for suspicious usage of "if" like
+ # } if (a == b) {
+ if Search(r'\}\s*if\s*\(', line):
+ error(filename, linenum, 'readability/braces', 4,
+ 'Did you mean "else if"? If not, start a new line for "if".')
+
+ # Check for potential format string bugs like printf(foo).
+ # We constrain the pattern not to pick things like DocidForPrintf(foo).
+ # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
+ # TODO(unknown): Catch the following case. Need to change the calling
+ # convention of the whole function to process multiple line to handle it.
+ # printf(
+ # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
+ printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
+ if printf_args:
+ match = Match(r'([\w.\->()]+)$', printf_args)
+ if match and match.group(1) != '__VA_ARGS__':
+ function_name = re.search(r'\b((?:string)?printf)\s*\(',
+ line, re.I).group(1)
+ error(filename, linenum, 'runtime/printf', 4,
+ 'Potential format string bug. Do %s("%%s", %s) instead.'
+ % (function_name, match.group(1)))
+
+ # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
+ match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
+ if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
+ error(filename, linenum, 'runtime/memset', 4,
+ 'Did you mean "memset(%s, 0, %s)"?'
+ % (match.group(1), match.group(2)))
+
+ if Search(r'\busing namespace\b', line):
+ error(filename, linenum, 'build/namespaces', 5,
+ 'Do not use namespace using-directives. '
+ 'Use using-declarations instead.')
+
+ # Detect variable-length arrays.
+ match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
+ if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
+ match.group(3).find(']') == -1):
+ # Split the size using space and arithmetic operators as delimiters.
+ # If any of the resulting tokens are not compile time constants then
+ # report the error.
+ tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
+ is_const = True
+ skip_next = False
+ for tok in tokens:
+ if skip_next:
+ skip_next = False
+ continue
+
+ if Search(r'sizeof\(.+\)', tok): continue
+ if Search(r'arraysize\(\w+\)', tok): continue
+
+ tok = tok.lstrip('(')
+ tok = tok.rstrip(')')
+ if not tok: continue
+ if Match(r'\d+', tok): continue
+ if Match(r'0[xX][0-9a-fA-F]+', tok): continue
+ if Match(r'k[A-Z0-9]\w*', tok): continue
+ if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
+ if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
+ # A catch all for tricky sizeof cases, including 'sizeof expression',
+ # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
+ # requires skipping the next token because we split on ' ' and '*'.
+ if tok.startswith('sizeof'):
+ skip_next = True
+ continue
+ is_const = False
+ break
+ if not is_const:
+ error(filename, linenum, 'runtime/arrays', 1,
+ 'Do not use variable-length arrays. Use an appropriately named '
+ "('k' followed by CamelCase) compile-time constant for the size.")
+
+ # Check for use of unnamed namespaces in header files. Registration
+ # macros are typically OK, so we allow use of "namespace {" on lines
+ # that end with backslashes.
+ if (file_extension == 'h'
+ and Search(r'\bnamespace\s*{', line)
+ and line[-1] != '\\'):
+ error(filename, linenum, 'build/namespaces', 4,
+ 'Do not use unnamed namespaces in header files. See '
+ 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
+ ' for more information.')
+
+
+def CheckGlobalStatic(filename, clean_lines, linenum, error):
+ """Check for unsafe global or static objects.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Match two lines at a time to support multiline declarations
+ if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
+ line += clean_lines.elided[linenum + 1].strip()
+
+ # Check for people declaring static/global STL strings at the top level.
+ # This is dangerous because the C++ language does not guarantee that
+ # globals with constructors are initialized before the first access.
+ match = Match(
+ r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
+ line)
+
+ # Remove false positives:
+ # - String pointers (as opposed to values).
+ # string *pointer
+ # const string *pointer
+ # string const *pointer
+ # string *const pointer
+ #
+ # - Functions and template specializations.
+ # string Function<Type>(...
+ # string Class<Type>::Method(...
+ #
+ # - Operators. These are matched separately because operator names
+ # cross non-word boundaries, and trying to match both operators
+ # and functions at the same time would decrease accuracy of
+ # matching identifiers.
+ # string Class::operator*()
+ if (match and
+ not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and
+ not Search(r'\boperator\W', line) and
+ not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(3))):
+ error(filename, linenum, 'runtime/string', 4,
+ 'For a static/global string constant, use a C style string instead: '
+ '"%schar %s[]".' %
+ (match.group(1), match.group(2)))
+
+ if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
+ error(filename, linenum, 'runtime/init', 4,
+ 'You seem to be initializing a member variable with itself.')
+
+
+def CheckPrintf(filename, clean_lines, linenum, error):
+ """Check for printf related issues.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # When snprintf is used, the second argument shouldn't be a literal.
+ match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
+ if match and match.group(2) != '0':
+ # If 2nd arg is zero, snprintf is used to calculate size.
+ error(filename, linenum, 'runtime/printf', 3,
+ 'If you can, use sizeof(%s) instead of %s as the 2nd arg '
+ 'to snprintf.' % (match.group(1), match.group(2)))
+
+ # Check if some verboten C functions are being used.
+ if Search(r'\bsprintf\s*\(', line):
+ error(filename, linenum, 'runtime/printf', 5,
+ 'Never use sprintf. Use snprintf instead.')
+ match = Search(r'\b(strcpy|strcat)\s*\(', line)
+ if match:
+ error(filename, linenum, 'runtime/printf', 4,
+ 'Almost always, snprintf is better than %s' % match.group(1))
+
+
+def IsDerivedFunction(clean_lines, linenum):
+ """Check if current line contains an inherited function.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ Returns:
+ True if current line contains a function with "override"
+ virt-specifier.
+ """
+ # Scan back a few lines for start of current function
+ for i in xrange(linenum, max(-1, linenum - 10), -1):
+ match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
+ if match:
+ # Look for "override" after the matching closing parenthesis
+ line, _, closing_paren = CloseExpression(
+ clean_lines, i, len(match.group(1)))
+ return (closing_paren >= 0 and
+ Search(r'\boverride\b', line[closing_paren:]))
+ return False
+
+
+def IsOutOfLineMethodDefinition(clean_lines, linenum):
+ """Check if current line contains an out-of-line method definition.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ Returns:
+ True if current line contains an out-of-line method definition.
+ """
+ # Scan back a few lines for start of current function
+ for i in xrange(linenum, max(-1, linenum - 10), -1):
+ if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
+ return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
+ return False
+
+
+def IsInitializerList(clean_lines, linenum):
+ """Check if current line is inside constructor initializer list.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ Returns:
+ True if current line appears to be inside constructor initializer
+ list, False otherwise.
+ """
+ for i in xrange(linenum, 1, -1):
+ line = clean_lines.elided[i]
+ if i == linenum:
+ remove_function_body = Match(r'^(.*)\{\s*$', line)
+ if remove_function_body:
+ line = remove_function_body.group(1)
+
+ if Search(r'\s:\s*\w+[({]', line):
+ # A lone colon tend to indicate the start of a constructor
+ # initializer list. It could also be a ternary operator, which
+ # also tend to appear in constructor initializer lists as
+ # opposed to parameter lists.
+ return True
+ if Search(r'\}\s*,\s*$', line):
+ # A closing brace followed by a comma is probably the end of a
+ # brace-initialized member in constructor initializer list.
+ return True
+ if Search(r'[{};]\s*$', line):
+ # Found one of the following:
+ # - A closing brace or semicolon, probably the end of the previous
+ # function.
+ # - An opening brace, probably the start of current class or namespace.
+ #
+ # Current line is probably not inside an initializer list since
+ # we saw one of those things without seeing the starting colon.
+ return False
+
+ # Got to the beginning of the file without seeing the start of
+ # constructor initializer list.
+ return False
+
+
+def CheckForNonConstReference(filename, clean_lines, linenum,
+ nesting_state, error):
+ """Check for non-const references.
+
+ Separate from CheckLanguage since it scans backwards from current
+ line, instead of scanning forward.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: The function to call with any errors found.
+ """
+ # Do nothing if there is no '&' on current line.
+ line = clean_lines.elided[linenum]
+ if '&' not in line:
+ return
+
+ # If a function is inherited, current function doesn't have much of
+ # a choice, so any non-const references should not be blamed on
+ # derived function.
+ if IsDerivedFunction(clean_lines, linenum):
+ return
+
+ # Don't warn on out-of-line method definitions, as we would warn on the
+ # in-line declaration, if it isn't marked with 'override'.
+ if IsOutOfLineMethodDefinition(clean_lines, linenum):
+ return
+
+ # Long type names may be broken across multiple lines, usually in one
+ # of these forms:
+ # LongType
+ # ::LongTypeContinued &identifier
+ # LongType::
+ # LongTypeContinued &identifier
+ # LongType<
+ # ...>::LongTypeContinued &identifier
+ #
+ # If we detected a type split across two lines, join the previous
+ # line to current line so that we can match const references
+ # accordingly.
+ #
+ # Note that this only scans back one line, since scanning back
+ # arbitrary number of lines would be expensive. If you have a type
+ # that spans more than 2 lines, please use a typedef.
+ if linenum > 1:
+ previous = None
+ if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
+ # previous_line\n + ::current_line
+ previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
+ clean_lines.elided[linenum - 1])
+ elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
+ # previous_line::\n + current_line
+ previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
+ clean_lines.elided[linenum - 1])
+ if previous:
+ line = previous.group(1) + line.lstrip()
+ else:
+ # Check for templated parameter that is split across multiple lines
+ endpos = line.rfind('>')
+ if endpos > -1:
+ (_, startline, startpos) = ReverseCloseExpression(
+ clean_lines, linenum, endpos)
+ if startpos > -1 and startline < linenum:
+ # Found the matching < on an earlier line, collect all
+ # pieces up to current line.
+ line = ''
+ for i in xrange(startline, linenum + 1):
+ line += clean_lines.elided[i].strip()
+
+ # Check for non-const references in function parameters. A single '&' may
+ # found in the following places:
+ # inside expression: binary & for bitwise AND
+ # inside expression: unary & for taking the address of something
+ # inside declarators: reference parameter
+ # We will exclude the first two cases by checking that we are not inside a
+ # function body, including one that was just introduced by a trailing '{'.
+ # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
+ if (nesting_state.previous_stack_top and
+ not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
+ isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
+ # Not at toplevel, not within a class, and not within a namespace
+ return
+
+ # Avoid initializer lists. We only need to scan back from the
+ # current line for something that starts with ':'.
+ #
+ # We don't need to check the current line, since the '&' would
+ # appear inside the second set of parentheses on the current line as
+ # opposed to the first set.
+ if linenum > 0:
+ for i in xrange(linenum - 1, max(0, linenum - 10), -1):
+ previous_line = clean_lines.elided[i]
+ if not Search(r'[),]\s*$', previous_line):
+ break
+ if Match(r'^\s*:\s+\S', previous_line):
+ return
+
+ # Avoid preprocessors
+ if Search(r'\\\s*$', line):
+ return
+
+ # Avoid constructor initializer lists
+ if IsInitializerList(clean_lines, linenum):
+ return
+
+ # We allow non-const references in a few standard places, like functions
+ # called "swap()" or iostream operators like "<<" or ">>". Do not check
+ # those function parameters.
+ #
+ # We also accept & in static_assert, which looks like a function but
+ # it's actually a declaration expression.
+ whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
+ r'operator\s*[<>][<>]|'
+ r'static_assert|COMPILE_ASSERT'
+ r')\s*\(')
+ if Search(whitelisted_functions, line):
+ return
+ elif not Search(r'\S+\([^)]*$', line):
+ # Don't see a whitelisted function on this line. Actually we
+ # didn't see any function name on this line, so this is likely a
+ # multi-line parameter list. Try a bit harder to catch this case.
+ for i in xrange(2):
+ if (linenum > i and
+ Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
+ return
+
+ decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body
+ for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
+ if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
+ error(filename, linenum, 'runtime/references', 2,
+ 'Is this a non-const reference? '
+ 'If so, make const or use a pointer: ' +
+ ReplaceAll(' *<', '<', parameter))
+
+
+def CheckCasts(filename, clean_lines, linenum, error):
+ """Various cast related checks.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Check to see if they're using an conversion function cast.
+ # I just try to capture the most common basic types, though there are more.
+ # Parameterless conversion functions, such as bool(), are allowed as they are
+ # probably a member operator declaration or default constructor.
+ match = Search(
+ r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b'
+ r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
+ r'(\([^)].*)', line)
+ expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
+ if match and not expecting_function:
+ matched_type = match.group(2)
+
+ # matched_new_or_template is used to silence two false positives:
+ # - New operators
+ # - Template arguments with function types
+ #
+ # For template arguments, we match on types immediately following
+ # an opening bracket without any spaces. This is a fast way to
+ # silence the common case where the function type is the first
+ # template argument. False negative with less-than comparison is
+ # avoided because those operators are usually followed by a space.
+ #
+ # function<double(double)> // bracket + no space = false positive
+ # value < double(42) // bracket + space = true positive
+ matched_new_or_template = match.group(1)
+
+ # Avoid arrays by looking for brackets that come after the closing
+ # parenthesis.
+ if Match(r'\([^()]+\)\s*\[', match.group(3)):
+ return
+
+ # Other things to ignore:
+ # - Function pointers
+ # - Casts to pointer types
+ # - Placement new
+ # - Alias declarations
+ matched_funcptr = match.group(3)
+ if (matched_new_or_template is None and
+ not (matched_funcptr and
+ (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
+ matched_funcptr) or
+ matched_funcptr.startswith('(*)'))) and
+ not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
+ not Search(r'new\(\S+\)\s*' + matched_type, line)):
+ error(filename, linenum, 'readability/casting', 4,
+ 'Using deprecated casting style. '
+ 'Use static_cast<%s>(...) instead' %
+ matched_type)
+
+ if not expecting_function:
+ CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
+ r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
+
+ # This doesn't catch all cases. Consider (const char * const)"hello".
+ #
+ # (char *) "foo" should always be a const_cast (reinterpret_cast won't
+ # compile).
+ if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast',
+ r'\((char\s?\*+\s?)\)\s*"', error):
+ pass
+ else:
+ # Check pointer casts for other than string constants
+ CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast',
+ r'\((\w+\s?\*+\s?)\)', error)
+
+ # In addition, we look for people taking the address of a cast. This
+ # is dangerous -- casts can assign to temporaries, so the pointer doesn't
+ # point where you think.
+ #
+ # Some non-identifier character is required before the '&' for the
+ # expression to be recognized as a cast. These are casts:
+ # expression = &static_cast<int*>(temporary());
+ # function(&(int*)(temporary()));
+ #
+ # This is not a cast:
+ # reference_type&(int* function_param);
+ match = Search(
+ r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
+ r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
+ if match:
+ # Try a better error message when the & is bound to something
+ # dereferenced by the casted pointer, as opposed to the casted
+ # pointer itself.
+ parenthesis_error = False
+ match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
+ if match:
+ _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
+ if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
+ _, y2, x2 = CloseExpression(clean_lines, y1, x1)
+ if x2 >= 0:
+ extended_line = clean_lines.elided[y2][x2:]
+ if y2 < clean_lines.NumLines() - 1:
+ extended_line += clean_lines.elided[y2 + 1]
+ if Match(r'\s*(?:->|\[)', extended_line):
+ parenthesis_error = True
+
+ if parenthesis_error:
+ error(filename, linenum, 'readability/casting', 4,
+ ('Are you taking an address of something dereferenced '
+ 'from a cast? Wrapping the dereferenced expression in '
+ 'parentheses will make the binding more obvious'))
+ else:
+ error(filename, linenum, 'runtime/casting', 4,
+ ('Are you taking an address of a cast? '
+ 'This is dangerous: could be a temp var. '
+ 'Take the address before doing the cast, rather than after'))
+
+
+def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
+ """Checks for a C-style cast by looking for the pattern.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ cast_type: The string for the C++ cast to recommend. This is either
+ reinterpret_cast, static_cast, or const_cast, depending.
+ pattern: The regular expression used to find C-style casts.
+ error: The function to call with any errors found.
+
+ Returns:
+ True if an error was emitted.
+ False otherwise.
+ """
+ line = clean_lines.elided[linenum]
+ match = Search(pattern, line)
+ if not match:
+ return False
+
+ # Exclude lines with keywords that tend to look like casts
+ context = line[0:match.start(1) - 1]
+ if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
+ return False
+
+ # Try expanding current context to see if we one level of
+ # parentheses inside a macro.
+ if linenum > 0:
+ for i in xrange(linenum - 1, max(0, linenum - 5), -1):
+ context = clean_lines.elided[i] + context
+ if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
+ return False
+
+ # operator++(int) and operator--(int)
+ if context.endswith(' operator++') or context.endswith(' operator--'):
+ return False
+
+ # A single unnamed argument for a function tends to look like old
+ # style cast. If we see those, don't issue warnings for deprecated
+ # casts, instead issue warnings for unnamed arguments where
+ # appropriate.
+ #
+ # These are things that we want warnings for, since the style guide
+ # explicitly require all parameters to be named:
+ # Function(int);
+ # Function(int) {
+ # ConstMember(int) const;
+ # ConstMember(int) const {
+ # ExceptionMember(int) throw (...);
+ # ExceptionMember(int) throw (...) {
+ # PureVirtual(int) = 0;
+ # [](int) -> bool {
+ #
+ # These are functions of some sort, where the compiler would be fine
+ # if they had named parameters, but people often omit those
+ # identifiers to reduce clutter:
+ # (FunctionPointer)(int);
+ # (FunctionPointer)(int) = value;
+ # Function((function_pointer_arg)(int))
+ # Function((function_pointer_arg)(int), int param)
+ # <TemplateArgument(int)>;
+ # <(FunctionPointerTemplateArgument)(int)>;
+ remainder = line[match.end(0):]
+ if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
+ remainder):
+ # Looks like an unnamed parameter.
+
+ # Don't warn on any kind of template arguments.
+ if Match(r'^\s*>', remainder):
+ return False
+
+ # Don't warn on assignments to function pointers, but keep warnings for
+ # unnamed parameters to pure virtual functions. Note that this pattern
+ # will also pass on assignments of "0" to function pointers, but the
+ # preferred values for those would be "nullptr" or "NULL".
+ matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder)
+ if matched_zero and matched_zero.group(1) != '0':
+ return False
+
+ # Don't warn on function pointer declarations. For this we need
+ # to check what came before the "(type)" string.
+ if Match(r'.*\)\s*$', line[0:match.start(0)]):
+ return False
+
+ # Don't warn if the parameter is named with block comments, e.g.:
+ # Function(int /*unused_param*/);
+ raw_line = clean_lines.raw_lines[linenum]
+ if '/*' in raw_line:
+ return False
+
+ # Passed all filters, issue warning here.
+ error(filename, linenum, 'readability/function', 3,
+ 'All parameters should be named in a function')
+ return True
+
+ # At this point, all that should be left is actual casts.
+ error(filename, linenum, 'readability/casting', 4,
+ 'Using C-style cast. Use %s<%s>(...) instead' %
+ (cast_type, match.group(1)))
+
+ return True
+
+
+def ExpectingFunctionArgs(clean_lines, linenum):
+ """Checks whether where function type arguments are expected.
+
+ Args:
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+
+ Returns:
+ True if the line at 'linenum' is inside something that expects arguments
+ of function types.
+ """
+ line = clean_lines.elided[linenum]
+ return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
+ (linenum >= 2 and
+ (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
+ clean_lines.elided[linenum - 1]) or
+ Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
+ clean_lines.elided[linenum - 2]) or
+ Search(r'\bstd::m?function\s*\<\s*$',
+ clean_lines.elided[linenum - 1]))))
+
+
+_HEADERS_CONTAINING_TEMPLATES = (
+ ('<deque>', ('deque',)),
+ ('<functional>', ('unary_function', 'binary_function',
+ 'plus', 'minus', 'multiplies', 'divides', 'modulus',
+ 'negate',
+ 'equal_to', 'not_equal_to', 'greater', 'less',
+ 'greater_equal', 'less_equal',
+ 'logical_and', 'logical_or', 'logical_not',
+ 'unary_negate', 'not1', 'binary_negate', 'not2',
+ 'bind1st', 'bind2nd',
+ 'pointer_to_unary_function',
+ 'pointer_to_binary_function',
+ 'ptr_fun',
+ 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
+ 'mem_fun_ref_t',
+ 'const_mem_fun_t', 'const_mem_fun1_t',
+ 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
+ 'mem_fun_ref',
+ )),
+ ('<limits>', ('numeric_limits',)),
+ ('<list>', ('list',)),
+ ('<map>', ('map', 'multimap',)),
+ ('<memory>', ('allocator',)),
+ ('<queue>', ('queue', 'priority_queue',)),
+ ('<set>', ('set', 'multiset',)),
+ ('<stack>', ('stack',)),
+ ('<string>', ('char_traits', 'basic_string',)),
+ ('<tuple>', ('tuple',)),
+ ('<utility>', ('pair',)),
+ ('<vector>', ('vector',)),
+
+ # gcc extensions.
+ # Note: std::hash is their hash, ::hash is our hash
+ ('<hash_map>', ('hash_map', 'hash_multimap',)),
+ ('<hash_set>', ('hash_set', 'hash_multiset',)),
+ ('<slist>', ('slist',)),
+ )
+
+_RE_PATTERN_STRING = re.compile(r'\bstring\b')
+
+_re_pattern_algorithm_header = []
+for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap',
+ 'transform'):
+ # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
+ # type::max().
+ _re_pattern_algorithm_header.append(
+ (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
+ _template,
+ '<algorithm>'))
+
+_re_pattern_templates = []
+for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
+ for _template in _templates:
+ _re_pattern_templates.append(
+ (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
+ _template + '<>',
+ _header))
+
+
+def FilesBelongToSameModule(filename_cc, filename_h):
+ """Check if these two filenames belong to the same module.
+
+ The concept of a 'module' here is a as follows:
+ foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
+ same 'module' if they are in the same directory.
+ some/path/public/xyzzy and some/path/internal/xyzzy are also considered
+ to belong to the same module here.
+
+ If the filename_cc contains a longer path than the filename_h, for example,
+ '/absolute/path/to/base/sysinfo.cc', and this file would include
+ 'base/sysinfo.h', this function also produces the prefix needed to open the
+ header. This is used by the caller of this function to more robustly open the
+ header file. We don't have access to the real include paths in this context,
+ so we need this guesswork here.
+
+ Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
+ according to this implementation. Because of this, this function gives
+ some false positives. This should be sufficiently rare in practice.
+
+ Args:
+ filename_cc: is the path for the .cc file
+ filename_h: is the path for the header path
+
+ Returns:
+ Tuple with a bool and a string:
+ bool: True if filename_cc and filename_h belong to the same module.
+ string: the additional prefix needed to open the header file.
+ """
+
+ if not filename_cc.endswith('.cc'):
+ return (False, '')
+ filename_cc = filename_cc[:-len('.cc')]
+ if filename_cc.endswith('_unittest'):
+ filename_cc = filename_cc[:-len('_unittest')]
+ elif filename_cc.endswith('_test'):
+ filename_cc = filename_cc[:-len('_test')]
+ filename_cc = filename_cc.replace('/public/', '/')
+ filename_cc = filename_cc.replace('/internal/', '/')
+
+ if not filename_h.endswith('.h'):
+ return (False, '')
+ filename_h = filename_h[:-len('.h')]
+ if filename_h.endswith('-inl'):
+ filename_h = filename_h[:-len('-inl')]
+ filename_h = filename_h.replace('/public/', '/')
+ filename_h = filename_h.replace('/internal/', '/')
+
+ files_belong_to_same_module = filename_cc.endswith(filename_h)
+ common_path = ''
+ if files_belong_to_same_module:
+ common_path = filename_cc[:-len(filename_h)]
+ return files_belong_to_same_module, common_path
+
+
+def UpdateIncludeState(filename, include_dict, io=codecs):
+ """Fill up the include_dict with new includes found from the file.
+
+ Args:
+ filename: the name of the header to read.
+ include_dict: a dictionary in which the headers are inserted.
+ io: The io factory to use to read the file. Provided for testability.
+
+ Returns:
+ True if a header was successfully added. False otherwise.
+ """
+ headerfile = None
+ try:
+ headerfile = io.open(filename, 'r', 'utf8', 'replace')
+ except IOError:
+ return False
+ linenum = 0
+ for line in headerfile:
+ linenum += 1
+ clean_line = CleanseComments(line)
+ match = _RE_PATTERN_INCLUDE.search(clean_line)
+ if match:
+ include = match.group(2)
+ include_dict.setdefault(include, linenum)
+ return True
+
+
+def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
+ io=codecs):
+ """Reports for missing stl includes.
+
+ This function will output warnings to make sure you are including the headers
+ necessary for the stl containers and functions that you use. We only give one
+ reason to include a header. For example, if you use both equal_to<> and
+ less<> in a .h file, only one (the latter in the file) of these will be
+ reported as a reason to include the <functional>.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ include_state: An _IncludeState instance.
+ error: The function to call with any errors found.
+ io: The IO factory to use to read the header file. Provided for unittest
+ injection.
+ """
+ required = {} # A map of header name to linenumber and the template entity.
+ # Example of required: { '<functional>': (1219, 'less<>') }
+
+ for linenum in xrange(clean_lines.NumLines()):
+ line = clean_lines.elided[linenum]
+ if not line or line[0] == '#':
+ continue
+
+ # String is special -- it is a non-templatized type in STL.
+ matched = _RE_PATTERN_STRING.search(line)
+ if matched:
+ # Don't warn about strings in non-STL namespaces:
+ # (We check only the first match per line; good enough.)
+ prefix = line[:matched.start()]
+ if prefix.endswith('std::') or not prefix.endswith('::'):
+ required['<string>'] = (linenum, 'string')
+
+ for pattern, template, header in _re_pattern_algorithm_header:
+ if pattern.search(line):
+ required[header] = (linenum, template)
+
+ # The following function is just a speed up, no semantics are changed.
+ if not '<' in line: # Reduces the cpu time usage by skipping lines.
+ continue
+
+ for pattern, template, header in _re_pattern_templates:
+ if pattern.search(line):
+ required[header] = (linenum, template)
+
+ # The policy is that if you #include something in foo.h you don't need to
+ # include it again in foo.cc. Here, we will look at possible includes.
+ # Let's flatten the include_state include_list and copy it into a dictionary.
+ include_dict = dict([item for sublist in include_state.include_list
+ for item in sublist])
+
+ # Did we find the header for this file (if any) and successfully load it?
+ header_found = False
+
+ # Use the absolute path so that matching works properly.
+ abs_filename = FileInfo(filename).FullName()
+
+ # For Emacs's flymake.
+ # If cpplint is invoked from Emacs's flymake, a temporary file is generated
+ # by flymake and that file name might end with '_flymake.cc'. In that case,
+ # restore original file name here so that the corresponding header file can be
+ # found.
+ # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
+ # instead of 'foo_flymake.h'
+ abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
+
+ # include_dict is modified during iteration, so we iterate over a copy of
+ # the keys.
+ header_keys = include_dict.keys()
+ for header in header_keys:
+ (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
+ fullpath = common_path + header
+ if same_module and UpdateIncludeState(fullpath, include_dict, io):
+ header_found = True
+
+ # If we can't find the header file for a .cc, assume it's because we don't
+ # know where to look. In that case we'll give up as we're not sure they
+ # didn't include it in the .h file.
+ # TODO(unknown): Do a better job of finding .h files so we are confident that
+ # not having the .h file means there isn't one.
+ if filename.endswith('.cc') and not header_found:
+ return
+
+ # All the lines have been processed, report the errors found.
+ for required_header_unstripped in required:
+ template = required[required_header_unstripped][1]
+ if required_header_unstripped.strip('<>"') not in include_dict:
+ error(filename, required[required_header_unstripped][0],
+ 'build/include_what_you_use', 4,
+ 'Add #include ' + required_header_unstripped + ' for ' + template)
+
+
+_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
+
+
+def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
+ """Check that make_pair's template arguments are deduced.
+
+ G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
+ specified explicitly, and such use isn't intended in any case.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+ match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
+ if match:
+ error(filename, linenum, 'build/explicit_make_pair',
+ 4, # 4 = high confidence
+ 'For C++11-compatibility, omit template arguments from make_pair'
+ ' OR use pair directly OR if appropriate, construct a pair directly')
+
+
+def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error):
+ """Check that default lambda captures are not used.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # A lambda introducer specifies a default capture if it starts with "[="
+ # or if it starts with "[&" _not_ followed by an identifier.
+ match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line)
+ if match:
+ # Found a potential error, check what comes after the lambda-introducer.
+ # If it's not open parenthesis (for lambda-declarator) or open brace
+ # (for compound-statement), it's not a lambda.
+ line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1)))
+ if pos >= 0 and Match(r'^\s*[{(]', line[pos:]):
+ error(filename, linenum, 'build/c++11',
+ 4, # 4 = high confidence
+ 'Default lambda captures are an unapproved C++ feature.')
+
+
+def CheckRedundantVirtual(filename, clean_lines, linenum, error):
+ """Check if line contains a redundant "virtual" function-specifier.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ # Look for "virtual" on current line.
+ line = clean_lines.elided[linenum]
+ virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line)
+ if not virtual: return
+
+ # Ignore "virtual" keywords that are near access-specifiers. These
+ # are only used in class base-specifier and do not apply to member
+ # functions.
+ if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
+ Match(r'^\s+(public|protected|private)\b', virtual.group(3))):
+ return
+
+ # Ignore the "virtual" keyword from virtual base classes. Usually
+ # there is a column on the same line in these cases (virtual base
+ # classes are rare in google3 because multiple inheritance is rare).
+ if Match(r'^.*[^:]:[^:].*$', line): return
+
+ # Look for the next opening parenthesis. This is the start of the
+ # parameter list (possibly on the next line shortly after virtual).
+ # TODO(unknown): doesn't work if there are virtual functions with
+ # decltype() or other things that use parentheses, but csearch suggests
+ # that this is rare.
+ end_col = -1
+ end_line = -1
+ start_col = len(virtual.group(2))
+ for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
+ line = clean_lines.elided[start_line][start_col:]
+ parameter_list = Match(r'^([^(]*)\(', line)
+ if parameter_list:
+ # Match parentheses to find the end of the parameter list
+ (_, end_line, end_col) = CloseExpression(
+ clean_lines, start_line, start_col + len(parameter_list.group(1)))
+ break
+ start_col = 0
+
+ if end_col < 0:
+ return # Couldn't find end of parameter list, give up
+
+ # Look for "override" or "final" after the parameter list
+ # (possibly on the next few lines).
+ for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
+ line = clean_lines.elided[i][end_col:]
+ match = Search(r'\b(override|final)\b', line)
+ if match:
+ error(filename, linenum, 'readability/inheritance', 4,
+ ('"virtual" is redundant since function is '
+ 'already declared as "%s"' % match.group(1)))
+
+ # Set end_col to check whole lines after we are done with the
+ # first line.
+ end_col = 0
+ if Search(r'[^\w]\s*$', line):
+ break
+
+
+def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
+ """Check if line contains a redundant "override" or "final" virt-specifier.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ # Look for closing parenthesis nearby. We need one to confirm where
+ # the declarator ends and where the virt-specifier starts to avoid
+ # false positives.
+ line = clean_lines.elided[linenum]
+ declarator_end = line.rfind(')')
+ if declarator_end >= 0:
+ fragment = line[declarator_end:]
+ else:
+ if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0:
+ fragment = line
+ else:
+ return
+
+ # Check that at most one of "override" or "final" is present, not both
+ if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment):
+ error(filename, linenum, 'readability/inheritance', 4,
+ ('"override" is redundant since function is '
+ 'already declared as "final"'))
+
+
+
+
+# Returns true if we are at a new block, and it is directly
+# inside of a namespace.
+def IsBlockInNameSpace(nesting_state, is_forward_declaration):
+ """Checks that the new block is directly in a namespace.
+
+ Args:
+ nesting_state: The _NestingState object that contains info about our state.
+ is_forward_declaration: If the class is a forward declared class.
+ Returns:
+ Whether or not the new block is directly in a namespace.
+ """
+ if is_forward_declaration:
+ if len(nesting_state.stack) >= 1 and (
+ isinstance(nesting_state.stack[-1], _NamespaceInfo)):
+ return True
+ else:
+ return False
+
+ return (len(nesting_state.stack) > 1 and
+ nesting_state.stack[-1].check_namespace_indentation and
+ isinstance(nesting_state.stack[-2], _NamespaceInfo))
+
+
+def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
+ raw_lines_no_comments, linenum):
+ """This method determines if we should apply our namespace indentation check.
+
+ Args:
+ nesting_state: The current nesting state.
+ is_namespace_indent_item: If we just put a new class on the stack, True.
+ If the top of the stack is not a class, or we did not recently
+ add the class, False.
+ raw_lines_no_comments: The lines without the comments.
+ linenum: The current line number we are processing.
+
+ Returns:
+ True if we should apply our namespace indentation check. Currently, it
+ only works for classes and namespaces inside of a namespace.
+ """
+
+ is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments,
+ linenum)
+
+ if not (is_namespace_indent_item or is_forward_declaration):
+ return False
+
+ # If we are in a macro, we do not want to check the namespace indentation.
+ if IsMacroDefinition(raw_lines_no_comments, linenum):
+ return False
+
+ return IsBlockInNameSpace(nesting_state, is_forward_declaration)
+
+
+# Call this method if the line is directly inside of a namespace.
+# If the line above is blank (excluding comments) or the start of
+# an inner namespace, it cannot be indented.
+def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum,
+ error):
+ line = raw_lines_no_comments[linenum]
+ if Match(r'^\s+', line):
+ error(filename, linenum, 'runtime/indentation_namespace', 4,
+ 'Do not indent within a namespace')
+
+
+def ProcessLine(filename, file_extension, clean_lines, line,
+ include_state, function_state, nesting_state, error,
+ extra_check_functions=[]):
+ """Processes a single line in the file.
+
+ Args:
+ filename: Filename of the file that is being processed.
+ file_extension: The extension (dot not included) of the file.
+ clean_lines: An array of strings, each representing a line of the file,
+ with comments stripped.
+ line: Number of line being processed.
+ include_state: An _IncludeState instance in which the headers are inserted.
+ function_state: A _FunctionState instance which counts function lines, etc.
+ nesting_state: A NestingState instance which maintains information about
+ the current stack of nested blocks being parsed.
+ error: A callable to which errors are reported, which takes 4 arguments:
+ filename, line number, error level, and message
+ extra_check_functions: An array of additional check functions that will be
+ run on each source line. Each function takes 4
+ arguments: filename, clean_lines, line, error
+ """
+ raw_lines = clean_lines.raw_lines
+ ParseNolintSuppressions(filename, raw_lines[line], line, error)
+ nesting_state.Update(filename, clean_lines, line, error)
+ CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
+ error)
+ if nesting_state.InAsmBlock(): return
+ CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
+ CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
+ CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
+ CheckLanguage(filename, clean_lines, line, file_extension, include_state,
+ nesting_state, error)
+ CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
+ CheckForNonStandardConstructs(filename, clean_lines, line,
+ nesting_state, error)
+ CheckVlogArguments(filename, clean_lines, line, error)
+ CheckPosixThreading(filename, clean_lines, line, error)
+ CheckInvalidIncrement(filename, clean_lines, line, error)
+ CheckMakePairUsesDeduction(filename, clean_lines, line, error)
+ CheckDefaultLambdaCaptures(filename, clean_lines, line, error)
+ CheckRedundantVirtual(filename, clean_lines, line, error)
+ CheckRedundantOverrideOrFinal(filename, clean_lines, line, error)
+ for check_fn in extra_check_functions:
+ check_fn(filename, clean_lines, line, error)
+
+def FlagCxx11Features(filename, clean_lines, linenum, error):
+ """Flag those c++11 features that we only allow in certain places.
+
+ Args:
+ filename: The name of the current file.
+ clean_lines: A CleansedLines instance containing the file.
+ linenum: The number of the line to check.
+ error: The function to call with any errors found.
+ """
+ line = clean_lines.elided[linenum]
+
+ # Flag unapproved C++11 headers.
+ include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
+ if include and include.group(1) in ('cfenv',
+ 'condition_variable',
+ 'fenv.h',
+ 'future',
+ 'mutex',
+ 'thread',
+ 'chrono',
+ 'ratio',
+ 'regex',
+ 'system_error',
+ ):
+ error(filename, linenum, 'build/c++11', 5,
+ ('<%s> is an unapproved C++11 header.') % include.group(1))
+
+ # The only place where we need to worry about C++11 keywords and library
+ # features in preprocessor directives is in macro definitions.
+ if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
+
+ # These are classes and free functions. The classes are always
+ # mentioned as std::*, but we only catch the free functions if
+ # they're not found by ADL. They're alphabetical by header.
+ for top_name in (
+ # type_traits
+ 'alignment_of',
+ 'aligned_union',
+ ):
+ if Search(r'\bstd::%s\b' % top_name, line):
+ error(filename, linenum, 'build/c++11', 5,
+ ('std::%s is an unapproved C++11 class or function. Send c-style '
+ 'an example of where it would make your code more readable, and '
+ 'they may let you use it.') % top_name)
+
+
+def ProcessFileData(filename, file_extension, lines, error,
+ extra_check_functions=[]):
+ """Performs lint checks and reports any errors to the given error function.
+
+ Args:
+ filename: Filename of the file that is being processed.
+ file_extension: The extension (dot not included) of the file.
+ lines: An array of strings, each representing a line of the file, with the
+ last element being empty if the file is terminated with a newline.
+ error: A callable to which errors are reported, which takes 4 arguments:
+ filename, line number, error level, and message
+ extra_check_functions: An array of additional check functions that will be
+ run on each source line. Each function takes 4
+ arguments: filename, clean_lines, line, error
+ """
+ lines = (['// marker so line numbers and indices both start at 1'] + lines +
+ ['// marker so line numbers end in a known way'])
+
+ include_state = _IncludeState()
+ function_state = _FunctionState()
+ nesting_state = NestingState()
+
+ ResetNolintSuppressions()
+
+ CheckForCopyright(filename, lines, error)
+
+ RemoveMultiLineComments(filename, lines, error)
+ clean_lines = CleansedLines(lines)
+
+ if file_extension == 'h':
+ CheckForHeaderGuard(filename, clean_lines, error)
+
+ for line in xrange(clean_lines.NumLines()):
+ ProcessLine(filename, file_extension, clean_lines, line,
+ include_state, function_state, nesting_state, error,
+ extra_check_functions)
+ FlagCxx11Features(filename, clean_lines, line, error)
+ nesting_state.CheckCompletedBlocks(filename, error)
+
+ CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
+
+ # Check that the .cc file has included its header if it exists.
+ if file_extension == 'cc':
+ CheckHeaderFileIncluded(filename, include_state, error)
+
+ # We check here rather than inside ProcessLine so that we see raw
+ # lines rather than "cleaned" lines.
+ CheckForBadCharacters(filename, lines, error)
+
+ CheckForNewlineAtEOF(filename, lines, error)
+
+def ProcessConfigOverrides(filename):
+ """ Loads the configuration files and processes the config overrides.
+
+ Args:
+ filename: The name of the file being processed by the linter.
+
+ Returns:
+ False if the current |filename| should not be processed further.
+ """
+
+ abs_filename = os.path.abspath(filename)
+ cfg_filters = []
+ keep_looking = True
+ while keep_looking:
+ abs_path, base_name = os.path.split(abs_filename)
+ if not base_name:
+ break # Reached the root directory.
+
+ cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
+ abs_filename = abs_path
+ if not os.path.isfile(cfg_file):
+ continue
+
+ try:
+ with open(cfg_file) as file_handle:
+ for line in file_handle:
+ line, _, _ = line.partition('#') # Remove comments.
+ if not line.strip():
+ continue
+
+ name, _, val = line.partition('=')
+ name = name.strip()
+ val = val.strip()
+ if name == 'set noparent':
+ keep_looking = False
+ elif name == 'filter':
+ cfg_filters.append(val)
+ elif name == 'exclude_files':
+ # When matching exclude_files pattern, use the base_name of
+ # the current file name or the directory name we are processing.
+ # For example, if we are checking for lint errors in /foo/bar/baz.cc
+ # and we found the .cfg file at /foo/CPPLINT.cfg, then the config
+ # file's "exclude_files" filter is meant to be checked against "bar"
+ # and not "baz" nor "bar/baz.cc".
+ if base_name:
+ pattern = re.compile(val)
+ if pattern.match(base_name):
+ sys.stderr.write('Ignoring "%s": file excluded by "%s". '
+ 'File path component "%s" matches '
+ 'pattern "%s"\n' %
+ (filename, cfg_file, base_name, val))
+ return False
+ elif name == 'linelength':
+ global _line_length
+ try:
+ _line_length = int(val)
+ except ValueError:
+ sys.stderr.write('Line length must be numeric.')
+ else:
+ sys.stderr.write(
+ 'Invalid configuration option (%s) in file %s\n' %
+ (name, cfg_file))
+
+ except IOError:
+ sys.stderr.write(
+ "Skipping config file '%s': Can't open for reading\n" % cfg_file)
+ keep_looking = False
+
+ # Apply all the accumulated filters in reverse order (top-level directory
+ # config options having the least priority).
+ for filter in reversed(cfg_filters):
+ _AddFilters(filter)
+
+ return True
+
+
+def ProcessFile(filename, vlevel, extra_check_functions=[]):
+ """Does google-lint on a single file.
+
+ Args:
+ filename: The name of the file to parse.
+
+ vlevel: The level of errors to report. Every error of confidence
+ >= verbose_level will be reported. 0 is a good default.
+
+ extra_check_functions: An array of additional check functions that will be
+ run on each source line. Each function takes 4
+ arguments: filename, clean_lines, line, error
+ """
+
+ _SetVerboseLevel(vlevel)
+ _BackupFilters()
+
+ if not ProcessConfigOverrides(filename):
+ _RestoreFilters()
+ return
+
+ lf_lines = []
+ crlf_lines = []
+ try:
+ # Support the UNIX convention of using "-" for stdin. Note that
+ # we are not opening the file with universal newline support
+ # (which codecs doesn't support anyway), so the resulting lines do
+ # contain trailing '\r' characters if we are reading a file that
+ # has CRLF endings.
+ # If after the split a trailing '\r' is present, it is removed
+ # below.
+ if filename == '-':
+ lines = codecs.StreamReaderWriter(sys.stdin,
+ codecs.getreader('utf8'),
+ codecs.getwriter('utf8'),
+ 'replace').read().split('\n')
+ else:
+ lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
+
+ # Remove trailing '\r'.
+ # The -1 accounts for the extra trailing blank line we get from split()
+ for linenum in range(len(lines) - 1):
+ if lines[linenum].endswith('\r'):
+ lines[linenum] = lines[linenum].rstrip('\r')
+ crlf_lines.append(linenum + 1)
+ else:
+ lf_lines.append(linenum + 1)
+
+ except IOError:
+ sys.stderr.write(
+ "Skipping input '%s': Can't open for reading\n" % filename)
+ _RestoreFilters()
+ return
+
+ # Note, if no dot is found, this will give the entire filename as the ext.
+ file_extension = filename[filename.rfind('.') + 1:]
+
+ # When reading from stdin, the extension is unknown, so no cpplint tests
+ # should rely on the extension.
+ if filename != '-' and file_extension not in _valid_extensions:
+ sys.stderr.write('Ignoring %s; not a valid file name '
+ '(%s)\n' % (filename, ', '.join(_valid_extensions)))
+ else:
+ ProcessFileData(filename, file_extension, lines, Error,
+ extra_check_functions)
+
+ # If end-of-line sequences are a mix of LF and CR-LF, issue
+ # warnings on the lines with CR.
+ #
+ # Don't issue any warnings if all lines are uniformly LF or CR-LF,
+ # since critique can handle these just fine, and the style guide
+ # doesn't dictate a particular end of line sequence.
+ #
+ # We can't depend on os.linesep to determine what the desired
+ # end-of-line sequence should be, since that will return the
+ # server-side end-of-line sequence.
+ if lf_lines and crlf_lines:
+ # Warn on every line with CR. An alternative approach might be to
+ # check whether the file is mostly CRLF or just LF, and warn on the
+ # minority, we bias toward LF here since most tools prefer LF.
+ for linenum in crlf_lines:
+ Error(filename, linenum, 'whitespace/newline', 1,
+ 'Unexpected \\r (^M) found; better to use only \\n')
+
+ sys.stderr.write('Done processing %s\n' % filename)
+ _RestoreFilters()
+
+
+def PrintUsage(message):
+ """Prints a brief usage string and exits, optionally with an error message.
+
+ Args:
+ message: The optional error message.
+ """
+ sys.stderr.write(_USAGE)
+ if message:
+ sys.exit('\nFATAL ERROR: ' + message)
+ else:
+ sys.exit(1)
+
+
+def PrintCategories():
+ """Prints a list of all the error-categories used by error messages.
+
+ These are the categories used to filter messages via --filter.
+ """
+ sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES))
+ sys.exit(0)
+
+
+def ParseArguments(args):
+ """Parses the command line arguments.
+
+ This may set the output format and verbosity level as side-effects.
+
+ Args:
+ args: The command line arguments:
+
+ Returns:
+ The list of filenames to lint.
+ """
+ try:
+ (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
+ 'counting=',
+ 'filter=',
+ 'root=',
+ 'linelength=',
+ 'extensions='])
+ except getopt.GetoptError:
+ PrintUsage('Invalid arguments.')
+
+ verbosity = _VerboseLevel()
+ output_format = _OutputFormat()
+ filters = ''
+ counting_style = ''
+
+ for (opt, val) in opts:
+ if opt == '--help':
+ PrintUsage(None)
+ elif opt == '--output':
+ if val not in ('emacs', 'vs7', 'eclipse'):
+ PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
+ output_format = val
+ elif opt == '--verbose':
+ verbosity = int(val)
+ elif opt == '--filter':
+ filters = val
+ if not filters:
+ PrintCategories()
+ elif opt == '--counting':
+ if val not in ('total', 'toplevel', 'detailed'):
+ PrintUsage('Valid counting options are total, toplevel, and detailed')
+ counting_style = val
+ elif opt == '--root':
+ global _root
+ _root = val
+ elif opt == '--linelength':
+ global _line_length
+ try:
+ _line_length = int(val)
+ except ValueError:
+ PrintUsage('Line length must be digits.')
+ elif opt == '--extensions':
+ global _valid_extensions
+ try:
+ _valid_extensions = set(val.split(','))
+ except ValueError:
+ PrintUsage('Extensions must be comma seperated list.')
+
+ if not filenames:
+ PrintUsage('No files were specified.')
+
+ _SetOutputFormat(output_format)
+ _SetVerboseLevel(verbosity)
+ _SetFilters(filters)
+ _SetCountingStyle(counting_style)
+
+ return filenames
+
+
+def main():
+ filenames = ParseArguments(sys.argv[1:])
+
+ # Change stderr to write with replacement characters so we don't die
+ # if we try to print something containing non-ASCII characters.
+ sys.stderr = codecs.StreamReaderWriter(sys.stderr,
+ codecs.getreader('utf8'),
+ codecs.getwriter('utf8'),
+ 'replace')
+
+ _cpplint_state.ResetErrorCounts()
+ for filename in filenames:
+ ProcessFile(filename, _cpplint_state.verbose_level)
+ _cpplint_state.PrintErrorCounts()
+
+ sys.exit(_cpplint_state.error_count > 0)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/doit b/tools/doit
index e31cb03..012491b 100755
--- a/tools/doit
+++ b/tools/doit
@@ -11,8 +11,9 @@ cd build
cmake -DBUILD_LATEX=OFF -DWITH_DOC=ON -DWITH_DD=ON ..
#cmake -DWITH_DD=ON ..
make all doc && sudo make install && (cd ..; tools/test-runner.pl -clean)
-rsync -a doc/html/* /u/www/html/pgr2-doc/.
-ln -sf /u/www/html/pgr2-doc/. /u/www/html/pgr2-doc/dev
+mkdir -p /u/www/imaptools/docs/pgr2-doc/
+rsync -a doc/html/* /u/www/imaptools/docs/pgr2-doc/.
+ln -sf /u/www/imaptools/docs/pgr2-doc/. /u/www/imaptools/docs/pgr2-doc/dev
gzip -c doc/man/en/pgrouting.7 > doc/man/en/pgrouting.7.gz
for x in `ls doc/latex` ; do
mkdir -p /u/www/html/pgr2-doc/$x/.
diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile
new file mode 100644
index 0000000..52e683f
--- /dev/null
+++ b/tools/doxygen/Doxyfile
@@ -0,0 +1,2312 @@
+# Doxyfile 1.8.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "pgRouting"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = 2.1
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "pgRouting extends the PostGIS / PostgreSQL geospatial database to provide geospatial routing functionality."
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO = "../../doc/static/images/pgrouting-logo.png"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ../../build/doxy/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = YES
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = YES
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ../..
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = ../../tools ../../doc ../../build ../../cmake ../../.tx
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = */notUsed/*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH = ../../doc/static/images/developers/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = ../README.md
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = VICKY
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS = ../doc/images/
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/tools/doxygen/DoxygenLayout.xml b/tools/doxygen/DoxygenLayout.xml
new file mode 100644
index 0000000..b7c9586
--- /dev/null
+++ b/tools/doxygen/DoxygenLayout.xml
@@ -0,0 +1,194 @@
+<doxygenlayout version="1.0">
+ <!-- Generated by doxygen 1.8.7 -->
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="pages" visible="yes" title="" intro=""/>
+ <tab type="modules" visible="yes" title="" intro=""/>
+ <tab type="namespaces" visible="yes" title="">
+ <tab type="namespacelist" visible="yes" title="" intro=""/>
+ <tab type="namespacemembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="classes" visible="yes" title="">
+ <tab type="classlist" visible="yes" title="" intro=""/>
+ <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="hierarchy" visible="yes" title="" intro=""/>
+ <tab type="classmembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="files" visible="yes" title="">
+ <tab type="filelist" visible="yes" title="" intro=""/>
+ <tab type="globals" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="examples" visible="yes" title="" intro=""/>
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <allmemberslink visible="yes"/>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="yes"/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/tools/doxygen/Makefile b/tools/doxygen/Makefile
new file mode 100644
index 0000000..4dc7835
--- /dev/null
+++ b/tools/doxygen/Makefile
@@ -0,0 +1,5 @@
+all: doxygen
+
+doxygen:
+ mkdir -p ../../build/doxy/
+ doxygen
diff --git a/tools/mk-signature-file b/tools/mk-signature-file
new file mode 100755
index 0000000..271e09c
--- /dev/null
+++ b/tools/mk-signature-file
@@ -0,0 +1,156 @@
+#!/usr/bin/perl -w
+eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
+ if 0; #$running_under_some_shell
+
+# -------------------------------------------------------------
+# Usage: mk-signature-file <version>
+#
+# Author: Stephen Woodbridge
+# Date: 2015-07-25
+# License: MIT-X
+# -------------------------------------------------------------
+# Description
+#
+# This script read a file from lib/pgrouting--<version>.sql
+# that should be the sql for the postgresql extension.
+# It parses this file and extracts the signatures for the TYPES and
+# FUNCTIONS and writes them to the output file
+# lib/pgrouting--<version>.sig
+#
+# This is part of the automated pgRouting extension update
+# system that PostgreSQL require a collection of files that define
+# how to update an old version of pgRouting to the current version
+# using "ALTER EXTENSION pgrouting UPDATE TO <version>;"
+# The lib/pgrouting--<current_version>.sig and the update scripts
+# are automatically generated when when cmake is run. You don't
+# need to run this script manually.
+#
+# See also tools/build-extension-update-files
+# ------------------------------------------------------------
+
+use strict;
+use Data::Dumper;
+use Cwd qw(cwd chdir);
+
+my $DEBUG = 0;
+
+sub Usage {
+ die "Usage: mk-signature-file <version>\n";
+}
+
+# get the version from the commandline
+# cmake provides the version when it is run
+my $version = shift @ARGV || Usage();
+
+# generate the input and output file names
+my $sql = "lib/pgrouting--$version.sql";
+my $sig = "lib/pgrouting--$version.sig";
+
+die "ERROR: File '$sql' does not exist!\n"
+ unless -f $sql;
+
+# read the inpput file and parse it into signatures
+# for both types and functions
+my ($types, $funcs) = parse_signatures( $sql );
+
+# create and write the output file
+open(SIG, ">$sig") || die "ERROR: Failed to create '$sig' : $!\n";
+print SIG "#VERSION pgrouting $version\n";
+print SIG "#TYPES\n";
+print SIG join("\n", @{$types}), "\n";
+print SIG "#FUNCTIONS\n";
+print SIG join("\n", @{$funcs}), "\n";
+close(SIG);
+
+exit 0;
+
+# open the input file
+# manipulate it with regular expression to extract what we need
+sub parse_signatures {
+ my $file = shift;
+
+ # open and read the file into an array and convert it to one big string
+ my %sigs = ();
+ open(IN, $file) || die "ERROR: '$file' does not exist!\n";
+ my @data = <IN>;
+ close(IN);
+ my $data = join('', @data);
+
+ # manipulate the data with regular expressions
+
+ # delete C style comments
+ $data =~ s{
+ /\*
+ .*?
+ \*/
+ } []gsx;
+ # delete sql comments
+ $data =~ s/--[^\n]*\n//gs;
+
+ # extract TYPEs
+
+ # extract all "create type <name> as (<column_definition>, ...)"
+ # and sort them
+ my @types = $data =~ /create\s+type\s+(\w+\s+as\s*\([^\)]+\))/igs;
+ @types = sort @types;
+
+ # clean up types
+ for (my $i=0; $i<@types; $i++) {
+ # remove the "AS " phrase
+ $types[$i] =~ s/\bas\s*\(/\(/is;
+ # compress multiple white spaces into a single <space>
+ $types[$i] =~ s/\s+/ /gs;
+ # remove <space> before and after characters ",()"
+ $types[$i] =~ s/\s*([,\(\)])\s*/$1/gs;
+ # search for "<name> <type>[,)] and remove <name>
+ $types[$i] =~ s/\b(\w+)\s([^,\)]+)([,\)])/$2$3/gs;
+ }
+
+ # extract FUNCTIONs
+
+ # extract all "create or replace function <name>(<args>) returns"
+ # and sort them
+ my @funcs = $data =~ /create\s+or\s+replace\s+function\s+(\w+\s*\([^\)]+\))\s*RETURNS/igs;
+ @funcs = sort @funcs;
+
+ # clean up functions
+ for (my $i=0; $i<@funcs; $i++) {
+ # compress multiple white spaces into a single <space>
+ $funcs[$i] =~ s/\s+/ /gs;
+ # remove DEFAULT clauses
+ $funcs[$i] =~ s/\sdefault\s*((?:\()[^\)]+\)|[^\(\),]+)//ig;
+ # remove argument names and keep IN|OUT and type name
+ $funcs[$i] =~ s/(IN|OUT)\s(\w+)\s([^,\)]+)/$1 $3/ig;
+ # remove <space> following "("
+ $funcs[$i] =~ s/\(\s+/(/g;
+ # remove <space> following ","
+ $funcs[$i] =~ s/,\s+/,/g;
+ # handle cleanup of more complex arguments
+ $funcs[$i] = parse_function_args($funcs[$i]);
+ }
+
+ print Data::Dumper->Dump([\@types, \@funcs], ['types', 'funcs']) if $DEBUG;
+
+ return (\@types, \@funcs);
+}
+
+
+sub parse_function_args {
+ my $str = shift;
+
+ # convert it to lowercase
+ $str = lc($str);
+
+ # split arguments based ","
+ my @parts = split /,/, $str;
+ foreach my $p (@parts) {
+ # if we handled it above skip over it
+ next if $p =~ /\b(in|out)\s(\w+)/;
+ # if we still have <name> <type> then remove <name>
+ $p =~ s/\b(\w+)\s(\w+)/$2/;
+ }
+
+ # put all the parts back into a string
+ return join(',', @parts);
+}
+
diff --git a/tools/sigs/pgrouting--2.0.0.sig b/tools/sigs/pgrouting--2.0.0.sig
new file mode 100644
index 0000000..cea030e
--- /dev/null
+++ b/tools/sigs/pgrouting--2.0.0.sig
@@ -0,0 +1,36 @@
+#VERSION pgrouting 2.0.0
+#TYPES
+pgr_costResult(integer,integer,integer,float8)
+pgr_costResult3(integer,integer,integer,integer,float8)
+pgr_geomResult(integer,integer,integer,geometry)
+#FUNCTIONS
+pgr_alphashape(text,out float8,out float8)
+pgr_analyzeoneway(text,text[],text[],text[],text[],boolean,text,text,text)
+pgr_analyzegraph(text,double precision,text,text,text,text,text)
+pgr_apspjohnson(text)
+pgr_apspwarshall(text,boolean,boolean)
+pgr_astar(text,integer,integer,boolean,boolean)
+pgr_bdastar(text,integer,integer,boolean,boolean)
+pgr_bddijkstra(text,integer,integer,boolean,boolean)
+pgr_createtopology(text,double precision,text,text,text,text,text)
+pgr_createverticestable(text,text,text,text,text)
+pgr_dijkstra(text,integer,integer,boolean,boolean)
+pgr_drivingdistance(text,integer,float8,boolean,boolean)
+pgr_endpoint(geometry)
+pgr_getcolumnname(text,text)
+pgr_gettablename(in text,out text,out text)
+pgr_iscolumnintable(text,text)
+pgr_kdijkstracost(text,integer,integer array,boolean,boolean)
+pgr_kdijkstrapath(text,integer,integer array,boolean,boolean)
+pgr_ksp(text,integer,integer,integer,boolean)
+pgr_makedistancematrix(text,out double precision[],out integer[])
+pgr_nodenetwork(text,double precision,text,text,text)
+pgr_pointtoid(geometry,double precision,text,integer)
+pgr_pointsaspolygon(varchar)
+pgr_quote_ident(text)
+pgr_startpoint(geometry)
+pgr_trsp(text,integer,float8,integer,float8,boolean,boolean,text)
+pgr_trsp(text,integer,integer,boolean,boolean,text)
+pgr_tsp(float8[][],integer,integer,out integer,out integer)
+pgr_tsp(text,integer,integer)
+pgr_versionless(text,text)
diff --git a/tools/sigs/pgrouting--2.1.0.sig b/tools/sigs/pgrouting--2.1.0.sig
new file mode 100644
index 0000000..b33d132
--- /dev/null
+++ b/tools/sigs/pgrouting--2.1.0.sig
@@ -0,0 +1,80 @@
+#VERSION pgrouting 2.1.0
+#TYPES
+pgr_costResult(integer,integer,integer,float8)
+pgr_costResult3(integer,integer,integer,integer,float8)
+pgr_geomResult(integer,integer,integer,geometry)
+#FUNCTIONS
+_pgr_checkverttab(text,text[],in int,in text,out text,out text)
+_pgr_createindex(text,text,text,text,in int,in text)
+_pgr_createindex(text,text,text,text,in int,in text)
+_pgr_createindex(text,text,text,in int,in text)
+_pgr_createindex(text,text,text,in int,in text)
+_pgr_dijkstra(text,bigint,bigint,boolean,boolean,out integer,out integer,out bigint,out bigint,out float,out float)
+_pgr_dijkstra(text,bigint,anyarray,boolean,boolean,out integer,out integer,out bigint,out bigint,out bigint,out float,out float)
+_pgr_dijkstra(text,anyarray,anyarray,boolean,boolean,out integer,out integer,out bigint,out bigint,out bigint,out bigint,out float,out float)
+_pgr_dijkstra(text,anyarray,bigint,boolean,boolean,out integer,out integer,out bigint,out bigint,out bigint,out float,out float)
+_pgr_drivingdistance(text,anyarray,float8,boolean,boolean,boolean,out integer,out bigint,out bigint,out bigint,out float,out float)
+_pgr_drivingdistance(text,bigint,float8,boolean,boolean,out integer,out bigint,out bigint,out float,out float)
+_pgr_endpoint(geometry)
+_pgr_getcolumnname(text,text,text,in int,in text)
+_pgr_getcolumnname(text,text,in int,in text)
+_pgr_getcolumntype(text,text,in int,in text)
+_pgr_gettablename(in text,in int,in text,out text,out text)
+_pgr_iscolumnintable(text,text)
+_pgr_iscolumnindexed(text,text,text,in int,in text)
+_pgr_iscolumnindexed(text,text,in int,in text)
+_pgr_ksp(text,bigint,bigint,integer,boolean,boolean,out integer,out integer,out integer,out bigint,out bigint,out float,out float)
+_pgr_msg(in int,in text,in text(sname text,text,text,in int,in text)
+_pgr_onerror(in boolean,in int,in text,in text,in text,in text)
+_pgr_parameter_check(text,text,boolean)
+_pgr_pointtoid(geometry,double precision,text,integer)
+_pgr_quote_ident(text)
+_pgr_startpoint(geometry)
+_pgr_versionless(text,text)
+pgr_alphashape(text,float8,out float8,out float8)
+pgr_analyzeoneway(text,text[],text[],text[],text[],boolean,text,text,text)
+pgr_analyzegraph(text,double precision,text,text,text,text,text)
+pgr_apspjohnson(text)
+pgr_apspwarshall(text,boolean,boolean)
+pgr_astar(text,integer,integer,boolean,boolean)
+pgr_bdastar(text,integer,integer,boolean,boolean)
+pgr_bddijkstra(text,integer,integer,boolean,boolean)
+pgr_createtopology(text,double precision,text,text,text,text,text,boolean)
+pgr_createverticestable(text,text,text,text,text)
+pgr_dijkstra(text,bigint,bigint,out integer,out integer,out bigint,out bigint,out float,out float)
+pgr_dijkstra(text,bigint,bigint,boolean,out integer,out integer,out bigint,out bigint,out float,out float)
+pgr_dijkstra(text,bigint,bigint,boolean,boolean)
+pgr_dijkstra(text,bigint,anyarray,boolean,out integer,out integer,out bigint,out bigint,out bigint,out float,out float)
+pgr_dijkstra(text,anyarray,bigint,boolean,out integer,out integer,out bigint,out bigint,out bigint,out float,out float)
+pgr_dijkstra(text,anyarray,anyarray,boolean,out integer,out integer,out bigint,out bigint,out bigint,out bigint,out float,out float)
+pgr_drivingdistance(text,bigint,float8,boolean,boolean)
+pgr_drivingdistance(text,anyarray,float8,boolean,boolean,out integer,out bigint,out bigint,out bigint,out float,out float)
+pgr_drivingdistance(text,bigint,float8,out integer,out bigint,out bigint,out float,out float)
+pgr_drivingdistance(text,bigint,float8,boolean,out integer,out bigint,out bigint,out float,out float)
+pgr_endpoint(geometry)
+pgr_flipedges(geometry[])
+pgr_getcolumnname(text,text)
+pgr_gettablename(in text,out text,out text)
+pgr_gsoc_vrppdtw(text,integer,integer,out integer,out integer,out integer,out integer )
+pgr_iscolumnintable(text,text)
+pgr_iscolumnindexed(text,text)
+pgr_kdijkstracost(text,integer,integer array,boolean,boolean)
+pgr_kdijkstrapath(text,integer,integer array,boolean,boolean)
+pgr_ksp(text,bigint,bigint,integer,boolean,boolean,out integer,out integer,out integer,out bigint,out bigint,out float,out float)
+pgr_ksp(text,integer,integer,integer,boolean)
+pgr_labelgraph(text,text,text,text,text,text)
+pgr_nodenetwork(text,double precision,text,text,text)
+pgr_pointsaspolygon(varchar,float8)
+pgr_pointtoedgenode(text,geometry,float8)
+pgr_quote_ident(text)
+pgr_startpoint(geometry)
+pgr_trsp(text,integer,float8,integer,float8,boolean,boolean,text)
+pgr_trsp(text,integer,integer,boolean,boolean,text)
+pgr_trsp(text,integer[],float8[],boolean,boolean,text)
+pgr_trsp(text,integer[],boolean,boolean,text)
+pgr_trspviaedges(text,integer[],float8[],boolean,boolean,text)
+pgr_trspviavertices(text,integer[],boolean,boolean,text)
+pgr_tsp(float8[][],integer,integer,out integer,out integer)
+pgr_versionless(text,text)
+pgr_vidstodmatrix(text,integer[],bool,bool,bool)
+pgr_vrponedepot(text,text,text,integer,out integer,out integer,out integer,out integer,out integer)
diff --git a/tools/test-runner.pl b/tools/test-runner.pl
index 0affa2a..267c575 100755
--- a/tools/test-runner.pl
+++ b/tools/test-runner.pl
@@ -20,14 +20,16 @@ my $DRYRUN = 0;
my $DEBUG = 0;
my $DBNAME = "pgr_test__db__test";
-my $DBUSER = 'postgres';
-my $DBHOST = 'localhost';
-my $DBPORT = '5432';
+my $DBUSER;
+my $DBHOST;
+my $DBPORT;
sub Usage {
die "Usage: test-runner.pl -pgver vpg -pgisver vpgis -psql /path/to/psql\n" .
" -pgver vpg - postgresql version\n" .
- " -pgport port - postgresql port to use (default: 5432)\n" .
+ " -pghost host - postgresql host or socket directory to use\n" .
+ " -pgport port - postgresql port to use\n" .
+ " -pguser username - postgresql user role to use\n" .
" -pgisver vpgis - postgis version\n" .
" -pgrver vpgr - pgrouting version\n" .
" -psql /path/to/psql - optional path to psql\n" .
@@ -50,9 +52,15 @@ while (my $a = shift @ARGV) {
if ( $a eq '-pgver') {
$vpg = shift @ARGV || Usage();
}
+ elsif ($a eq '-pghost') {
+ $DBHOST = shift @ARGV || Usage();
+ }
elsif ($a eq '-pgport') {
$DBPORT = shift @ARGV || Usage();
}
+ elsif ($a eq '-pguser') {
+ $DBUSER = shift @ARGV || Usage();
+ }
elsif ($a eq '-pgisver') {
$vpgis = shift @ARGV || Usage();
}
@@ -62,9 +70,10 @@ while (my $a = shift @ARGV) {
elsif ($a eq '-alg') {
$alg = shift @ARGV || Usage();
if ($alg eq 'doc') {
- @testpath = ($alg);
- }
- else {
+ @testpath = ('doc');
+ } elsif ($alg eq 'recipes') {
+ @testpath = ("doc/src/recipes");
+ } else {
@testpath = ("src/$alg");
}
}
@@ -92,7 +101,12 @@ while (my $a = shift @ARGV) {
}
}
-mysystem("dropdb -U $DBUSER -h $DBHOST -p $DBPORT $DBNAME") if $clean;
+my $connopts = "";
+$connopts .= " -U $DBUSER" if defined $DBUSER;
+$connopts .= " -h $DBHOST" if defined $DBHOST;
+$connopts .= " -p $DBPORT" if defined $DBPORT;
+
+mysystem("dropdb $connopts $DBNAME") if $clean;
%main::tests = ();
my @cfgs = ();
@@ -181,19 +195,19 @@ sub run_test {
$res{comment} = $t->{comment} if $t->{comment};
for my $x (@{$t->{data}}) {
- mysystem("$psql -U $DBUSER -h $DBHOST -p $DBPORT -A -t -q -f '$dir/$x' $DBNAME >> $TMP2 2>\&1 ");
+ mysystem("$psql $connopts -A -t -q -f '$dir/$x' $DBNAME >> $TMP2 2>\&1 ");
}
for my $x (@{$t->{tests}}) {
print "Processing test: $x\n";
my $t0 = [gettimeofday];
- open(TIN, "$dir/$x.test") || do {
- $res{"$dir/$x.test"} = "FAILED: could not open '$dir/$x.test' : $!";
+ open(TIN, "$dir/$x.test.sql") || do {
+ $res{"$dir/$x.test.sql"} = "FAILED: could not open '$dir/$x.test.sql' : $!";
$stats{z_fail}++;
next;
};
- open(PSQL, "|$psql -U $DBUSER -h $DBHOST -p $DBPORT -A -t -q $DBNAME > $TMP 2>\&1 ") || do {
- $res{"$dir/$x.test"} = "FAILED: could not open connection to db : $!";
+ open(PSQL, "|$psql $connopts -A -t -q $DBNAME > $TMP 2>\&1 ") || do {
+ $res{"$dir/$x.test.sql"} = "FAILED: could not open connection to db : $!";
$stats{z_fail}++;
next;
};
@@ -210,28 +224,29 @@ sub run_test {
$dfile2 = $TMP2;
mysystem("grep -v NOTICE '$TMP' | grep -v '^CONTEXT:' | grep -v '^PL/pgSQL function' > $dfile2");
$dfile = $TMP3;
- mysystem("grep -v NOTICE '$dir/$x.rest' | grep -v '^CONTEXT:' | grep -v '^PL/pgSQL function' > $dfile");
+ mysystem("grep -v NOTICE '$dir/$x.result' | grep -v '^CONTEXT:' | grep -v '^PL/pgSQL function' > $dfile");
}
else {
- $dfile = "$dir/$x.rest";
+ $dfile = "$dir/$x.result";
$dfile2 = $TMP;
}
# use diff -w to ignore white space differences like \r vs \r\n
my $r = `diff -w '$dfile' '$dfile2' `;
$r =~ s/^\s*|\s*$//g;
if ($r =~ /connection to server was lost/) {
- $res{"$dir/$x.test"} = "CRASHED SERVER: $r";
+ $res{"$dir/$x.test.sql"} = "CRASHED SERVER: $r";
$stats{z_crash}++;
# allow the server some time to recover from the crash
- warn "CRASHED SERVER: '$dir/$x.test', sleeping 5 ...\n";
+ warn "CRASHED SERVER: '$dir/$x.test.sql', sleeping 5 ...\n";
sleep 5;
}
elsif (length($r)) {
- $res{"$dir/$x.test"} = "FAILED: $r";
+ $res{"$dir/$x.test.sql"} = "FAILED: $r";
$stats{z_fail}++;
}
+# TODO missing when the result file does not exist
else {
- $res{"$dir/$x.test"} = "Passed";
+ $res{"$dir/$x.test.sql"} = "Passed";
$stats{z_pass}++;
}
print " test run time: " . tv_interval($t0, [gettimeofday]) . "\n";
@@ -245,7 +260,7 @@ sub createTestDB {
if dbExists($DBNAME);
my $template;
-
+
my $dbver = getServerVersion();
my $dbshare = getSharePath($dbver);
@@ -257,7 +272,7 @@ sub createTestDB {
# first create a database with postgis installed in it
if (version_greater_eq($dbver, '9.1') &&
-f "$dbshare/extension/postgis.control") {
- mysystem("createdb -U $DBUSER -h $DBHOST -p $DBPORT $DBNAME");
+ mysystem("createdb $connopts $DBNAME");
die "ERROR: Failed to create database '$DBNAME'!\n"
unless dbExists($DBNAME);
my $myver = '';
@@ -270,7 +285,7 @@ sub createTestDB {
$encoding = "SET client_encoding TO 'UTF8';";
}
print "-- Trying to install postgis extension $myver\n" if $DEBUG;
- mysystem("$psql -U $DBUSER -h $DBHOST -p $DBPORT -c \"$encoding create extension postgis $myver\" $DBNAME");
+ mysystem("$psql $connopts -c \"$encoding create extension postgis $myver\" $DBNAME");
}
else {
if ($vpgis && dbExists("template_postgis_$vpgis")) {
@@ -283,7 +298,7 @@ sub createTestDB {
die "ERROR: Could not find an appropriate template_postgis database!\n";
}
print "-- Trying to install postgis from $template\n" if $DEBUG;
- mysystem("createdb -U $DBUSER -h $DBHOST -p $DBPORT -T $template $DBNAME");
+ mysystem("createdb $connopts -T $template $DBNAME");
sleep(2);
die "ERROR: Failed to create database '$DBNAME'!\n"
if ! dbExists($DBNAME);
@@ -294,14 +309,14 @@ sub createTestDB {
-f "$dbshare/extension/postgis.control") {
my $myver = '';
if ($vpgr) {
- $myver = " VERSION '$vpgr'";
+ $myver = " PGROUTING VERSION '$vpgr'";
}
print "-- Trying to install pgrouting extension $myver\n" if $DEBUG;
- mysystem("$psql -U $DBUSER -h $DBHOST -p $DBPORT -c \"create extension pgrouting $myver\" $DBNAME");
+ mysystem("$psql $connopts -c \"create extension pgrouting $myver\" $DBNAME");
}
elsif ($vpgr && -f "$dbshare/extension/pgrouting--$vpgr.sql") {
print "-- Trying to install pgrouting from '$dbshare/extension/pgrouting--$vpgr.sql'\n" if $DEBUG;
- mysystem("$psql -U $DBUSER -h $DBHOST -p $DBPORT -f '$dbshare/extension/pgrouting--$vpgr.sql' $DBNAME");
+ mysystem("$psql $connopts -f '$dbshare/extension/pgrouting--$vpgr.sql' $DBNAME");
}
else {
my $find = `find "$dbshare/contrib" -name pgrouting.sql | sort -r -n `;
@@ -309,7 +324,7 @@ sub createTestDB {
my $file = shift @found;
if ($file && length($file)) {
print "-- Trying to install pgrouting from '$file'\n" if $DEBUG;
- mysystem("$psql -U $DBUSER -h $DBHOST -p $DBPORT -f '$file' $DBNAME");
+ mysystem("$psql $connopts -f '$file' $DBNAME");
}
else {
mysystem("ls -alR $dbshare") if $DEBUG;
@@ -319,14 +334,14 @@ sub createTestDB {
# now verify that we have pgrouting installed
- my $pgrv = `$psql -U $DBUSER -h $DBHOST -p $DBPORT -c "select pgr_version()" $DBNAME`;
+ my $pgrv = `$psql $connopts -c "select pgr_version()" $DBNAME`;
die "ERROR: failed to install pgrouting into the database!\n"
unless $pgrv;
}
sub dropTestDB {
- mysystem("dropdb -U $DBUSER -h $DBHOST -p $DBPORT $DBNAME");
+ mysystem("dropdb $connopts $DBNAME");
}
sub version_greater_eq {
@@ -353,8 +368,8 @@ sub version_greater_eq {
sub getServerVersion {
- my $v = `$psql -U $DBUSER -h $DBHOST -p $DBPORT -q -t -c "select version()" postgres`;
- print "$psql -U $DBUSER -h $DBHOST -p $DBPORT -q -t -c \"select version()\" postgres\n # RETURNED: $v\n" if $VERBOSE;
+ my $v = `$psql $connopts -q -t -c "select version()" postgres`;
+ print "$psql $connopts -q -t -c \"select version()\" postgres\n # RETURNED: $v\n" if $VERBOSE;
if ($v =~ m/PostgreSQL (\d+(\.\d+)?(\.\d+)?)/) {
print " # Got ($1)\n" if $VERBOSE;
return $1;
@@ -365,7 +380,7 @@ sub getServerVersion {
sub dbExists {
my $dbname = shift;
- my $isdb = `$psql -U $DBUSER -h $DBHOST -p $DBPORT -l | grep $dbname`;
+ my $isdb = `$psql $connopts -l | grep $dbname`;
$isdb =~ s/^\s*|\s*$//g;
return length($isdb);
}
@@ -379,7 +394,7 @@ sub findPsql {
# getSharePath is complicated by the fact that on Debian we can have multiple
# versions installed in a cluster. So we get the DB version by connectiong
-# to the port for the server we want. Then we get the share path for the
+# to the port for the server we want. Then we get the share path for the
# newest version od pg installed on the cluster. And finally we change the
# in the path to the version of the server.
diff --git a/tools/test-update.sh b/tools/test-update.sh
new file mode 100755
index 0000000..52b8cca
--- /dev/null
+++ b/tools/test-update.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+dropdb -U postgres -h localhost test_update -p 5432
+createdb -U postgres -h localhost test_update -p 5432
+psql -U postgres -h localhost test_update -p 5432 <<EOF
+create extension postgis;
+create extension pgrouting with version '2.0.0';
+select pgr_version();
+alter extension pgrouting update to '2.1.0';
+select pgr_version();
+
+EOF
+
diff --git a/tools/travis/pgrouting_build.sh b/tools/travis/pgrouting_build.sh
index f9f828b..6574075 100755
--- a/tools/travis/pgrouting_build.sh
+++ b/tools/travis/pgrouting_build.sh
@@ -11,5 +11,6 @@ set -e
# build pgRouting
cmake -DWITH_DD=ON
+#cmake
make
sudo make install
diff --git a/tools/travis/pgrouting_install.sh b/tools/travis/pgrouting_install.sh
index e9ca772..95ac449 100755
--- a/tools/travis/pgrouting_install.sh
+++ b/tools/travis/pgrouting_install.sh
@@ -16,59 +16,50 @@ ERROR=0
# ------------------------------------------------------------------------------
# Remove PostgreSQL and all its files
# ------------------------------------------------------------------------------
-if [ "$POSTGRESQL_VERSION" != "9.1" ]; then
- sudo service postgresql stop
- sudo apt-get remove postgresql postgresql-common postgresql-client-common postgresql-9.1 postgresql-client-9.1 libpq-dev libpq5 -qq --purge
-fi
+sudo service postgresql stop
+sudo apt-get remove postgresql libpq-dev libpq5 postgresql-client-common postgresql-common -qq --purge -y
+sudo rm -rf /var/lib/postgresql
# Add PPA's'
# ------------------------------------------------------------------------------
sudo apt-add-repository -y ppa:georepublic/pgrouting-travis
if [ "$POSTGIS_VERSION" == "2.0" ] || [ "$POSTGIS_VERSION" == "2.1" ]; then
- sudo apt-add-repository -y ppa:ubuntugis/ubuntugis-unstable
+ sudo apt-add-repository -y ppa:ubuntugis/ppa
fi
# Add PostgreSQL Apt repository
+# UPDATE: seems to be already available in Travis
# ------------------------------------------------------------------------------
-if [ "$POSTGRESQL_VERSION" != "9.1" ]; then
- echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > pgdg.list
- sudo mv pgdg.list /etc/apt/sources.list.d/
- wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add -
-fi
-
-# Reload package archive
-# ------------------------------------------------------------------------------
+# echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > pgdg.list
+# sudo mv pgdg.list /etc/apt/sources.list.d/
+# wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update -qq
# ------------------------------------------------------------------------------
-# Install PostgreSQL
+# Install PostgreSQL (always install from PostgreSQL Apt repository)
# ------------------------------------------------------------------------------
-if [ "$POSTGRESQL_VERSION" != "9.1" ]; then
- sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install -y -qq postgresql-$POSTGRESQL_VERSION postgresql-contrib-$POSTGRESQL_VERSION
-fi
+sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install -y -qq postgresql-$POSTGRESQL_VERSION postgresql-contrib-$POSTGRESQL_VERSION postgresql-server-dev-$POSTGRESQL_VERSION
+# Install packages
# ------------------------------------------------------------------------------
-# Install dependecies
-# ------------------------------------------------------------------------------
-sudo apt-get install cmake libcgal-dev libboost-graph-dev libboost-thread-dev postgresql-server-dev-$POSTGRESQL_VERSION
-
-# ------------------------------------------------------------------------------
-# Install PostGIS (always build from source)
-# ------------------------------------------------------------------------------
-sudo apt-get install -y -qq build-essential libxml2-dev libproj-dev libjson0-dev xsltproc docbook-xsl docbook-mathml libgeos-dev libgdal1-dev
+echo "Installing packages ... this may take some time."
+sudo apt-get install -y -qq packaging-dev cmake checkinstall libcgal-dev libboost-graph-dev libboost-thread-dev libxml2-dev libproj-dev libjson0-dev xsltproc docbook-xsl docbook-mathml libgeos-dev libgdal1-dev
if [ "$POSTGIS_VERSION" == "1.5" ]; then
- wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-1.5.8.tar.gz | tar xzf -
+ RELEASE="1.5.8"
+ wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-${RELEASE}.tar.gz | tar xzf -
fi
if [ "$POSTGIS_VERSION" == "2.0" ]; then
- wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-2.0.3.tar.gz | tar xzf -
+ RELEASE="2.0.7"
+ wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-${RELEASE}.tar.gz | tar xzf -
fi
if [ "$POSTGIS_VERSION" == "2.1" ]; then
sudo apt-get install -y -qq libpoppler-dev libarmadillo-dev libepsilon-dev liblzma-dev libxml2-dev
- wget --quiet -O - https://github.com/postgis/postgis/archive/svn-trunk.tar.gz | tar xzf -
+ RELEASE="2.1.7"
+ wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-${RELEASE}.tar.gz | tar xzf -
fi
# Build and compile
@@ -91,4 +82,4 @@ sudo /etc/init.d/postgresql restart
# Return success or failure
# ------------------------------------------------------------------------------
-exit $ERROR
\ No newline at end of file
+exit $ERROR
diff --git a/tools/travis/pgrouting_prepare.sh b/tools/travis/pgrouting_prepare.sh
index 8748209..216acc1 100755
--- a/tools/travis/pgrouting_prepare.sh
+++ b/tools/travis/pgrouting_prepare.sh
@@ -14,6 +14,12 @@ POSTGIS_VERSION="$2"
POSTGRESQL_DIRECTORY="/usr/share/postgresql/$POSTGRESQL_VERSION"
+echo "POSTGRESQL_VERSION=$POSTGRESQL_VERSION"
+echo "POSTGIS_VERSION=$POSTGIS_VERSION"
+echo "POSTGRESQL_DIRECTORY=/usr/share/postgresql/$POSTGRESQL_VERSION"
+ls $POSTGRESQL_DIRECTORY/extension/postgis--*
+ls /usr/lib/postgresql/$POSTGRESQL_VERSION/lib/postgis-*.so
+
# exit script on error
set -e
ERROR=0
@@ -31,49 +37,53 @@ run_psql () {
# ------------------------------------------------------------------------------
# Set PostgreSQL users and permissions
# ------------------------------------------------------------------------------
-sudo cp $TRAVIS_BUILD_DIR/tools/travis/pg_hba.conf `find /etc/postgresql/*/main/pg_hba.conf`
+sudo cp $TRAVIS_BUILD_DIR/tools/travis/pg_hba.conf `find /etc/postgresql/*/*/pg_hba.conf`
sudo /etc/init.d/postgresql restart
# Disable password (better: create new user)
sudo -u $DBUSER psql -c "ALTER ROLE postgres WITH PASSWORD '';"
+exit $ERROR
+
+# WE ARE NOT USING TEMPLATE DATABASES SO DON'T GO BELOW HERE
+
# ------------------------------------------------------------------------------
# Create database templates
# ------------------------------------------------------------------------------
# PostGIS
# ------------------------------------------------------------------------------
-run_psql -U $DBUSER -c "CREATE DATABASE template_postgis ENCODING 'UTF8' TEMPLATE template0;"
+#run_psql -U $DBUSER -c "CREATE DATABASE template_postgis ENCODING 'UTF8' TEMPLATE template0;"
-if [ "$POSTGRESQL_VERSION" == "8.4" ]
-then
- run_psql -U $DBUSER -d template_postgis -c "CREATE LANGUAGE plpgsql;"
-fi
+#if [ "$POSTGRESQL_VERSION" == "8.4" ]
+#then
+# run_psql -U $DBUSER -d template_postgis -c "CREATE LANGUAGE plpgsql;"
+#fi
-run_psql -U $DBUSER -d template_postgis -f `find $POSTGRESQL_DIRECTORY/contrib -name "postgis.sql"`
-run_psql -U $DBUSER -d template_postgis -f `find $POSTGRESQL_DIRECTORY/contrib -name "spatial_ref_sys.sql"`
-
-run_psql -U $DBUSER -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;"
-run_psql -U $DBUSER -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"
-run_psql -U $DBUSER -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
+#run_psql -U $DBUSER -d template_postgis -f `find $POSTGRESQL_DIRECTORY/contrib -name "postgis.sql"`
+#run_psql -U $DBUSER -d template_postgis -f `find $POSTGRESQL_DIRECTORY/contrib -name "spatial_ref_sys.sql"`
+#
+#run_psql -U $DBUSER -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;"
+#run_psql -U $DBUSER -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"
+#run_psql -U $DBUSER -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
-run_psql -U $DBUSER -d template_postgis -c "VACUUM FULL;"
-run_psql -U $DBUSER -d template_postgis -c "VACUUM FREEZE;"
+#run_psql -U $DBUSER -d template_postgis -c "VACUUM FULL;"
+#run_psql -U $DBUSER -d template_postgis -c "VACUUM FREEZE;"
-run_psql -U $DBUSER -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
-run_psql -U $DBUSER -c "UPDATE pg_database SET datallowconn='false' WHERE datname='template_postgis';"
+#run_psql -U $DBUSER -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
+#run_psql -U $DBUSER -c "UPDATE pg_database SET datallowconn='false' WHERE datname='template_postgis';"
# pgRouting
# ------------------------------------------------------------------------------
-run_psql -U $DBUSER -c "CREATE DATABASE template_pgrouting ENCODING 'UTF8' TEMPLATE template_postgis;"
-run_psql -U $DBUSER -d template_pgrouting -f `find $POSTGRESQL_DIRECTORY/contrib -name "pgrouting.sql"`
+#run_psql -U $DBUSER -c "CREATE DATABASE template_pgrouting ENCODING 'UTF8' TEMPLATE template_postgis;"
+#run_psql -U $DBUSER -d template_pgrouting -f `find $POSTGRESQL_DIRECTORY/contrib -name "pgrouting.sql"`
-run_psql -U $DBUSER -d template_pgrouting -c "VACUUM FULL;"
-run_psql -U $DBUSER -d template_pgrouting -c "VACUUM FREEZE;"
+#run_psql -U $DBUSER -d template_pgrouting -c "VACUUM FULL;"
+#run_psql -U $DBUSER -d template_pgrouting -c "VACUUM FREEZE;"
-run_psql -U $DBUSER -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_pgrouting';"
-run_psql -U $DBUSER -c "UPDATE pg_database SET datallowconn='false' WHERE datname='template_pgrouting';"
+#run_psql -U $DBUSER -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_pgrouting';"
+#run_psql -U $DBUSER -c "UPDATE pg_database SET datallowconn='false' WHERE datname='template_pgrouting';"
# Return success or failure
# ------------------------------------------------------------------------------
-exit $ERROR
+#exit $ERROR
diff --git a/tools/travis/pgrouting_test.sh b/tools/travis/pgrouting_test.sh
index 7440bf9..46bec11 100755
--- a/tools/travis/pgrouting_test.sh
+++ b/tools/travis/pgrouting_test.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# ------------------------------------------------------------------------------
# Travis CI scripts
# Copyright(c) pgRouting Contributors
@@ -6,8 +6,8 @@
# Test pgRouting
# ------------------------------------------------------------------------------
-DBUSER="postgres"
-DBNAME="pgrouting"
+PGUSER="postgres"
+PGDATABASE="pgrouting"
POSTGRESQL_VERSION="$1"
POSTGIS_VERSION="$2"
@@ -31,55 +31,59 @@ run_psql () {
# ------------------------------------------------------------------------------
# CREATE DATABASE
# ------------------------------------------------------------------------------
-run_psql -U $DBUSER -l
-run_psql -U $DBUSER -c "CREATE DATABASE $DBNAME;"
+export PGUSER
+run_psql -l
+run_psql -c "CREATE DATABASE $PGDATABASE;"
+export PGDATABASE
# ------------------------------------------------------------------------------
# CREATE EXTENSION
# ------------------------------------------------------------------------------
IGNORE=-ignorenotice
-if [ "$POSTGRESQL_VERSION" == "8.4" ] || [ "$POSTGRESQL_VERSION" == "9.0" ]
-then
- run_psql -U $DBUSER -d $DBNAME -f `find $POSTGRESQL_DIRECTORY/contrib -name "postgis.sql"`
- run_psql -U $DBUSER -d $DBNAME -f `find $POSTGRESQL_DIRECTORY/contrib -name "spatial_ref_sys.sql"`
- run_psql -U $DBUSER -d $DBNAME -f `find $POSTGRESQL_DIRECTORY/contrib -name "pgrouting.sql"`
- IGNORE=-ignorenotice
-fi
+#if [ "$POSTGRESQL_VERSION" == "8.4" ] || [ "$POSTGRESQL_VERSION" == "9.0" ]
+#then
+# run_psql -f `find $POSTGRESQL_DIRECTORY/contrib -name "postgis.sql"`
+# run_psql -f `find $POSTGRESQL_DIRECTORY/contrib -name "spatial_ref_sys.sql"`
+# run_psql -f `find $POSTGRESQL_DIRECTORY/contrib -name "pgrouting.sql"`
+# IGNORE=-ignorenotice
+#fi
-if [ "$POSTGRESQL_VERSION" == "9.1" ]
-then
- if [ "$POSTGIS_VERSION" == "1.5" ]
- then
- run_psql -U $DBUSER -d $DBNAME -f `find $POSTGRESQL_DIRECTORY/contrib -name "postgis.sql"`
- run_psql -U $DBUSER -d $DBNAME -f `find $POSTGRESQL_DIRECTORY/contrib -name "spatial_ref_sys.sql"`
- run_psql -U $DBUSER -d $DBNAME -f `find $POSTGRESQL_DIRECTORY/contrib -name "pgrouting.sql"`
- else
- run_psql -U $DBUSER -d $DBNAME -c "CREATE EXTENSION postgis;"
- run_psql -U $DBUSER -d $DBNAME -c "CREATE EXTENSION pgrouting;"
- fi
- IGNORE=-ignorenotice
-fi
+#if [ "$POSTGRESQL_VERSION" == "9.1" ]
+#then
+# if [ "$POSTGIS_VERSION" == "1.5" ]
+# then
+# run_psql -f `find $POSTGRESQL_DIRECTORY/contrib -name "postgis.sql"`
+# run_psql -f `find $POSTGRESQL_DIRECTORY/contrib -name "spatial_ref_sys.sql"`
+# run_psql -f `find $POSTGRESQL_DIRECTORY/contrib -name "pgrouting.sql"`
+# else
+# run_psql -c "CREATE EXTENSION postgis;"
+# run_psql -c "CREATE EXTENSION pgrouting;"
+# fi
+# IGNORE=-ignorenotice
+#fi
-if [ "$POSTGRESQL_VERSION" == "9.2" ] || [ "$POSTGRESQL_VERSION" == "9.3" ]
-then
- run_psql -U $DBUSER -d $DBNAME -c "CREATE EXTENSION postgis;"
- run_psql -U $DBUSER -d $DBNAME -c "CREATE EXTENSION pgrouting;"
-fi
+#if [ "$POSTGRESQL_VERSION" == "9.2" ] || [ "$POSTGRESQL_VERSION" == "9.3" ] || [ "$POSTGRESQL_VERSION" == "9.4" ]
+#then
+#we are allways creating extension
+ run_psql -c "CREATE EXTENSION postgis;"
+ run_psql -c "CREATE EXTENSION pgrouting;"
+#fi
# ------------------------------------------------------------------------------
# Get version information
# ------------------------------------------------------------------------------
-run_psql -U $DBUSER -d $DBNAME -c "SELECT postgis_full_version();"
-run_psql -U $DBUSER -d $DBNAME -c "SELECT pgr_version();"
+run_psql -c "SELECT postgis_full_version();"
+run_psql -c "SELECT pgr_version();"
-PGROUTING_VERSION=`run_psql -U $DBUSER -A -t -d $DBNAME -c "SELECT version FROM pgr_version();"`
+PGROUTING_VERSION=`run_psql -A -t -c "SELECT version FROM pgr_version();"`
# ------------------------------------------------------------------------------
# Test runner
# ------------------------------------------------------------------------------
# use -v -v for more verbose debuging output
# ./tools/test-runner.pl -v -v -pgver $POSTGRESQL_VERSION
-./tools/test-runner.pl -pgver $POSTGRESQL_VERSION $IGNORE
+ ./tools/test-runner.pl -pgver $POSTGRESQL_VERSION $IGNORE
+#./tools/test-runner.pl -pgver $POSTGRESQL_VERSION $IGNORE -v -alg ksp
if [ "$?" -ne 0 ]
then
ERROR=1
diff --git a/tools/vagrant/bootstrap.sh b/tools/vagrant/bootstrap.sh
index ff9573c..2d24dd2 100755
--- a/tools/vagrant/bootstrap.sh
+++ b/tools/vagrant/bootstrap.sh
@@ -32,17 +32,15 @@ apt-get install -y -qq python-software-properties vim
apt-add-repository -y ppa:georepublic/pgrouting-travis
if [ "$POSTGIS_VERSION" == "2.0" ] || [ "$POSTGIS_VERSION" == "2.1" ]; then
- apt-add-repository -y ppa:ubuntugis/ubuntugis-unstable
+ apt-add-repository -y ppa:ubuntugis/ppa
fi
# Add PostgreSQL Apt repository
# ------------------------------------------------------------------------------
-if [ "$POSTGRESQL_VERSION" != "9.1" ]; then
- echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list
- wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt-key add -
-fi
-
-apt-get update -qq
+echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > pgdg.list
+sudo mv pgdg.list /etc/apt/sources.list.d/
+wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
+sudo apt-get update -qq
# Install packages
# ------------------------------------------------------------------------------
@@ -62,16 +60,19 @@ pip install sphinx transifex-client sphinx-intl
# ------------------------------------------------------------------------------
if [ "$POSTGIS_VERSION" == "1.5" ]; then
- wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-1.5.8.tar.gz | tar xzf -
+ RELEASE="1.5.8"
+ wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-${RELEASE}.tar.gz | tar xzf -
fi
if [ "$POSTGIS_VERSION" == "2.0" ]; then
- wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-2.0.3.tar.gz | tar xzf -
+ RELEASE="2.0.4"
+ wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-${RELEASE}.tar.gz | tar xzf -
fi
if [ "$POSTGIS_VERSION" == "2.1" ]; then
- apt-get install -y -qq libpoppler-dev libarmadillo-dev libepsilon-dev liblzma-dev libxml2-dev
- wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-2.1.0.tar.gz | tar xzf -
+ sudo apt-get install -y -qq libpoppler-dev libarmadillo-dev libepsilon-dev liblzma-dev libxml2-dev
+ RELEASE="2.1.1"
+ wget --quiet -O - http://download.osgeo.org/postgis/source/postgis-${RELEASE}.tar.gz | tar xzf -
fi
# Build and compile
diff --git a/tools/winnie/build_pgrouting.sh b/tools/winnie/build_pgrouting.sh
index 496dc7f..2728e6e 100644
--- a/tools/winnie/build_pgrouting.sh
+++ b/tools/winnie/build_pgrouting.sh
@@ -7,29 +7,30 @@
#export PGHOST=localhost
#export PGPORT=8442
export PGUSER=postgres
-#export PGROUTING_VER=2.0
+#export PGROUTING_VER=2.1
#POSTGIS_VER=2.1.0SVN
#GCC_TYPE=
#export POSTIGS_VER=2.1.0beta3
-
+#export GIT_COMMIT=whatever
+export PROJECTS=/projects
+export PGPATHEDB=${PROJECTS}/postgresql/rel/pg${PG_VER}w${OS_BUILD}${GCC_TYPE}edb #this is so winnie know's where to copy the dlls for vc++ edb compiled postgresql testing
+export PATHOLD=$PATH
+export PGPATH=${PROJECTS}/postgresql/rel/pg${PG_VER}w${OS_BUILD}${GCC_TYPE}
#export PROJECTS=/c/ming${OS_BUILD}/projects
-if [[ "${GCC_TYPE}" == "gcc48" ]] ; then
- export PROJECTS=/projects
- export PATHOLD=$PATH
- export PGPATH=${PROJECTS}/postgresql/rel/pg${PG_VER}w${OS_BUILD}${GCC_TYPE}
+if [[ "${GCC_TYPE}" == *gcc48* ]] ; then
export PostgreSQL_ROOT=${PGPATH}
export PATHOLD="/mingw/bin:/mingw/include:/c/Windows/system32:/c/Windows"
export PGWINVER=${PG_VER}w${OS_BUILD}${GCC_TYPE}edb
export PATH="${PATHOLD}:${PGPATH}/bin:${PGPATH}/lib:${PGPATH}/include"
- export PATH="${PROJECTS}/rel-libiconv-1.13.1w${OS_BUILD}/include:${PATH}"
+ export PATH="${PROJECTS}/rel-libiconv-1.13.1w${OS_BUILD}${GCC_TYPE}/include:${PATH}"
GMP_VER=5.1.2
MPFR_VER=3.1.2
CGAL_VER=4.2
- BOOST_VER=1.53.0
- BOOST_VER_WU=1_53_0
- BOOST_VER_WUM=1_53
+ BOOST_VER=1.59.0
+ BOOST_VER_WU=1_59_0
+ BOOST_VER_WUM=1_59
ZLIB_VER=1.2.8
#export PATH="/mingw/bin:/mingw/include:/c/Windows/system32"
#zlib
@@ -50,12 +51,9 @@ if [[ "${GCC_TYPE}" == "gcc48" ]] ; then
rm -rf build${PGROUTING_VER}w${OS_BUILD}${GCC_TYPE}
mkdir build${PGROUTING_VER}w${OS_BUILD}${GCC_TYPE}
cd build${PGROUTING_VER}w${OS_BUILD}${GCC_TYPE}
- cmake -G "MSYS Makefiles" -DWITH_DD=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DBOOST_ROOT:PATH=${PROJECTS}/boost/rel-${BOOST_VER_WU}w${OS_BUILD}${GCC_TYPE} -DCGAL_ROOT:PATH=${PROJECTS}/CGAL/rel-cgal-${CGAL_VER}w${OS_BUILD}${GCC_TYPE} -DGMP_ROOT:PATH=${PROJECTS}/CGAL/rel-gmp-${GMP_VER}w${OS_BUILD}${GCC_TYPE} -DBoost_USE_STATIC_LIBS=ON -DBoost_USE_MULTITHREADED=ON -DCMAKE_CXX_FLAGS="-I${PROJECTS}/CGAL/rel-gmp-${GMP_VER}w${OS_BUILD}${GCC_TYPE}/include -I${PROJECTS}/CGAL/rel-mpfr-${MPFR_VER}w${OS_BUI [...]
+ cmake -G "MSYS Makefiles" -DCMAKE_VERBOSE_MAKEFILE=ON -DBOOST_ROOT:PATH=${PROJECTS}/boost/rel-${BOOST_VER_WU}w${OS_BUILD}${GCC_TYPE} -DCGAL_ROOT:PATH=${PROJECTS}/CGAL/rel-cgal-${CGAL_VER}w${OS_BUILD}${GCC_TYPE} -DGMP_ROOT:PATH=${PROJECTS}/CGAL/rel-gmp-${GMP_VER}w${OS_BUILD}${GCC_TYPE} -DBoost_USE_STATIC_LIBS=ON -DBoost_USE_MULTITHREADED=ON -DCMAKE_CXX_FLAGS="-I${PROJECTS}/CGAL/rel-gmp-${GMP_VER}w${OS_BUILD}${GCC_TYPE}/include -I${PROJECTS}/CGAL/rel-mpfr-${MPFR_VER}w${OS_BUILD}${GCC_TYP [...]
else
- export PROJECTS=/c/jenkins
#alias cmake="/c/ming${OS_BUILD}/cmake-2.8.10.2-win32-x86/bin/cmake"
-
- export PGPATH=${PROJECTS}/postgresql/rel/pg${PG_VER}w${OS_BUILD}${GCC_TYPE}
export PostgreSQL_ROOT=${PGPATH}
export PATHOLD=$PATH
@@ -72,13 +70,29 @@ else
rm -rf build${PGROUTING_VER}w${OS_BUILD}${GCC_TYPE}
mkdir build${PGROUTING_VER}w${OS_BUILD}${GCC_TYPE}
cd build${PGROUTING_VER}w${OS_BUILD}${GCC_TYPE}
- cmake -G "MSYS Makefiles" -DWITH_DD=ON ../branches/${PGROUTING_VER}
+ cmake -G "MSYS Makefiles" ../branches/${PGROUTING_VER}
fi
#cmake -G "MSYS Makefiles" -DWITH_DD=ON ..
+#first delete old pgrouting files from installed folder before we reinstall
+echo "The git commit is ${GIT_COMMIT}"
+rm ${PGPATH}/lib/librouting*
+rm ${PGPATH}/share/extension/pgrouting*
make && make install
+#we need uninstall and reinstall copy to VC++ EDB instance if we want to test on standard Windows installed versions
+rm ${PGPATHEDB}/lib/librouting*
+cp lib/*.dll ${PGPATHEDB}/lib/
+rm ${PGPATHEDB}/share/extension/pgrouting*
+cp lib/*.sql ${PGPATHEDB}/share/extension/
+cp lib/*.control ${PGPATHEDB}/share/extension/
+
cd ${PROJECTS}/pgrouting/branches/${PGROUTING_VER}
-perl tools/test-runner.pl -pgisver "${POSTGIS_VER}" -pgport "${PGPORT}" -ignorenotice
+
+#perl tools/test-runner.pl -pgver ${PG_VER} -pgport "${PGPORT}" -clean
+perl tools/test-runner.pl -pgver ${PG_VER} -pgisver "${POSTGIS_VER}" -pgport "${PGPORT}" -ignorenotice -clean
+#perl tools/test-runner.pl -pgver ${PG_VER} -pgisver "${POSTGIS_VER}" -pgport "${PGPORT}"
+#perl tools/test-runner.pl -pgver "${PG_VER}" -pgisver "${POSTGIS_VER}" -pgport "${PGPORT}" -clean -v -alg ksp
+
cd ${PROJECTS}/pgrouting/build${PGROUTING_VER}w${OS_BUILD}${GCC_TYPE}/lib
strip *.dll
diff --git a/tools/winnie/package_pgrouting.sh b/tools/winnie/package_pgrouting.sh
index 69c80f9..c502158 100644
--- a/tools/winnie/package_pgrouting.sh
+++ b/tools/winnie/package_pgrouting.sh
@@ -6,10 +6,11 @@
#export PGPORT=8442
#export PGROUTING_VER=2.0
#export PGROUTING_MICRO_VER=0dev
+#export GIT_COMMIT=whatever
export PGUSER=postgres
-export PROJECTS=/c/jenkins
-
+#this should be setup as a mapping in msys/etc/fstab to where you keep your projects
+export PROJECTS=/projects
export PATHOLD=$PATH
#export PATHOLD=".:/bin:/include:/mingw/bin:/mingw/include:/c/Windows/system32:/c/Windows:/usr/local/bin:/c/ming64/Silksvn/bin:/c/Program Files (x86)/Git/bin"
@@ -18,13 +19,13 @@ export PATHOLD=".:/bin:/include:/mingw/bin:/mingw/include:/c/Windows/system32:/c
export PGWINVER=${PG_VER}edb
export PostgreSQL_ROOT=${PROJECTS}/postgresql/rel/pg${PG_VER}w${OS_BUILD}${GCC_TYPE}
export PATH="${PATHOLD}:${PostgreSQL_ROOT}/bin:${PostgreSQL_ROOT}/lib"
-if [[ "${GCC_TYPE}" == "gcc48" ]] ; then
+if [[ "${GCC_TYPE}" == *gcc48* ]] ; then
GMP_VER=5.1.2
MPFR_VER=3.1.2
- CGAL_VER=4.2
- BOOST_VER=1.53.0
- BOOST_VER_WU=1_53_0
- BOOST_VER_WUM=1_53
+ CGAL_VER=4.6.1
+ BOOST_VER=1.59.0
+ BOOST_VER_WU=1_59_0
+ BOOST_VER_WUM=1_59
else
GMP_VER=5.1.2
MPFR_VER=3.1.2
@@ -66,14 +67,15 @@ cp -r *.control $outdir/share/extension
cp -r *.dll $outdir/lib
#newer gcc for some reason CGAL is not statically linked
# so need to distribute
-if [[ "${GCC_TYPE}" == "gcc48" ]] ; then
+if [[ "${GCC_TYPE}" == *gcc48* ]] ; then
cp ${PROJECTS}/CGAL/rel-cgal-${CGAL_VER}w${OS_BUILD}${GCC_TYPE}/bin/libCGAL.dll $outdir/bin
fi
#cp extensions/postgis_topology/sql/* ${RELDIR}/${RELVERDIR}/share/extension
#cp extensions/postgis_topology/*.control ${RELDIR}/${RELVERDIR}/share/extension
cp -r ${RELDIR}/packaging_notes/* ${RELDIR}/${RELVERDIR}/
-echo "pgRouting http://pgrouting.org : ${PGROUTING_VER}.${PGROUTING_MICRO_VER}" > $verfile
+echo "The git commit is ${GIT_COMMIT}"
+echo "pgRouting http://pgrouting.org : ${PGROUTING_VER}.${PGROUTING_MICRO_VER} ${GIT_COMMIT}" > $verfile
echo "PostgreSQL http://www.postgresql.org : ${PG_VER} ${OS_BUILD} ${GCC_TYPE}" >> $verfile
echo "CGAL http://www.cgal.org : ${CGAL_VER}" >> $verfile
echo "BOOST http://www.boost.org : ${BOOST_VER}" >> $verfile
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/pgrouting.git
More information about the Pkg-grass-devel
mailing list