Replace dynamic distance calculation for table plugin with pre-calculated distances on shortcuts, avoiding unpacking cost.
Adds approx 10% to total data size. Speeds up large table requests by 2 orders of magnitude. Co-authored-by: Kajari Ghosh <ghoshkaj@gmail.com>
This commit is contained in:
parent
5327f8da4e
commit
498259b220
@ -1,7 +1,9 @@
|
|||||||
# UNRELEASED
|
# UNRELEASED
|
||||||
- Changes from 5.19.0:
|
- Changes from 5.19.0:
|
||||||
|
- Table:
|
||||||
|
- CHANGED: switch to pre-calculated distances for table responses for large speedup and 10% memory increase. [#5251](https://github.com/Project-OSRM/osrm-backend/pull/5251)
|
||||||
- Features:
|
- Features:
|
||||||
- ADDED: direct mmapping of datafiles is now supported via the `-mmap` switch. [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
|
- ADDED: direct mmapping of datafiles is now supported via the `--mmap` switch. [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
|
||||||
- REMOVED: the previous `--memory_file` switch is now deprecated and will fallback to `--mmap` [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
|
- REMOVED: the previous `--memory_file` switch is now deprecated and will fallback to `--mmap` [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
|
||||||
- Windows:
|
- Windows:
|
||||||
- FIXED: Windows builds again. [#5249](https://github.com/Project-OSRM/osrm-backend/pull/5249)
|
- FIXED: Windows builds again. [#5249](https://github.com/Project-OSRM/osrm-backend/pull/5249)
|
||||||
|
@ -5,21 +5,49 @@ Feature: Basic Distance Matrix
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
|
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
|
||||||
|
Scenario: Testbot - Travel distance matrix of small grid
|
||||||
Scenario: Testbot - Travel distance matrix of minimal network
|
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b
|
a b c
|
||||||
|
d e f
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
| ab |
|
| abc |
|
||||||
|
| def |
|
||||||
|
| ad |
|
||||||
|
| be |
|
||||||
|
| cf |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b |
|
| | a | b | e | f |
|
||||||
| a | 0 | 100+-1 |
|
| a | 0 | 100.1 | 199.5 | 299.5 |
|
||||||
| b | 100+-1 | 0 |
|
| b | 100.1 | 0 | 99.4 | 199.5 |
|
||||||
|
| e | 199.5 | 99.4 | 0 | 100.1 |
|
||||||
|
| f | 299.5 | 199.5 | 100.1 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel distance matrix of minimal network exact distances
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a z
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| az |
|
||||||
|
| zbcd |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | z | b | c | d |
|
||||||
|
| a | 0 | 100.1 | 199.5 | 298.9 | 398.3 |
|
||||||
|
| z | 100.1 | 0 | 99.4 | 198.8 | 298.2 |
|
||||||
|
| b | 199.5 | 99.4 | 0 | 99.4 | 198.8 |
|
||||||
|
| c | 298.9 | 198.8 | 99.4 | 0 | 99.4 |
|
||||||
|
| d | 398.3 | 298.2 | 198.8 | 99.4 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix of minimal network with toll exclude
|
Scenario: Testbot - Travel distance matrix of minimal network with toll exclude
|
||||||
Given the query options
|
Given the query options
|
||||||
@ -39,11 +67,11 @@ Feature: Basic Distance Matrix
|
|||||||
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 100+-1 | | |
|
| a | 0 | 100.1 | | |
|
||||||
| b | 100+-1 | 0 | | |
|
| b | 100.1 | 0 | | |
|
||||||
| c | | | 0 | 100+-1 |
|
| c | | | 0 | 100.1 |
|
||||||
| d | | | 100+-1 | 0 |
|
| d | | | 100.1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix of minimal network with motorway exclude
|
Scenario: Testbot - Travel distance matrix of minimal network with motorway exclude
|
||||||
Given the query options
|
Given the query options
|
||||||
@ -63,8 +91,8 @@ Feature: Basic Distance Matrix
|
|||||||
| bd | residential | |
|
| bd | residential | |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 300+-2 | 100+-2 | 200+-2 |
|
| a | 0 | 298.9 | 99.4 | 199.5 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix of minimal network disconnected motorway exclude
|
Scenario: Testbot - Travel distance matrix of minimal network disconnected motorway exclude
|
||||||
Given the query options
|
Given the query options
|
||||||
@ -84,8 +112,8 @@ Feature: Basic Distance Matrix
|
|||||||
| efgh | residential | |
|
| efgh | residential | |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e |
|
| | a | b | e |
|
||||||
| a | 0 | 50+-1 | |
|
| a | 0 | 50.1 | |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix of minimal network with motorway and toll excludes
|
Scenario: Testbot - Travel distance matrix of minimal network with motorway and toll excludes
|
||||||
Given the query options
|
Given the query options
|
||||||
@ -106,7 +134,7 @@ Feature: Basic Distance Matrix
|
|||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | g |
|
| | a | b | e | g |
|
||||||
| a | 0 | 100+-1 | | |
|
| a | 0 | 100.1 | | |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix with different way speeds
|
Scenario: Testbot - Travel distance matrix with different way speeds
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -121,22 +149,22 @@ Feature: Basic Distance Matrix
|
|||||||
| cd | tertiary |
|
| cd | tertiary |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
| a | 0 | 100.1 | 200.1 | 300.2 |
|
||||||
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
| b | 100.1 | 0 | 100.1 | 200.1 |
|
||||||
| c | 200+-1 | 100+-1 | 0 | 100+-1 |
|
| c | 200.1 | 100.1 | 0 | 100.1 |
|
||||||
| d | 300+-1 | 200+-1 | 100+-1 | 0 |
|
| d | 300.2 | 200.1 | 100.1 | 0 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
| a | 0 | 100.1 | 200.1 | 300.2 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a |
|
| | a |
|
||||||
| a | 0 |
|
| a | 0 |
|
||||||
| b | 100+-1 |
|
| b | 100.1 |
|
||||||
| c | 200+-1 |
|
| c | 200.1 |
|
||||||
| d | 300+-1 |
|
| d | 300.2 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix of small grid
|
Scenario: Testbot - Travel distance matrix of small grid
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -154,11 +182,11 @@ Feature: Basic Distance Matrix
|
|||||||
| cf |
|
| cf |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
| a | 0 | 100.1 | 199.5 | 299.5 |
|
||||||
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
| b | 100.1 | 0 | 99.4 | 199.5 |
|
||||||
| e | 200+-1 | 100+-1 | 0 | 100+-1 |
|
| e | 199.5 | 99.4 | 0 | 100.1 |
|
||||||
| f | 300+-1 | 200+-1 | 100+-1 | 0 |
|
| f | 299.5 | 199.5 | 100.1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix of network with unroutable parts
|
Scenario: Testbot - Travel distance matrix of network with unroutable parts
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -172,7 +200,7 @@ Feature: Basic Distance Matrix
|
|||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b |
|
| | a | b |
|
||||||
| a | 0 | 100+-1 |
|
| a | 0 | 100.1 |
|
||||||
| b | | 0 |
|
| b | | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix of network with oneways
|
Scenario: Testbot - Travel distance matrix of network with oneways
|
||||||
@ -189,11 +217,11 @@ Feature: Basic Distance Matrix
|
|||||||
| by | |
|
| by | |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | x | y | d | e |
|
| | x | y | d | e |
|
||||||
| x | 0 | 300+-2 | 400+-2 | 300+-2 |
|
| x | 0 | 300.2 | 399.6 | 299.5 |
|
||||||
| y | 500+-2 | 0 | 300+-2 | 200+-2 |
|
| y | 499 | 0 | 299.5 | 199.5 |
|
||||||
| d | 200+-2 | 300+-2 | 0 | 300+-2 |
|
| d | 199.5 | 299.5 | 0 | 298.9 |
|
||||||
| e | 300+-2 | 400+-2 | 100+-2 | 0 |
|
| e | 299.5 | 399.6 | 100.1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Rectangular travel distance matrix
|
Scenario: Testbot - Rectangular travel distance matrix
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -212,53 +240,53 @@ Feature: Basic Distance Matrix
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | distance |
|
| from | to | distance |
|
||||||
| e | a | 200m +- 1 |
|
| e | a | 200m |
|
||||||
| e | b | 100m +- 1 |
|
| e | b | 100m |
|
||||||
| f | a | 300m +- 1 |
|
| f | a | 299.9m |
|
||||||
| f | b | 200m +- 1 |
|
| f | b | 200m |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
| a | 0 | 100.1 | 199.5 | 299.5 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a |
|
| | a |
|
||||||
| a | 0 |
|
| a | 0 |
|
||||||
| b | 100+-1 |
|
| b | 100.1 |
|
||||||
| e | 200+-1 |
|
| e | 199.5 |
|
||||||
| f | 300+-1 |
|
| f | 299.5 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
| a | 0 | 100.1 | 199.5 | 299.5 |
|
||||||
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
| b | 100.1 | 0 | 99.4 | 199.5 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b |
|
| | a | b |
|
||||||
| a | 0 | 100+-1 |
|
| a | 0 | 100.1 |
|
||||||
| b | 100+-1 | 0 |
|
| b | 100.1 | 0 |
|
||||||
| e | 200+-1 | 100+-1 |
|
| e | 199.5 | 99.4 |
|
||||||
| f | 300+-1 | 200+-1 |
|
| f | 299.5 | 199.5 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
| a | 0 | 100.1 | 199.5 | 299.5 |
|
||||||
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
| b | 100.1 | 0 | 99.4 | 199.5 |
|
||||||
| e | 200+-1 | 100+-1 | 0 | 100+-1 |
|
| e | 199.5 | 99.4 | 0 | 100.1 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e |
|
| | a | b | e |
|
||||||
| a | 0 | 100+-1 | 200+-1 |
|
| a | 0 | 100.1 | 199.5 |
|
||||||
| b | 100+-1 | 0 | 100+-1 |
|
| b | 100.1 | 0 | 99.4 |
|
||||||
| e | 200+-1 | 100+-1 | 0 |
|
| e | 199.5 | 99.4 | 0 |
|
||||||
| f | 300+-1 | 200+-1 | 100+-1 |
|
| f | 299.5 | 199.5 | 100.1 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
| a | 0 | 100.1 | 199.5 | 299.5 |
|
||||||
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
| b | 100.1 | 0 | 99.4 | 199.5 |
|
||||||
| e | 200+-1 | 100+-1 | 0 | 100+-1 |
|
| e | 199.5 | 99.4 | 0 | 100.1 |
|
||||||
| f | 300+-1 | 200+-1 | 100+-1 | 0 |
|
| f | 299.5 | 199.5 | 100.1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance 3x2 matrix
|
Scenario: Testbot - Travel distance 3x2 matrix
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -277,9 +305,9 @@ Feature: Basic Distance Matrix
|
|||||||
|
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | b | e | f |
|
| | b | e | f |
|
||||||
| a | 100+-1 | 200+-1 | 300+-1 |
|
| a | 100.1 | 199.5 | 299.5 |
|
||||||
| b | 0 | 100+-1 | 200+-1 |
|
| b | 0 | 99.4 | 199.5 |
|
||||||
|
|
||||||
Scenario: Testbot - All coordinates are from same small component
|
Scenario: Testbot - All coordinates are from same small component
|
||||||
Given a grid size of 300 meters
|
Given a grid size of 300 meters
|
||||||
@ -299,9 +327,9 @@ Feature: Basic Distance Matrix
|
|||||||
| fg |
|
| fg |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | f | g |
|
| | f | g |
|
||||||
| f | 0 | 300+-2 |
|
| f | 0 | 298.2 |
|
||||||
| g | 300+-2 | 0 |
|
| g | 298.2 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Coordinates are from different small component and snap to big CC
|
Scenario: Testbot - Coordinates are from different small component and snap to big CC
|
||||||
Given a grid size of 300 meters
|
Given a grid size of 300 meters
|
||||||
@ -333,11 +361,11 @@ Feature: Basic Distance Matrix
|
|||||||
| i | h | 300m |
|
| i | h | 300m |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | f | g | h | i |
|
| | f | g | h | i |
|
||||||
| f | 0 | 300+-2 | 0 | 300+-2 |
|
| f | 0 | 298.2 | 0 | 298.2 |
|
||||||
| g | 300+-2 | 0 | 300+-2 | 0 |
|
| g | 298.2 | 0 | 298.2 | 0 |
|
||||||
| h | 0 | 300+-2 | 0 | 300+-2 |
|
| h | 0 | 298.2 | 0 | 298.2 |
|
||||||
| i | 300+-2 | 0 | 300+-2 | 0 |
|
| i | 298.2 | 0 | 298.2 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix with loops
|
Scenario: Testbot - Travel distance matrix with loops
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -354,11 +382,11 @@ Feature: Basic Distance Matrix
|
|||||||
| da | yes |
|
| da | yes |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | 1 | 2 | 3 | 4 |
|
| | 1 | 2 | 3 | 4 |
|
||||||
| 1 | 0 | 100+-1 | 400+-1 | 500+-1 |
|
| 1 | 0 | 100.1 | 399.6 | 499.7 |
|
||||||
| 2 | 700+-1 | 0 | 300+-1 | 400+-1 |
|
| 2 | 699.1 | 0 | 299.5 | 399.6 |
|
||||||
| 3 | 400+-1 | 500+-1 | 0 | 100+-1 |
|
| 3 | 399.6 | 499.7 | 0 | 100.1 |
|
||||||
| 4 | 300+-1 | 400+-1 | 700+-1 | 0 |
|
| 4 | 299.5 | 399.6 | 699.1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix based on segment durations
|
Scenario: Testbot - Travel distance matrix based on segment durations
|
||||||
@ -395,12 +423,12 @@ Feature: Basic Distance Matrix
|
|||||||
| ce |
|
| ce |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d | e |
|
| | a | b | c | d | e |
|
||||||
| a | 0 | 100+-2 | 200+-2 | 300+-2 | 400+-2 |
|
| a | 0 | 100.1 | 200.1 | 300.2 | 398.9 |
|
||||||
| b | 100+-2 | 0 | 100+-2 | 200+-2 | 300+-2 |
|
| b | 100.1 | 0 | 100.1 | 200.1 | 298.9 |
|
||||||
| c | 200+-2 | 100+-2 | 0 | 100+-2 | 200+-2 |
|
| c | 200.1 | 100.1 | 0 | 100.1 | 198.8 |
|
||||||
| d | 300+-2 | 200+-2 | 100+-2 | 0 | 300+-2 |
|
| d | 300.2 | 200.1 | 100.1 | 0 | 298.9 |
|
||||||
| e | 400+-2 | 300+-2 | 200+-2 | 300+-2 | 0 |
|
| e | 398.9 | 298.9 | 198.8 | 298.9 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix for alternative loop paths
|
Scenario: Testbot - Travel distance matrix for alternative loop paths
|
||||||
Given the profile file
|
Given the profile file
|
||||||
@ -439,26 +467,26 @@ Feature: Basic Distance Matrix
|
|||||||
| ca | yes |
|
| ca | yes |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
| 1 | 0 | 1100+-5 | 300+-5 | 200+-5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 |
|
| 1 | 0 | 1096.7 | 298.9 | 199.5 | 598.4 | 498.3 | 897.3 | 797.9 |
|
||||||
| 2 | 100+-5 | 0 | 400+-5 | 300+-5 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 |
|
| 2 | 100.1 | 0 | 398.9 | 299.5 | 698.5 | 598.4 | 997.3 | 897.9 |
|
||||||
| 3 | 900+-5 | 800+-5 | 0 | 1100+-5 | 300+-5 | 200+-5 | 600+-5 | 500+-5 |
|
| 3 | 897.9 | 797.9 | 0 | 1097.4 | 299.5 | 199.5 | 598.4 | 499 |
|
||||||
| 4 | 1000+-5 | 900+-5 | 100+-5 | 0 | 400+-5 | 300+-5 | 700+-5 | 600+-5 |
|
| 4 | 997.3 | 897.3 | 99.4 | 0 | 398.9 | 298.9 | 697.8 | 598.4 |
|
||||||
| 5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 | 0 | 1100+-5 | 300+-5 | 200+-5 |
|
| 5 | 598.4 | 498.3 | 897.3 | 797.9 | 0 | 1096.7 | 298.9 | 199.5 |
|
||||||
| 6 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 | 100+-5 | 0 | 400+-5 | 300+-5 |
|
| 6 | 698.5 | 598.4 | 997.3 | 897.9 | 100.1 | 0 | 398.9 | 299.5 |
|
||||||
| 7 | 300+-5 | 200+-5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 | 0 | 1100+-5 |
|
| 7 | 299.5 | 199.5 | 598.4 | 499 | 897.9 | 797.9 | 0 | 1097.4 |
|
||||||
| 8 | 400+-5 | 300+-5 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 | 100+-5 | 0 |
|
| 8 | 398.9 | 298.9 | 697.8 | 598.4 | 997.3 | 897.3 | 99.4 | 0 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | 1 |
|
| | 1 |
|
||||||
| 1 | 0 |
|
| 1 | 0 |
|
||||||
| 2 | 100+-5 |
|
| 2 | 100.1 |
|
||||||
| 3 | 900+-5 |
|
| 3 | 897.9 |
|
||||||
| 4 | 1000+-5 |
|
| 4 | 997.3 |
|
||||||
| 5 | 600+-5 |
|
| 5 | 598.4 |
|
||||||
| 6 | 700+-5 |
|
| 6 | 698.5 |
|
||||||
| 7 | 300+-5 |
|
| 7 | 299.5 |
|
||||||
| 8 | 400+-5 |
|
| 8 | 398.9 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel distance matrix with ties
|
Scenario: Testbot - Travel distance matrix with ties
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -480,26 +508,26 @@ Feature: Basic Distance Matrix
|
|||||||
| a | c | ac,ac | 200m | 20s | 20 |
|
| a | c | ac,ac | 200m | 20s | 20 |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | distance |
|
| from | to | route | distance |
|
||||||
| a | b | ab,ab | 450m |
|
| a | b | ab,ab | 450m |
|
||||||
| a | c | ac,ac | 200m |
|
| a | c | ac,ac | 200m |
|
||||||
| a | d | ac,dc,dc | 500m +- 1 |
|
| a | d | ac,dc,dc | 499.9m |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 450+-2 | 200+-2 | 500+-2 |
|
| a | 0 | 450.3 | 198.8 | 499 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a |
|
| | a |
|
||||||
| a | 0 |
|
| a | 0 |
|
||||||
| b | 450+-2 |
|
| b | 450.3 |
|
||||||
| c | 200+-2 |
|
| c | 198.8 |
|
||||||
| d | 500+-2 |
|
| d | 499 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | c |
|
| | a | c |
|
||||||
| a | 0 | 200+-2 |
|
| a | 0 | 198.8 |
|
||||||
| c | 200+-2 | 0 |
|
| c | 198.8 | 0 |
|
||||||
|
|
||||||
|
|
||||||
# Check rounding errors
|
# Check rounding errors
|
||||||
@ -515,8 +543,8 @@ Feature: Basic Distance Matrix
|
|||||||
| abcd |
|
| abcd |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 1000+-3 | 2000+-3 | 3000+-3 |
|
| a | 0 | 1000.7 | 2001.4 | 3002.1 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Testbot - OneToMany vs ManyToOne
|
Scenario: Testbot - OneToMany vs ManyToOne
|
||||||
@ -560,10 +588,10 @@ Feature: Basic Distance Matrix
|
|||||||
| fd | |
|
| fd | |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d | e | f |
|
| | a | b | c | d | e | f |
|
||||||
| a | 0 | 100+-1 | 300+-1 | 650+-1 | 1930+-1 | 1533+-1 |
|
| a | 0 | 100.1 | 300.2 | 650.5 | 1930.6 | 1533 |
|
||||||
| b | 760+-1 | 0 | 200+-1 | 550+-1 | 1830+-1 | 1433+-1 |
|
| b | 759 | 0 | 200.1 | 550.4 | 1830.5 | 1432.9 |
|
||||||
| c | 560+-2 | 660+-2 | 0 | 350+-1 | 1630+-1 | 1233+-1 |
|
| c | 558.8 | 658.9 | 0 | 350.3 | 1630.4 | 1232.8 |
|
||||||
| d | 1480+-2 | 1580+-1 | 1780+-1 | 0 | 1280+-1 | 883+-1 |
|
| d | 1478.9 | 1579 | 1779.1 | 0 | 1280.1 | 882.5 |
|
||||||
| e | 200+-2 | 300+-2 | 500+-1 | 710+-1 | 0 | 1593+-1 |
|
| e | 198.8 | 298.9 | 499 | 710.3 | 0 | 1592.8 |
|
||||||
| f | 597+-1 | 696+-1 | 896+-1 | 1108+-1 | 400+-3 | 0 |
|
| f | 596.4 | 696.5 | 896.6 | 1107.9 | 397.6 | 0 |
|
||||||
|
@ -38,15 +38,15 @@ Feature: Multi level routing
|
|||||||
Scenario: Testbot - Multi level routing
|
Scenario: Testbot - Multi level routing
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a───b e───f
|
a────b e─────f
|
||||||
│ │ │ │
|
\ │ │ /
|
||||||
d───c h───g
|
d───c h───g
|
||||||
╲ ╱
|
╲ ╱
|
||||||
╳
|
╳
|
||||||
╱ ╲
|
╱ ╲
|
||||||
i───j m───n
|
i───j m───n
|
||||||
│ │ │ │
|
/ │ │ \
|
||||||
l───k───p───o
|
l─────k───p─────o
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the nodes
|
And the nodes
|
||||||
@ -67,78 +67,76 @@ Feature: Multi level routing
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| a | b | abcda,abcda | 20s |
|
| a | b | abcda,abcda | 25s |
|
||||||
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 229.4s |
|
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 239.2s |
|
||||||
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 144.7s |
|
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 157.1s |
|
||||||
| a | o | abcda,cm,mnopm,mnopm,mnopm | 124.7s |
|
| a | o | abcda,cm,mnopm,mnopm,mnopm | 137.1s |
|
||||||
| f | l | efghe,hj,ijkli,ijkli,ijkli | 124.7s |
|
| f | l | efghe,hj,ijkli,ijkli | 136.7s |
|
||||||
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 144.7s |
|
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 162.1s |
|
||||||
| l | o | ijkli,kp,mnopm,mnopm | 60s |
|
| l | o | ijkli,kp,mnopm,mnopm | 80s |
|
||||||
| c | m | cm,cm | 44.7s |
|
| c | m | cm,cm | 44.7s |
|
||||||
|
| f | a | efghe,hj,ijkli,kp,mnopm,cm,abcda,abcda | 239.2s |
|
||||||
|
| l | a | ijkli,kp,mnopm,cm,abcda,abcda | 157.1s |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel time matrix I should get
|
||||||
| | a | f | l | o |
|
| | a | f | l | o |
|
||||||
| a | 0 | 229.4 | 144.7 | 124.7 |
|
| a | 0 | 239.2 | 157.1 | 137.1 |
|
||||||
| f | 229.4 | 0 | 124.7 | 144.7 |
|
| f | 239.2 | 0 | 136.7 | 162.1 |
|
||||||
| l | 144.7 | 124.7 | 0 | 60 |
|
| l | 157.1 | 136.7 | 0 | 80 |
|
||||||
| o | 124.7 | 144.7 | 60 | 0 |
|
| o | 137.1 | 162.1 | 80 | 0 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel time matrix I should get
|
||||||
| | a | f | l | o |
|
| | a | f | l | o |
|
||||||
| a | 0 | 229.4 | 144.7 | 124.7 |
|
| a | 0 | 239.2 | 157.1 | 137.1 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel time matrix I should get
|
||||||
| | a |
|
| | a |
|
||||||
| a | 0 |
|
| a | 0 |
|
||||||
| f | 229.4 |
|
| f | 239.2 |
|
||||||
| l | 144.7 |
|
| l | 157.1 |
|
||||||
| o | 124.7 |
|
| o | 137.1 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel time matrix I should get
|
||||||
| | a | f | l | o |
|
| | a | f | l | o |
|
||||||
| a | 0 | 229.4 | 144.7 | 124.7 |
|
| a | 0 | 239.2 | 157.1 | 137.1 |
|
||||||
| o | 124.7 | 144.7 | 60 | 0 |
|
| o | 137.1 | 162.1 | 80 | 0 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel time matrix I should get
|
||||||
| | a | o |
|
| | a | o |
|
||||||
| a | 0 | 124.7 |
|
| a | 0 | 137.1 |
|
||||||
| f | 229.4 | 144.7 |
|
| f | 239.2 | 162.1 |
|
||||||
| l | 144.7 | 60 |
|
| l | 157.1 | 80 |
|
||||||
| o | 124.7 | 0 |
|
| o | 137.1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | f | l | o |
|
| | a | f | l | o |
|
||||||
| a | 0+-2 | 2287+-2 | 1443+-2 | 1243+-2 |
|
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
|
||||||
| f | 2284+-2 | 0+-2 | 1241+-2 | 1443+-2 |
|
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
|
||||||
| l | 1443+-2 | 1244+-2 | 0+-2 | 600+-2 |
|
| l | 1618.3 | 1293.3 | 0 | 800.5 |
|
||||||
| o | 1243+-2 | 1444+-2 | 600+-2 | 0+-2 |
|
| o | 1418.2 | 1617.3 | 800.5 | 0 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | f | l | o |
|
| | a | f | l | o |
|
||||||
| a | 0 | 2287.2+-2 | 1443+-2 | 1243+-2 |
|
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a |
|
| | a |
|
||||||
| a | 0 |
|
| a | 0 |
|
||||||
| f | 2284.5+-2 |
|
| f | 2339.9 |
|
||||||
| l | 1443.1 |
|
| l | 1618.3 |
|
||||||
| o | 1243 |
|
| o | 1418.2 |
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | f | l | o |
|
| | a | f | l | o |
|
||||||
| a | 0 | 2287+-2 | 1443+-2 | 1243+-2 |
|
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
|
||||||
| o | 1243 | 1444+-2 | 600+-2 | 0+-2 |
|
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
|
||||||
|
|
||||||
|
|
||||||
When I request a travel distance matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | o |
|
| | a | o |
|
||||||
| a | 0+-2 | 1243+-2 |
|
| a | 0 | 1366.8 |
|
||||||
| f | 2284+-2 | 1443+-2 |
|
| f | 2339.9 | 1522.1 |
|
||||||
| l | 1443+-2 | 600+-2 |
|
| l | 1618.3 | 800.5 |
|
||||||
| o | 1243+-2 | 0+-2 |
|
| o | 1418.2 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scenario: Testbot - Multi level routing: horizontal road
|
Scenario: Testbot - Multi level routing: horizontal road
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -12,23 +12,26 @@ namespace contractor
|
|||||||
struct ContractorEdgeData
|
struct ContractorEdgeData
|
||||||
{
|
{
|
||||||
ContractorEdgeData()
|
ContractorEdgeData()
|
||||||
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
|
: weight(0), duration(0), distance(0), id(0), originalEdges(0), shortcut(0), forward(0),
|
||||||
|
backward(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ContractorEdgeData(EdgeWeight weight,
|
ContractorEdgeData(EdgeWeight weight,
|
||||||
EdgeWeight duration,
|
EdgeWeight duration,
|
||||||
|
EdgeDistance distance,
|
||||||
unsigned original_edges,
|
unsigned original_edges,
|
||||||
unsigned id,
|
unsigned id,
|
||||||
bool shortcut,
|
bool shortcut,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool backward)
|
bool backward)
|
||||||
: weight(weight), duration(duration), id(id),
|
: weight(weight), duration(duration), distance(distance), id(id),
|
||||||
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
|
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
|
||||||
forward(forward), backward(backward)
|
forward(forward), backward(backward)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
|
EdgeDistance distance;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned originalEdges : 29;
|
unsigned originalEdges : 29;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
|
@ -41,6 +41,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
input_edge.target,
|
input_edge.target,
|
||||||
std::max(input_edge.data.weight, 1),
|
std::max(input_edge.data.weight, 1),
|
||||||
input_edge.data.duration,
|
input_edge.data.duration,
|
||||||
|
input_edge.data.distance,
|
||||||
1,
|
1,
|
||||||
input_edge.data.turn_id,
|
input_edge.data.turn_id,
|
||||||
false,
|
false,
|
||||||
@ -51,6 +52,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
input_edge.source,
|
input_edge.source,
|
||||||
std::max(input_edge.data.weight, 1),
|
std::max(input_edge.data.weight, 1),
|
||||||
input_edge.data.duration,
|
input_edge.data.duration,
|
||||||
|
input_edge.data.distance,
|
||||||
1,
|
1,
|
||||||
input_edge.data.turn_id,
|
input_edge.data.turn_id,
|
||||||
false,
|
false,
|
||||||
@ -82,6 +84,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
||||||
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
||||||
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
|
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
|
||||||
|
forward_edge.data.distance = reverse_edge.data.distance = MAXIMAL_EDGE_DISTANCE;
|
||||||
// remove parallel edges
|
// remove parallel edges
|
||||||
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||||
{
|
{
|
||||||
@ -90,12 +93,16 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
|
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
|
||||||
forward_edge.data.duration =
|
forward_edge.data.duration =
|
||||||
std::min(edges[i].data.duration, forward_edge.data.duration);
|
std::min(edges[i].data.duration, forward_edge.data.duration);
|
||||||
|
forward_edge.data.distance =
|
||||||
|
std::min(edges[i].data.distance, forward_edge.data.distance);
|
||||||
}
|
}
|
||||||
if (edges[i].data.backward)
|
if (edges[i].data.backward)
|
||||||
{
|
{
|
||||||
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
|
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
|
||||||
reverse_edge.data.duration =
|
reverse_edge.data.duration =
|
||||||
std::min(edges[i].data.duration, reverse_edge.data.duration);
|
std::min(edges[i].data.duration, reverse_edge.data.duration);
|
||||||
|
reverse_edge.data.distance =
|
||||||
|
std::min(edges[i].data.distance, reverse_edge.data.distance);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@ -151,6 +158,7 @@ template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT g
|
|||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
||||||
new_edge.data.weight = data.weight;
|
new_edge.data.weight = data.weight;
|
||||||
new_edge.data.duration = data.duration;
|
new_edge.data.duration = data.duration;
|
||||||
|
new_edge.data.distance = data.distance;
|
||||||
new_edge.data.shortcut = data.shortcut;
|
new_edge.data.shortcut = data.shortcut;
|
||||||
new_edge.data.turn_id = data.id;
|
new_edge.data.turn_id = data.id;
|
||||||
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
|
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
|
||||||
|
@ -17,7 +17,8 @@ struct QueryEdge
|
|||||||
struct EdgeData
|
struct EdgeData
|
||||||
{
|
{
|
||||||
explicit EdgeData()
|
explicit EdgeData()
|
||||||
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false)
|
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false),
|
||||||
|
distance(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,10 +26,11 @@ struct QueryEdge
|
|||||||
const bool shortcut,
|
const bool shortcut,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward)
|
const bool backward)
|
||||||
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
|
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
|
||||||
forward(forward), backward(backward)
|
forward(forward), backward(backward), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +42,7 @@ struct QueryEdge
|
|||||||
turn_id = other.id;
|
turn_id = other.id;
|
||||||
forward = other.forward;
|
forward = other.forward;
|
||||||
backward = other.backward;
|
backward = other.backward;
|
||||||
|
distance = other.distance;
|
||||||
}
|
}
|
||||||
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node
|
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node
|
||||||
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
|
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
|
||||||
@ -50,6 +53,7 @@ struct QueryEdge
|
|||||||
EdgeWeight duration : 30;
|
EdgeWeight duration : 30;
|
||||||
std::uint32_t forward : 1;
|
std::uint32_t forward : 1;
|
||||||
std::uint32_t backward : 1;
|
std::uint32_t backward : 1;
|
||||||
|
EdgeDistance distance;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
|
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
|
||||||
@ -69,7 +73,8 @@ struct QueryEdge
|
|||||||
return (source == right.source && target == right.target &&
|
return (source == right.source && target == right.target &&
|
||||||
data.weight == right.data.weight && data.duration == right.data.duration &&
|
data.weight == right.data.weight && data.duration == right.data.duration &&
|
||||||
data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
|
data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
|
||||||
data.backward == right.data.backward && data.turn_id == right.data.turn_id);
|
data.backward == right.data.backward && data.turn_id == right.data.turn_id &&
|
||||||
|
data.distance == right.data.distance);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ class CellCustomizer
|
|||||||
{
|
{
|
||||||
bool from_clique;
|
bool from_clique;
|
||||||
EdgeDuration duration;
|
EdgeDuration duration;
|
||||||
|
EdgeDistance distance;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -60,7 +61,7 @@ class CellCustomizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
heap.Clear();
|
heap.Clear();
|
||||||
heap.Insert(source, 0, {false, 0});
|
heap.Insert(source, 0, {false, 0, 0});
|
||||||
|
|
||||||
// explore search space
|
// explore search space
|
||||||
while (!heap.Empty() && !destinations_set.empty())
|
while (!heap.Empty() && !destinations_set.empty())
|
||||||
@ -68,8 +69,18 @@ class CellCustomizer
|
|||||||
const NodeID node = heap.DeleteMin();
|
const NodeID node = heap.DeleteMin();
|
||||||
const EdgeWeight weight = heap.GetKey(node);
|
const EdgeWeight weight = heap.GetKey(node);
|
||||||
const EdgeDuration duration = heap.GetData(node).duration;
|
const EdgeDuration duration = heap.GetData(node).duration;
|
||||||
|
const EdgeDistance distance = heap.GetData(node).distance;
|
||||||
|
|
||||||
RelaxNode(graph, cells, allowed_nodes, metric, heap, level, node, weight, duration);
|
RelaxNode(graph,
|
||||||
|
cells,
|
||||||
|
allowed_nodes,
|
||||||
|
metric,
|
||||||
|
heap,
|
||||||
|
level,
|
||||||
|
node,
|
||||||
|
weight,
|
||||||
|
duration,
|
||||||
|
distance);
|
||||||
|
|
||||||
destinations_set.erase(node);
|
destinations_set.erase(node);
|
||||||
}
|
}
|
||||||
@ -77,21 +88,27 @@ class CellCustomizer
|
|||||||
// fill a map of destination nodes to placeholder pointers
|
// fill a map of destination nodes to placeholder pointers
|
||||||
auto weights = cell.GetOutWeight(source);
|
auto weights = cell.GetOutWeight(source);
|
||||||
auto durations = cell.GetOutDuration(source);
|
auto durations = cell.GetOutDuration(source);
|
||||||
|
auto distances = cell.GetOutDistance(source);
|
||||||
for (auto &destination : destinations)
|
for (auto &destination : destinations)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!weights.empty());
|
BOOST_ASSERT(!weights.empty());
|
||||||
BOOST_ASSERT(!durations.empty());
|
BOOST_ASSERT(!durations.empty());
|
||||||
|
BOOST_ASSERT(!distances.empty());
|
||||||
|
|
||||||
const bool inserted = heap.WasInserted(destination);
|
const bool inserted = heap.WasInserted(destination);
|
||||||
weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
|
weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
|
||||||
durations.front() =
|
durations.front() =
|
||||||
inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION;
|
inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION;
|
||||||
|
distances.front() =
|
||||||
|
inserted ? heap.GetData(destination).distance : INVALID_EDGE_DISTANCE;
|
||||||
|
|
||||||
weights.advance_begin(1);
|
weights.advance_begin(1);
|
||||||
durations.advance_begin(1);
|
durations.advance_begin(1);
|
||||||
|
distances.advance_begin(1);
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(weights.empty());
|
BOOST_ASSERT(weights.empty());
|
||||||
BOOST_ASSERT(durations.empty());
|
BOOST_ASSERT(durations.empty());
|
||||||
|
BOOST_ASSERT(distances.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +145,8 @@ class CellCustomizer
|
|||||||
LevelID level,
|
LevelID level,
|
||||||
NodeID node,
|
NodeID node,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration) const
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance) const
|
||||||
{
|
{
|
||||||
auto first_level = level == 1;
|
auto first_level = level == 1;
|
||||||
BOOST_ASSERT(heap.WasInserted(node));
|
BOOST_ASSERT(heap.WasInserted(node));
|
||||||
@ -149,6 +167,7 @@ class CellCustomizer
|
|||||||
auto subcell = cells.GetCell(metric, level - 1, subcell_id);
|
auto subcell = cells.GetCell(metric, level - 1, subcell_id);
|
||||||
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
||||||
auto subcell_duration = subcell.GetOutDuration(node).begin();
|
auto subcell_duration = subcell.GetOutDuration(node).begin();
|
||||||
|
auto subcell_distance = subcell.GetOutDistance(node).begin();
|
||||||
for (auto subcell_weight : subcell.GetOutWeight(node))
|
for (auto subcell_weight : subcell.GetOutWeight(node))
|
||||||
{
|
{
|
||||||
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
||||||
@ -161,20 +180,24 @@ class CellCustomizer
|
|||||||
|
|
||||||
const EdgeWeight to_weight = weight + subcell_weight;
|
const EdgeWeight to_weight = weight + subcell_weight;
|
||||||
const EdgeDuration to_duration = duration + *subcell_duration;
|
const EdgeDuration to_duration = duration + *subcell_duration;
|
||||||
|
const EdgeDistance to_distance = distance + *subcell_distance;
|
||||||
if (!heap.WasInserted(to))
|
if (!heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, {true, to_duration});
|
heap.Insert(to, to_weight, {true, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration) <
|
else if (std::tie(to_weight, to_duration, to_distance) <
|
||||||
std::tie(heap.GetKey(to), heap.GetData(to).duration))
|
std::tie(heap.GetKey(to),
|
||||||
|
heap.GetData(to).duration,
|
||||||
|
heap.GetData(to).distance))
|
||||||
{
|
{
|
||||||
heap.DecreaseKey(to, to_weight);
|
heap.DecreaseKey(to, to_weight);
|
||||||
heap.GetData(to) = {true, to_duration};
|
heap.GetData(to) = {true, to_duration, to_distance};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++subcell_destination;
|
++subcell_destination;
|
||||||
++subcell_duration;
|
++subcell_duration;
|
||||||
|
++subcell_distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,15 +218,18 @@ class CellCustomizer
|
|||||||
{
|
{
|
||||||
const EdgeWeight to_weight = weight + data.weight;
|
const EdgeWeight to_weight = weight + data.weight;
|
||||||
const EdgeDuration to_duration = duration + data.duration;
|
const EdgeDuration to_duration = duration + data.duration;
|
||||||
|
const EdgeDistance to_distance = distance + data.distance;
|
||||||
if (!heap.WasInserted(to))
|
if (!heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, {false, duration + data.duration});
|
heap.Insert(
|
||||||
|
to, to_weight, {false, duration + data.duration, distance + data.distance});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration) <
|
else if (std::tie(to_weight, to_duration, to_distance) <
|
||||||
std::tie(heap.GetKey(to), heap.GetData(to).duration))
|
std::tie(
|
||||||
|
heap.GetKey(to), heap.GetData(to).duration, heap.GetData(to).distance))
|
||||||
{
|
{
|
||||||
heap.DecreaseKey(to, to_weight);
|
heap.DecreaseKey(to, to_weight);
|
||||||
heap.GetData(to) = {false, to_duration};
|
heap.GetData(to) = {false, to_duration, to_distance};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ template <storage::Ownership Ownership> struct CellMetricImpl
|
|||||||
|
|
||||||
Vector<EdgeWeight> weights;
|
Vector<EdgeWeight> weights;
|
||||||
Vector<EdgeDuration> durations;
|
Vector<EdgeDuration> durations;
|
||||||
|
Vector<EdgeDistance> distances;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +58,10 @@ class MultiLevelGraph : public partitioner::MultiLevelGraph<EdgeDataT, Ownership
|
|||||||
|
|
||||||
MultiLevelGraph(PartitionerGraphT &&graph,
|
MultiLevelGraph(PartitionerGraphT &&graph,
|
||||||
Vector<EdgeWeight> node_weights_,
|
Vector<EdgeWeight> node_weights_,
|
||||||
Vector<EdgeDuration> node_durations_)
|
Vector<EdgeDuration> node_durations_,
|
||||||
: node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_))
|
Vector<EdgeDistance> node_distances_)
|
||||||
|
: node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
|
||||||
|
node_distances(std::move(node_distances_))
|
||||||
{
|
{
|
||||||
util::ViewOrVector<PartitionerGraphT::EdgeArrayEntry, storage::Ownership::Container>
|
util::ViewOrVector<PartitionerGraphT::EdgeArrayEntry, storage::Ownership::Container>
|
||||||
original_edge_array;
|
original_edge_array;
|
||||||
@ -83,11 +85,13 @@ class MultiLevelGraph : public partitioner::MultiLevelGraph<EdgeDataT, Ownership
|
|||||||
Vector<EdgeOffset> node_to_edge_offset_,
|
Vector<EdgeOffset> node_to_edge_offset_,
|
||||||
Vector<EdgeWeight> node_weights_,
|
Vector<EdgeWeight> node_weights_,
|
||||||
Vector<EdgeDuration> node_durations_,
|
Vector<EdgeDuration> node_durations_,
|
||||||
|
Vector<EdgeDistance> node_distances_,
|
||||||
Vector<bool> is_forward_edge_,
|
Vector<bool> is_forward_edge_,
|
||||||
Vector<bool> is_backward_edge_)
|
Vector<bool> is_backward_edge_)
|
||||||
: SuperT(std::move(node_array_), std::move(edge_array_), std::move(node_to_edge_offset_)),
|
: SuperT(std::move(node_array_), std::move(edge_array_), std::move(node_to_edge_offset_)),
|
||||||
node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
|
node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
|
||||||
is_forward_edge(is_forward_edge_), is_backward_edge(is_backward_edge_)
|
node_distances(std::move(node_distances_)), is_forward_edge(is_forward_edge_),
|
||||||
|
is_backward_edge(is_backward_edge_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +99,8 @@ class MultiLevelGraph : public partitioner::MultiLevelGraph<EdgeDataT, Ownership
|
|||||||
|
|
||||||
EdgeWeight GetNodeDuration(NodeID node) const { return node_durations[node]; }
|
EdgeWeight GetNodeDuration(NodeID node) const { return node_durations[node]; }
|
||||||
|
|
||||||
|
EdgeDistance GetNodeDistance(NodeID node) const { return node_distances[node]; }
|
||||||
|
|
||||||
bool IsForwardEdge(EdgeID edge) const { return is_forward_edge[edge]; }
|
bool IsForwardEdge(EdgeID edge) const { return is_forward_edge[edge]; }
|
||||||
|
|
||||||
bool IsBackwardEdge(EdgeID edge) const { return is_backward_edge[edge]; }
|
bool IsBackwardEdge(EdgeID edge) const { return is_backward_edge[edge]; }
|
||||||
@ -111,6 +117,7 @@ class MultiLevelGraph : public partitioner::MultiLevelGraph<EdgeDataT, Ownership
|
|||||||
protected:
|
protected:
|
||||||
Vector<EdgeWeight> node_weights;
|
Vector<EdgeWeight> node_weights;
|
||||||
Vector<EdgeDuration> node_durations;
|
Vector<EdgeDuration> node_durations;
|
||||||
|
Vector<EdgeDistance> node_distances;
|
||||||
Vector<bool> is_forward_edge;
|
Vector<bool> is_forward_edge;
|
||||||
Vector<bool> is_backward_edge;
|
Vector<bool> is_backward_edge;
|
||||||
};
|
};
|
||||||
|
@ -23,6 +23,7 @@ inline void read(storage::tar::FileReader &reader,
|
|||||||
{
|
{
|
||||||
storage::serialization::read(reader, name + "/weights", metric.weights);
|
storage::serialization::read(reader, name + "/weights", metric.weights);
|
||||||
storage::serialization::read(reader, name + "/durations", metric.durations);
|
storage::serialization::read(reader, name + "/durations", metric.durations);
|
||||||
|
storage::serialization::read(reader, name + "/distances", metric.distances);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <storage::Ownership Ownership>
|
template <storage::Ownership Ownership>
|
||||||
@ -32,6 +33,7 @@ inline void write(storage::tar::FileWriter &writer,
|
|||||||
{
|
{
|
||||||
storage::serialization::write(writer, name + "/weights", metric.weights);
|
storage::serialization::write(writer, name + "/weights", metric.weights);
|
||||||
storage::serialization::write(writer, name + "/durations", metric.durations);
|
storage::serialization::write(writer, name + "/durations", metric.durations);
|
||||||
|
storage::serialization::write(writer, name + "/distances", metric.distances);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||||
@ -42,6 +44,7 @@ inline void read(storage::tar::FileReader &reader,
|
|||||||
storage::serialization::read(reader, name + "/node_array", graph.node_array);
|
storage::serialization::read(reader, name + "/node_array", graph.node_array);
|
||||||
storage::serialization::read(reader, name + "/node_weights", graph.node_weights);
|
storage::serialization::read(reader, name + "/node_weights", graph.node_weights);
|
||||||
storage::serialization::read(reader, name + "/node_durations", graph.node_durations);
|
storage::serialization::read(reader, name + "/node_durations", graph.node_durations);
|
||||||
|
storage::serialization::read(reader, name + "/node_distances", graph.node_distances);
|
||||||
storage::serialization::read(reader, name + "/edge_array", graph.edge_array);
|
storage::serialization::read(reader, name + "/edge_array", graph.edge_array);
|
||||||
storage::serialization::read(reader, name + "/is_forward_edge", graph.is_forward_edge);
|
storage::serialization::read(reader, name + "/is_forward_edge", graph.is_forward_edge);
|
||||||
storage::serialization::read(reader, name + "/is_backward_edge", graph.is_backward_edge);
|
storage::serialization::read(reader, name + "/is_backward_edge", graph.is_backward_edge);
|
||||||
@ -56,6 +59,7 @@ inline void write(storage::tar::FileWriter &writer,
|
|||||||
storage::serialization::write(writer, name + "/node_array", graph.node_array);
|
storage::serialization::write(writer, name + "/node_array", graph.node_array);
|
||||||
storage::serialization::write(writer, name + "/node_weights", graph.node_weights);
|
storage::serialization::write(writer, name + "/node_weights", graph.node_weights);
|
||||||
storage::serialization::write(writer, name + "/node_durations", graph.node_durations);
|
storage::serialization::write(writer, name + "/node_durations", graph.node_durations);
|
||||||
|
storage::serialization::write(writer, name + "/node_distances", graph.node_distances);
|
||||||
storage::serialization::write(writer, name + "/edge_array", graph.edge_array);
|
storage::serialization::write(writer, name + "/edge_array", graph.edge_array);
|
||||||
storage::serialization::write(writer, name + "/is_forward_edge", graph.is_forward_edge);
|
storage::serialization::write(writer, name + "/is_forward_edge", graph.is_forward_edge);
|
||||||
storage::serialization::write(writer, name + "/is_backward_edge", graph.is_backward_edge);
|
storage::serialization::write(writer, name + "/is_backward_edge", graph.is_backward_edge);
|
||||||
|
@ -78,6 +78,8 @@ template <> class AlgorithmDataFacade<MLD>
|
|||||||
|
|
||||||
virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed
|
virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed
|
||||||
|
|
||||||
|
virtual EdgeDistance GetNodeDistance(const NodeID node) const = 0;
|
||||||
|
|
||||||
virtual bool IsForwardEdge(EdgeID edge) const = 0;
|
virtual bool IsForwardEdge(EdgeID edge) const = 0;
|
||||||
|
|
||||||
virtual bool IsBackwardEdge(EdgeID edge) const = 0;
|
virtual bool IsBackwardEdge(EdgeID edge) const = 0;
|
||||||
|
@ -697,6 +697,11 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
return query_graph.GetNodeDuration(node);
|
return query_graph.GetNodeDuration(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EdgeDistance GetNodeDistance(const NodeID node) const override final
|
||||||
|
{
|
||||||
|
return query_graph.GetNodeDistance(node);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsForwardEdge(const NodeID node) const override final
|
bool IsForwardEdge(const NodeID node) const override final
|
||||||
{
|
{
|
||||||
return query_graph.IsForwardEdge(node);
|
return query_graph.IsForwardEdge(node);
|
||||||
|
@ -25,15 +25,17 @@ struct NodeBucket
|
|||||||
unsigned from_clique_arc : 1;
|
unsigned from_clique_arc : 1;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeDuration duration;
|
EdgeDuration duration;
|
||||||
|
EdgeDistance distance;
|
||||||
|
|
||||||
NodeBucket(NodeID middle_node,
|
NodeBucket(NodeID middle_node,
|
||||||
NodeID parent_node,
|
NodeID parent_node,
|
||||||
bool from_clique_arc,
|
bool from_clique_arc,
|
||||||
unsigned column_index,
|
unsigned column_index,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration)
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance)
|
||||||
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
||||||
from_clique_arc(from_clique_arc), weight(weight), duration(duration)
|
from_clique_arc(from_clique_arc), weight(weight), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,9 +43,10 @@ struct NodeBucket
|
|||||||
NodeID parent_node,
|
NodeID parent_node,
|
||||||
unsigned column_index,
|
unsigned column_index,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration)
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance)
|
||||||
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
||||||
from_clique_arc(false), weight(weight), duration(duration)
|
from_clique_arc(false), weight(weight), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +85,17 @@ void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
|
|||||||
{
|
{
|
||||||
heap.Insert(phantom_node.forward_segment_id.id,
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
-phantom_node.GetForwardWeightPlusOffset(),
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
{phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
|
{phantom_node.forward_segment_id.id,
|
||||||
|
-phantom_node.GetForwardDuration(),
|
||||||
|
-phantom_node.GetForwardDistance()});
|
||||||
}
|
}
|
||||||
if (phantom_node.IsValidReverseSource())
|
if (phantom_node.IsValidReverseSource())
|
||||||
{
|
{
|
||||||
heap.Insert(phantom_node.reverse_segment_id.id,
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
-phantom_node.GetReverseWeightPlusOffset(),
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
{phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
|
{phantom_node.reverse_segment_id.id,
|
||||||
|
-phantom_node.GetReverseDuration(),
|
||||||
|
-phantom_node.GetReverseDistance()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,13 +106,17 @@ void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
|
|||||||
{
|
{
|
||||||
heap.Insert(phantom_node.forward_segment_id.id,
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
phantom_node.GetForwardWeightPlusOffset(),
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
|
{phantom_node.forward_segment_id.id,
|
||||||
|
phantom_node.GetForwardDuration(),
|
||||||
|
phantom_node.GetForwardDistance()});
|
||||||
}
|
}
|
||||||
if (phantom_node.IsValidReverseTarget())
|
if (phantom_node.IsValidReverseTarget())
|
||||||
{
|
{
|
||||||
heap.Insert(phantom_node.reverse_segment_id.id,
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
phantom_node.GetReverseWeightPlusOffset(),
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
|
{phantom_node.reverse_segment_id.id,
|
||||||
|
phantom_node.GetReverseDuration(),
|
||||||
|
phantom_node.GetReverseDistance()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,9 +186,10 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool UseDuration>
|
template <bool UseDuration>
|
||||||
EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
|
std::tuple<EdgeWeight, EdgeDistance> getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
|
||||||
{
|
{
|
||||||
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
||||||
|
EdgeDistance loop_distance = MAXIMAL_EDGE_DISTANCE;
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
@ -198,11 +199,15 @@ EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
|
|||||||
if (to == node)
|
if (to == node)
|
||||||
{
|
{
|
||||||
const auto value = UseDuration ? data.duration : data.weight;
|
const auto value = UseDuration ? data.duration : data.weight;
|
||||||
loop_weight = std::min(loop_weight, value);
|
if (value < loop_weight)
|
||||||
|
{
|
||||||
|
loop_weight = value;
|
||||||
|
loop_distance = data.distance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return loop_weight;
|
return std::make_tuple(loop_weight, loop_distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -509,90 +509,6 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
||||||
}
|
}
|
||||||
|
|
||||||
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
|
|
||||||
// This gives us a packed path (node ids) from the base graph around s and t,
|
|
||||||
// and overlay node ids otherwise. We then have to unpack the overlay clique
|
|
||||||
// edges by recursively descending unpacking the path down to the base graph.
|
|
||||||
|
|
||||||
using UnpackedNodes = std::vector<NodeID>;
|
|
||||||
using UnpackedEdges = std::vector<EdgeID>;
|
|
||||||
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
|
|
||||||
|
|
||||||
template <typename Algorithm, typename... Args>
|
|
||||||
UnpackedPath
|
|
||||||
unpackPathAndCalculateDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|
||||||
const DataFacade<Algorithm> &facade,
|
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
|
||||||
const bool force_loop_forward,
|
|
||||||
const bool force_loop_reverse,
|
|
||||||
EdgeWeight weight_upper_bound,
|
|
||||||
PackedPath packed_path,
|
|
||||||
NodeID middle,
|
|
||||||
Args... args)
|
|
||||||
{
|
|
||||||
EdgeWeight weight = weight_upper_bound;
|
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
|
||||||
const NodeID source_node = !packed_path.empty() ? std::get<0>(packed_path.front()) : middle;
|
|
||||||
|
|
||||||
// Unpack path
|
|
||||||
std::vector<NodeID> unpacked_nodes;
|
|
||||||
std::vector<EdgeID> unpacked_edges;
|
|
||||||
unpacked_nodes.reserve(packed_path.size());
|
|
||||||
unpacked_edges.reserve(packed_path.size());
|
|
||||||
|
|
||||||
unpacked_nodes.push_back(source_node);
|
|
||||||
|
|
||||||
for (auto const &packed_edge : packed_path)
|
|
||||||
{
|
|
||||||
NodeID source, target;
|
|
||||||
bool overlay_edge;
|
|
||||||
std::tie(source, target, overlay_edge) = packed_edge;
|
|
||||||
if (!overlay_edge)
|
|
||||||
{ // a base graph edge
|
|
||||||
unpacked_nodes.push_back(target);
|
|
||||||
unpacked_edges.push_back(facade.FindEdge(source, target));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // an overlay graph edge
|
|
||||||
LevelID level = getNodeQueryLevel(partition, source, args...);
|
|
||||||
CellID parent_cell_id = partition.GetCell(level, source);
|
|
||||||
BOOST_ASSERT(parent_cell_id == partition.GetCell(level, target));
|
|
||||||
|
|
||||||
LevelID sublevel = level - 1;
|
|
||||||
|
|
||||||
// Here heaps can be reused, let's go deeper!
|
|
||||||
forward_heap.Clear();
|
|
||||||
reverse_heap.Clear();
|
|
||||||
forward_heap.Insert(source, 0, {source});
|
|
||||||
reverse_heap.Insert(target, 0, {target});
|
|
||||||
|
|
||||||
// TODO: when structured bindings will be allowed change to
|
|
||||||
// auto [subpath_weight, subpath_source, subpath_target, subpath] = ...
|
|
||||||
EdgeWeight subpath_weight;
|
|
||||||
std::vector<NodeID> subpath_nodes;
|
|
||||||
std::vector<EdgeID> subpath_edges;
|
|
||||||
std::tie(subpath_weight, subpath_nodes, subpath_edges) = search(engine_working_data,
|
|
||||||
facade,
|
|
||||||
forward_heap,
|
|
||||||
reverse_heap,
|
|
||||||
force_loop_forward,
|
|
||||||
force_loop_reverse,
|
|
||||||
weight_upper_bound,
|
|
||||||
sublevel,
|
|
||||||
parent_cell_id);
|
|
||||||
BOOST_ASSERT(!subpath_edges.empty());
|
|
||||||
BOOST_ASSERT(subpath_nodes.size() > 1);
|
|
||||||
BOOST_ASSERT(subpath_nodes.front() == source);
|
|
||||||
BOOST_ASSERT(subpath_nodes.back() == target);
|
|
||||||
unpacked_nodes.insert(
|
|
||||||
unpacked_nodes.end(), std::next(subpath_nodes.begin()), subpath_nodes.end());
|
|
||||||
unpacked_edges.insert(unpacked_edges.end(), subpath_edges.begin(), subpath_edges.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alias to be compatible with the CH-based search
|
// Alias to be compatible with the CH-based search
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
@ -30,7 +30,11 @@ struct HeapData
|
|||||||
struct ManyToManyHeapData : HeapData
|
struct ManyToManyHeapData : HeapData
|
||||||
{
|
{
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
|
EdgeDistance distance;
|
||||||
|
ManyToManyHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
|
||||||
|
: HeapData(p), duration(duration), distance(distance)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||||
@ -75,12 +79,16 @@ struct MultiLayerDijkstraHeapData
|
|||||||
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
|
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
|
||||||
{
|
{
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration)
|
EdgeDistance distance;
|
||||||
: MultiLayerDijkstraHeapData(p), duration(duration)
|
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
|
||||||
|
: MultiLayerDijkstraHeapData(p), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ManyToManyMultiLayerDijkstraHeapData(NodeID p, bool from, EdgeWeight duration)
|
ManyToManyMultiLayerDijkstraHeapData(NodeID p,
|
||||||
: MultiLayerDijkstraHeapData(p, from), duration(duration)
|
bool from,
|
||||||
|
EdgeWeight duration,
|
||||||
|
EdgeDistance distance)
|
||||||
|
: MultiLayerDijkstraHeapData(p, from), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -15,20 +15,25 @@ struct EdgeBasedEdge
|
|||||||
public:
|
public:
|
||||||
struct EdgeData
|
struct EdgeData
|
||||||
{
|
{
|
||||||
EdgeData() : turn_id(0), weight(0), duration(0), forward(false), backward(false) {}
|
EdgeData()
|
||||||
|
: turn_id(0), weight(0), distance(0), duration(0), forward(false), backward(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
EdgeData(const NodeID turn_id,
|
EdgeData(const NodeID turn_id,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
|
const EdgeDistance distance,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward)
|
const bool backward)
|
||||||
: turn_id(turn_id), weight(weight), duration(duration), forward(forward),
|
: turn_id(turn_id), weight(weight), distance(distance), duration(duration),
|
||||||
backward(backward)
|
forward(forward), backward(backward)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID turn_id; // ID of the edge based node (node based edge)
|
NodeID turn_id; // ID of the edge based node (node based edge)
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
|
EdgeDistance distance;
|
||||||
EdgeWeight duration : 30;
|
EdgeWeight duration : 30;
|
||||||
std::uint32_t forward : 1;
|
std::uint32_t forward : 1;
|
||||||
std::uint32_t backward : 1;
|
std::uint32_t backward : 1;
|
||||||
@ -43,6 +48,7 @@ struct EdgeBasedEdge
|
|||||||
const NodeID edge_id,
|
const NodeID edge_id,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward);
|
const bool backward);
|
||||||
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
|
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
|
||||||
@ -53,7 +59,7 @@ struct EdgeBasedEdge
|
|||||||
NodeID target;
|
NodeID target;
|
||||||
EdgeData data;
|
EdgeData data;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
|
static_assert(sizeof(extractor::EdgeBasedEdge) == 24,
|
||||||
"Size of extractor::EdgeBasedEdge type is "
|
"Size of extractor::EdgeBasedEdge type is "
|
||||||
"bigger than expected. This will influence "
|
"bigger than expected. This will influence "
|
||||||
"memory consumption.");
|
"memory consumption.");
|
||||||
@ -67,9 +73,10 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
|
|||||||
const NodeID turn_id,
|
const NodeID turn_id,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward)
|
const bool backward)
|
||||||
: source(source), target(target), data{turn_id, weight, duration, forward, backward}
|
: source(source), target(target), data{turn_id, weight, distance, duration, forward, backward}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +92,7 @@ class EdgeBasedGraphFactory
|
|||||||
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
||||||
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
||||||
void GetEdgeBasedNodeDurations(std::vector<EdgeWeight> &output_node_durations);
|
void GetEdgeBasedNodeDurations(std::vector<EdgeWeight> &output_node_durations);
|
||||||
|
void GetEdgeBasedNodeDistances(std::vector<EdgeDistance> &output_node_distances);
|
||||||
std::uint32_t GetConnectivityChecksum() const;
|
std::uint32_t GetConnectivityChecksum() const;
|
||||||
|
|
||||||
std::uint64_t GetNumberOfEdgeBasedNodes() const;
|
std::uint64_t GetNumberOfEdgeBasedNodes() const;
|
||||||
@ -119,6 +120,7 @@ class EdgeBasedGraphFactory
|
|||||||
//! edge-based node
|
//! edge-based node
|
||||||
std::vector<EdgeWeight> m_edge_based_node_weights;
|
std::vector<EdgeWeight> m_edge_based_node_weights;
|
||||||
std::vector<EdgeDuration> m_edge_based_node_durations;
|
std::vector<EdgeDuration> m_edge_based_node_durations;
|
||||||
|
std::vector<EdgeDistance> m_edge_based_node_distances;
|
||||||
|
|
||||||
//! list of edge based nodes (compressed segments)
|
//! list of edge based nodes (compressed segments)
|
||||||
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
|
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
|
||||||
|
@ -88,6 +88,7 @@ class Extractor
|
|||||||
std::vector<bool> &node_is_startpoint,
|
std::vector<bool> &node_is_startpoint,
|
||||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||||
std::vector<EdgeDuration> &edge_based_node_durations,
|
std::vector<EdgeDuration> &edge_based_node_durations,
|
||||||
|
std::vector<EdgeDistance> &edge_based_node_distances,
|
||||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||||
std::uint32_t &connectivity_checksum);
|
std::uint32_t &connectivity_checksum);
|
||||||
|
|
||||||
|
@ -453,8 +453,8 @@ void writeNames(const boost::filesystem::path &path, const NameTableT &table)
|
|||||||
serialization::write(writer, "/common/names", table);
|
serialization::write(writer, "/common/names", table);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename NodeWeigtsVectorT>
|
template <typename NodeWeightsVectorT>
|
||||||
void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeigtsVectorT &weights)
|
void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeightsVectorT &weights)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::tar::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
@ -462,9 +462,33 @@ void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeigtsVec
|
|||||||
storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights);
|
storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename NodeWeigtsVectorT, typename NodeDurationsVectorT>
|
template <typename NodeDistancesVectorT>
|
||||||
|
void readEdgeBasedNodeDistances(const boost::filesystem::path &path,
|
||||||
|
NodeDistancesVectorT &distances)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/extractor/edge_based_node_distances", distances);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT, typename NodeDistancesVectorT>
|
||||||
|
void writeEdgeBasedNodeWeightsDurationsDistances(const boost::filesystem::path &path,
|
||||||
|
const NodeWeightsVectorT &weights,
|
||||||
|
const NodeDurationsVectorT &durations,
|
||||||
|
const NodeDistancesVectorT &distances)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::write(writer, "/extractor/edge_based_node_weights", weights);
|
||||||
|
storage::serialization::write(writer, "/extractor/edge_based_node_durations", durations);
|
||||||
|
storage::serialization::write(writer, "/extractor/edge_based_node_distances", distances);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT>
|
||||||
void readEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
|
void readEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
|
||||||
NodeWeigtsVectorT &weights,
|
NodeWeightsVectorT &weights,
|
||||||
NodeDurationsVectorT &durations)
|
NodeDurationsVectorT &durations)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
@ -474,9 +498,9 @@ void readEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
|
|||||||
storage::serialization::read(reader, "/extractor/edge_based_node_durations", durations);
|
storage::serialization::read(reader, "/extractor/edge_based_node_durations", durations);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename NodeWeigtsVectorT, typename NodeDurationsVectorT>
|
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT>
|
||||||
void writeEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
|
void writeEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
|
||||||
const NodeWeigtsVectorT &weights,
|
const NodeWeightsVectorT &weights,
|
||||||
const NodeDurationsVectorT &durations)
|
const NodeDurationsVectorT &durations)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
@ -63,7 +63,7 @@ struct InternalExtractorEdge
|
|||||||
WeightData weight_data,
|
WeightData weight_data,
|
||||||
DurationData duration_data,
|
DurationData duration_data,
|
||||||
util::Coordinate source_coordinate)
|
util::Coordinate source_coordinate)
|
||||||
: result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
|
: result(source, target, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
|
||||||
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
|
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ struct NodeBasedEdge
|
|||||||
NodeID target,
|
NodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags);
|
NodeBasedEdgeClassification flags);
|
||||||
@ -107,6 +108,7 @@ struct NodeBasedEdge
|
|||||||
NodeID target; // 32 4
|
NodeID target; // 32 4
|
||||||
EdgeWeight weight; // 32 4
|
EdgeWeight weight; // 32 4
|
||||||
EdgeDuration duration; // 32 4
|
EdgeDuration duration; // 32 4
|
||||||
|
EdgeDistance distance; // 32 4
|
||||||
GeometryID geometry_id; // 32 4
|
GeometryID geometry_id; // 32 4
|
||||||
AnnotationID annotation_data; // 32 4
|
AnnotationID annotation_data; // 32 4
|
||||||
NodeBasedEdgeClassification flags; // 32 4
|
NodeBasedEdgeClassification flags; // 32 4
|
||||||
@ -120,6 +122,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
|||||||
OSMNodeID target,
|
OSMNodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags);
|
NodeBasedEdgeClassification flags);
|
||||||
@ -137,7 +140,8 @@ inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline NodeBasedEdge::NodeBasedEdge()
|
inline NodeBasedEdge::NodeBasedEdge()
|
||||||
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
|
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), distance(0),
|
||||||
|
annotation_data(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,11 +149,12 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
|||||||
NodeID target,
|
NodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags)
|
NodeBasedEdgeClassification flags)
|
||||||
: source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
|
: source(source), target(target), weight(weight), duration(duration), distance(distance),
|
||||||
annotation_data(annotation_data), flags(flags)
|
geometry_id(geometry_id), annotation_data(annotation_data), flags(flags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,11 +180,18 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
|||||||
OSMNodeID target,
|
OSMNodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags)
|
NodeBasedEdgeClassification flags)
|
||||||
: NodeBasedEdge(
|
: NodeBasedEdge(SPECIAL_NODEID,
|
||||||
SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
|
SPECIAL_NODEID,
|
||||||
|
weight,
|
||||||
|
duration,
|
||||||
|
distance,
|
||||||
|
geometry_id,
|
||||||
|
annotation_data,
|
||||||
|
flags),
|
||||||
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -189,7 +201,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(sizeof(extractor::NodeBasedEdge) == 28,
|
static_assert(sizeof(extractor::NodeBasedEdge) == 32,
|
||||||
"Size of extractor::NodeBasedEdge type is "
|
"Size of extractor::NodeBasedEdge type is "
|
||||||
"bigger than expected. This will influence "
|
"bigger than expected. This will influence "
|
||||||
"memory consumption.");
|
"memory consumption.");
|
||||||
|
@ -75,28 +75,35 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
|
|
||||||
// Implementation of the cell view. We need a template parameter here
|
// Implementation of the cell view. We need a template parameter here
|
||||||
// because we need to derive a read-only and read-write view from this.
|
// because we need to derive a read-only and read-write view from this.
|
||||||
template <typename WeightValueT, typename DurationValueT> class CellImpl
|
template <typename WeightValueT, typename DurationValueT, typename DistanceValueT>
|
||||||
|
class CellImpl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using WeightPtrT = WeightValueT *;
|
using WeightPtrT = WeightValueT *;
|
||||||
using DurationPtrT = DurationValueT *;
|
using DurationPtrT = DurationValueT *;
|
||||||
|
using DistancePtrT = DistanceValueT *;
|
||||||
BoundarySize num_source_nodes;
|
BoundarySize num_source_nodes;
|
||||||
BoundarySize num_destination_nodes;
|
BoundarySize num_destination_nodes;
|
||||||
|
|
||||||
WeightPtrT const weights;
|
WeightPtrT const weights;
|
||||||
DurationPtrT const durations;
|
DurationPtrT const durations;
|
||||||
|
DistancePtrT const distances;
|
||||||
const NodeID *const source_boundary;
|
const NodeID *const source_boundary;
|
||||||
const NodeID *const destination_boundary;
|
const NodeID *const destination_boundary;
|
||||||
|
|
||||||
using RowIterator = WeightPtrT;
|
using RowIterator = WeightPtrT;
|
||||||
// Possibly replace with
|
// Possibly replace with
|
||||||
// http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/adaptors/reference/strided.html
|
// http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/adaptors/reference/strided.html
|
||||||
class ColumnIterator : public boost::iterator_facade<ColumnIterator,
|
|
||||||
WeightValueT,
|
template <typename ValuePtrT>
|
||||||
|
class ColumnIterator : public boost::iterator_facade<ColumnIterator<ValuePtrT>,
|
||||||
|
decltype(*std::declval<ValuePtrT>()),
|
||||||
boost::random_access_traversal_tag>
|
boost::random_access_traversal_tag>
|
||||||
{
|
{
|
||||||
typedef boost::iterator_facade<ColumnIterator,
|
|
||||||
WeightValueT,
|
using ValueT = decltype(*std::declval<ValuePtrT>());
|
||||||
|
typedef boost::iterator_facade<ColumnIterator<ValueT>,
|
||||||
|
ValueT,
|
||||||
boost::random_access_traversal_tag>
|
boost::random_access_traversal_tag>
|
||||||
base_t;
|
base_t;
|
||||||
|
|
||||||
@ -108,7 +115,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
|
|
||||||
explicit ColumnIterator() : current(nullptr), stride(1) {}
|
explicit ColumnIterator() : current(nullptr), stride(1) {}
|
||||||
|
|
||||||
explicit ColumnIterator(WeightPtrT begin, std::size_t row_length)
|
explicit ColumnIterator(ValuePtrT begin, std::size_t row_length)
|
||||||
: current(begin), stride(row_length)
|
: current(begin), stride(row_length)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(begin != nullptr);
|
BOOST_ASSERT(begin != nullptr);
|
||||||
@ -126,7 +133,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
friend class ::boost::iterator_core_access;
|
friend class ::boost::iterator_core_access;
|
||||||
WeightPtrT current;
|
ValuePtrT current;
|
||||||
const std::size_t stride;
|
const std::size_t stride;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,12 +154,13 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
auto iter =
|
auto iter =
|
||||||
std::find(destination_boundary, destination_boundary + num_destination_nodes, node);
|
std::find(destination_boundary, destination_boundary + num_destination_nodes, node);
|
||||||
if (iter == destination_boundary + num_destination_nodes)
|
if (iter == destination_boundary + num_destination_nodes)
|
||||||
return boost::make_iterator_range(ColumnIterator{}, ColumnIterator{});
|
return boost::make_iterator_range(ColumnIterator<ValuePtr>{},
|
||||||
|
ColumnIterator<ValuePtr>{});
|
||||||
|
|
||||||
auto column = std::distance(destination_boundary, iter);
|
auto column = std::distance(destination_boundary, iter);
|
||||||
auto begin = ColumnIterator{ptr + column, num_destination_nodes};
|
auto begin = ColumnIterator<ValuePtr>{ptr + column, num_destination_nodes};
|
||||||
auto end = ColumnIterator{ptr + column + num_source_nodes * num_destination_nodes,
|
auto end = ColumnIterator<ValuePtr>{
|
||||||
num_destination_nodes};
|
ptr + column + num_source_nodes * num_destination_nodes, num_destination_nodes};
|
||||||
return boost::make_iterator_range(begin, end);
|
return boost::make_iterator_range(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +173,10 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
|
|
||||||
auto GetInDuration(NodeID node) const { return GetInRange(durations, node); }
|
auto GetInDuration(NodeID node) const { return GetInRange(durations, node); }
|
||||||
|
|
||||||
|
auto GetInDistance(NodeID node) const { return GetInRange(distances, node); }
|
||||||
|
|
||||||
|
auto GetOutDistance(NodeID node) const { return GetOutRange(distances, node); }
|
||||||
|
|
||||||
auto GetSourceNodes() const
|
auto GetSourceNodes() const
|
||||||
{
|
{
|
||||||
return boost::make_iterator_range(source_boundary, source_boundary + num_source_nodes);
|
return boost::make_iterator_range(source_boundary, source_boundary + num_source_nodes);
|
||||||
@ -179,17 +191,20 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
CellImpl(const CellData &data,
|
CellImpl(const CellData &data,
|
||||||
WeightPtrT const all_weights,
|
WeightPtrT const all_weights,
|
||||||
DurationPtrT const all_durations,
|
DurationPtrT const all_durations,
|
||||||
|
DistancePtrT const all_distances,
|
||||||
const NodeID *const all_sources,
|
const NodeID *const all_sources,
|
||||||
const NodeID *const all_destinations)
|
const NodeID *const all_destinations)
|
||||||
: num_source_nodes{data.num_source_nodes},
|
: num_source_nodes{data.num_source_nodes},
|
||||||
num_destination_nodes{data.num_destination_nodes},
|
num_destination_nodes{data.num_destination_nodes},
|
||||||
weights{all_weights + data.value_offset},
|
weights{all_weights + data.value_offset},
|
||||||
durations{all_durations + data.value_offset},
|
durations{all_durations + data.value_offset},
|
||||||
|
distances{all_distances + data.value_offset},
|
||||||
source_boundary{all_sources + data.source_boundary_offset},
|
source_boundary{all_sources + data.source_boundary_offset},
|
||||||
destination_boundary{all_destinations + data.destination_boundary_offset}
|
destination_boundary{all_destinations + data.destination_boundary_offset}
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(all_weights != nullptr);
|
BOOST_ASSERT(all_weights != nullptr);
|
||||||
BOOST_ASSERT(all_durations != nullptr);
|
BOOST_ASSERT(all_durations != nullptr);
|
||||||
|
BOOST_ASSERT(all_distances != nullptr);
|
||||||
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
|
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
|
||||||
BOOST_ASSERT(num_destination_nodes == 0 || all_destinations != nullptr);
|
BOOST_ASSERT(num_destination_nodes == 0 || all_destinations != nullptr);
|
||||||
}
|
}
|
||||||
@ -201,7 +216,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
const NodeID *const all_destinations)
|
const NodeID *const all_destinations)
|
||||||
: num_source_nodes{data.num_source_nodes},
|
: num_source_nodes{data.num_source_nodes},
|
||||||
num_destination_nodes{data.num_destination_nodes}, weights{nullptr},
|
num_destination_nodes{data.num_destination_nodes}, weights{nullptr},
|
||||||
durations{nullptr}, source_boundary{all_sources + data.source_boundary_offset},
|
durations{nullptr}, distances{nullptr},
|
||||||
|
source_boundary{all_sources + data.source_boundary_offset},
|
||||||
destination_boundary{all_destinations + data.destination_boundary_offset}
|
destination_boundary{all_destinations + data.destination_boundary_offset}
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
|
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
|
||||||
@ -212,8 +228,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
std::size_t LevelIDToIndex(LevelID level) const { return level - 1; }
|
std::size_t LevelIDToIndex(LevelID level) const { return level - 1; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Cell = CellImpl<EdgeWeight, EdgeDuration>;
|
using Cell = CellImpl<EdgeWeight, EdgeDuration, EdgeDistance>;
|
||||||
using ConstCell = CellImpl<const EdgeWeight, const EdgeDuration>;
|
using ConstCell = CellImpl<const EdgeWeight, const EdgeDuration, const EdgeDistance>;
|
||||||
|
|
||||||
CellStorageImpl() {}
|
CellStorageImpl() {}
|
||||||
|
|
||||||
@ -361,6 +377,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
|
|
||||||
metric.weights.resize(total_size + 1, INVALID_EDGE_WEIGHT);
|
metric.weights.resize(total_size + 1, INVALID_EDGE_WEIGHT);
|
||||||
metric.durations.resize(total_size + 1, MAXIMAL_EDGE_DURATION);
|
metric.durations.resize(total_size + 1, MAXIMAL_EDGE_DURATION);
|
||||||
|
metric.distances.resize(total_size + 1, INVALID_EDGE_DISTANCE);
|
||||||
|
|
||||||
return metric;
|
return metric;
|
||||||
}
|
}
|
||||||
@ -388,6 +405,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
return ConstCell{cells[cell_index],
|
return ConstCell{cells[cell_index],
|
||||||
metric.weights.data(),
|
metric.weights.data(),
|
||||||
metric.durations.data(),
|
metric.durations.data(),
|
||||||
|
metric.distances.data(),
|
||||||
source_boundary.empty() ? nullptr : source_boundary.data(),
|
source_boundary.empty() ? nullptr : source_boundary.data(),
|
||||||
destination_boundary.empty() ? nullptr : destination_boundary.data()};
|
destination_boundary.empty() ? nullptr : destination_boundary.data()};
|
||||||
}
|
}
|
||||||
@ -415,6 +433,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
return Cell{cells[cell_index],
|
return Cell{cells[cell_index],
|
||||||
metric.weights.data(),
|
metric.weights.data(),
|
||||||
metric.durations.data(),
|
metric.durations.data(),
|
||||||
|
metric.distances.data(),
|
||||||
source_boundary.data(),
|
source_boundary.data(),
|
||||||
destination_boundary.data()};
|
destination_boundary.data()};
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
|
|||||||
edge.data.turn_id,
|
edge.data.turn_id,
|
||||||
std::max(edge.data.weight, 1),
|
std::max(edge.data.weight, 1),
|
||||||
edge.data.duration,
|
edge.data.duration,
|
||||||
|
edge.data.distance,
|
||||||
edge.data.forward,
|
edge.data.forward,
|
||||||
edge.data.backward);
|
edge.data.backward);
|
||||||
|
|
||||||
@ -51,6 +52,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
|
|||||||
edge.data.turn_id,
|
edge.data.turn_id,
|
||||||
std::max(edge.data.weight, 1),
|
std::max(edge.data.weight, 1),
|
||||||
edge.data.duration,
|
edge.data.duration,
|
||||||
|
edge.data.distance,
|
||||||
edge.data.backward,
|
edge.data.backward,
|
||||||
edge.data.forward);
|
edge.data.forward);
|
||||||
}
|
}
|
||||||
|
@ -294,11 +294,14 @@ inline auto make_filtered_cell_metric_view(const SharedDataIndex &index,
|
|||||||
auto prefix = name + "/exclude/" + std::to_string(exclude_index);
|
auto prefix = name + "/exclude/" + std::to_string(exclude_index);
|
||||||
auto weights_block_id = prefix + "/weights";
|
auto weights_block_id = prefix + "/weights";
|
||||||
auto durations_block_id = prefix + "/durations";
|
auto durations_block_id = prefix + "/durations";
|
||||||
|
auto distances_block_id = prefix + "/distances";
|
||||||
|
|
||||||
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
|
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
|
||||||
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
|
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
|
||||||
|
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
|
||||||
|
|
||||||
return customizer::CellMetricView{std::move(weights), std::move(durations)};
|
return customizer::CellMetricView{
|
||||||
|
std::move(weights), std::move(durations), std::move(distances)};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name)
|
inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name)
|
||||||
@ -311,12 +314,14 @@ inline auto make_cell_metric_view(const SharedDataIndex &index, const std::strin
|
|||||||
{
|
{
|
||||||
auto weights_block_id = prefix + "/weights";
|
auto weights_block_id = prefix + "/weights";
|
||||||
auto durations_block_id = prefix + "/durations";
|
auto durations_block_id = prefix + "/durations";
|
||||||
|
auto distances_block_id = prefix + "/distances";
|
||||||
|
|
||||||
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
|
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
|
||||||
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
|
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
|
||||||
|
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
|
||||||
|
|
||||||
cell_metric_excludes.push_back(
|
cell_metric_excludes.push_back(customizer::CellMetricView{
|
||||||
customizer::CellMetricView{std::move(weights), std::move(durations)});
|
std::move(weights), std::move(durations), std::move(distances)});
|
||||||
}
|
}
|
||||||
|
|
||||||
return cell_metric_excludes;
|
return cell_metric_excludes;
|
||||||
@ -332,6 +337,7 @@ inline auto make_multi_level_graph_view(const SharedDataIndex &index, const std:
|
|||||||
index, name + "/node_to_edge_offset");
|
index, name + "/node_to_edge_offset");
|
||||||
auto node_weights = make_vector_view<EdgeWeight>(index, name + "/node_weights");
|
auto node_weights = make_vector_view<EdgeWeight>(index, name + "/node_weights");
|
||||||
auto node_durations = make_vector_view<EdgeDuration>(index, name + "/node_durations");
|
auto node_durations = make_vector_view<EdgeDuration>(index, name + "/node_durations");
|
||||||
|
auto node_distances = make_vector_view<EdgeDistance>(index, name + "/node_distances");
|
||||||
auto is_forward_edge = make_vector_view<bool>(index, name + "/is_forward_edge");
|
auto is_forward_edge = make_vector_view<bool>(index, name + "/is_forward_edge");
|
||||||
auto is_backward_edge = make_vector_view<bool>(index, name + "/is_backward_edge");
|
auto is_backward_edge = make_vector_view<bool>(index, name + "/is_backward_edge");
|
||||||
|
|
||||||
@ -340,6 +346,7 @@ inline auto make_multi_level_graph_view(const SharedDataIndex &index, const std:
|
|||||||
std::move(node_to_offset),
|
std::move(node_to_offset),
|
||||||
std::move(node_weights),
|
std::move(node_weights),
|
||||||
std::move(node_durations),
|
std::move(node_durations),
|
||||||
|
std::move(node_distances),
|
||||||
std::move(is_forward_edge),
|
std::move(is_forward_edge),
|
||||||
std::move(is_backward_edge));
|
std::move(is_backward_edge));
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,17 @@ class Updater
|
|||||||
std::vector<EdgeWeight> &node_weights,
|
std::vector<EdgeWeight> &node_weights,
|
||||||
std::uint32_t &connectivity_checksum) const;
|
std::uint32_t &connectivity_checksum) const;
|
||||||
|
|
||||||
EdgeID
|
EdgeID LoadAndUpdateEdgeExpandedGraph(
|
||||||
LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
|
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
|
||||||
std::vector<EdgeWeight> &node_weights,
|
std::vector<EdgeWeight> &node_weights,
|
||||||
std::vector<EdgeDuration> &node_durations, // TODO: to be deleted
|
std::vector<EdgeDuration> &node_durations, // TODO: remove when optional
|
||||||
std::uint32_t &connectivity_checksum) const;
|
std::uint32_t &connectivity_checksum) const;
|
||||||
|
EdgeID LoadAndUpdateEdgeExpandedGraph(
|
||||||
|
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
|
||||||
|
std::vector<EdgeWeight> &node_weights,
|
||||||
|
std::vector<EdgeDuration> &node_durations, // TODO: remove when optional
|
||||||
|
std::vector<EdgeDistance> &node_distances, // TODO: remove when optional
|
||||||
|
std::uint32_t &connectivity_checksum) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UpdaterConfig config;
|
UpdaterConfig config;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#ifndef OSRM_UTIL_DEBUG_HPP_
|
#ifndef OSRM_UTIL_DEBUG_HPP_
|
||||||
#define OSRM_UTIL_DEBUG_HPP_
|
#define OSRM_UTIL_DEBUG_HPP_
|
||||||
|
|
||||||
|
#include "extractor/edge_based_edge.hpp"
|
||||||
#include "extractor/node_data_container.hpp"
|
#include "extractor/node_data_container.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
#include "guidance/intersection.hpp"
|
#include "guidance/intersection.hpp"
|
||||||
|
#include "guidance/turn_instruction.hpp"
|
||||||
#include "guidance/turn_lane_data.hpp"
|
#include "guidance/turn_lane_data.hpp"
|
||||||
#include "engine/guidance/route_step.hpp"
|
#include "engine/guidance/route_step.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
@ -186,6 +188,23 @@ inline std::ostream &operator<<(std::ostream &out, const LaneDataVector &turn_la
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
inline std::ostream &operator<<(std::ostream &out, const EdgeBasedEdge &edge)
|
||||||
|
{
|
||||||
|
out << " EdgeBasedEdge {";
|
||||||
|
out << " source " << edge.source << ", target: " << edge.target;
|
||||||
|
out << " EdgeBasedEdgeData data {";
|
||||||
|
out << " turn_id: " << edge.data.turn_id << ", weight: " << edge.data.weight;
|
||||||
|
out << " distance: " << edge.data.distance << ", duration: " << edge.data.duration;
|
||||||
|
out << " forward: " << (edge.data.forward == 0 ? "false" : "true")
|
||||||
|
<< ", backward: " << (edge.data.backward == 0 ? "false" : "true");
|
||||||
|
out << " }";
|
||||||
|
out << "}";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/
|
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <tbb/parallel_sort.h>
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -20,24 +21,27 @@ namespace util
|
|||||||
struct NodeBasedEdgeData
|
struct NodeBasedEdgeData
|
||||||
{
|
{
|
||||||
NodeBasedEdgeData()
|
NodeBasedEdgeData()
|
||||||
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), geometry_id({0, false}),
|
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT),
|
||||||
reversed(false), annotation_data(-1)
|
distance(INVALID_EDGE_DISTANCE), geometry_id({0, false}), reversed(false),
|
||||||
|
annotation_data(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeBasedEdgeData(EdgeWeight weight,
|
NodeBasedEdgeData(EdgeWeight weight,
|
||||||
EdgeWeight duration,
|
EdgeWeight duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
bool reversed,
|
bool reversed,
|
||||||
extractor::NodeBasedEdgeClassification flags,
|
extractor::NodeBasedEdgeClassification flags,
|
||||||
AnnotationID annotation_data)
|
AnnotationID annotation_data)
|
||||||
: weight(weight), duration(duration), geometry_id(geometry_id), reversed(reversed),
|
: weight(weight), duration(duration), distance(distance), geometry_id(geometry_id),
|
||||||
flags(flags), annotation_data(annotation_data)
|
reversed(reversed), flags(flags), annotation_data(annotation_data)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
|
EdgeDistance distance;
|
||||||
GeometryID geometry_id;
|
GeometryID geometry_id;
|
||||||
bool reversed : 1;
|
bool reversed : 1;
|
||||||
extractor::NodeBasedEdgeClassification flags;
|
extractor::NodeBasedEdgeClassification flags;
|
||||||
@ -80,11 +84,13 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
|
|||||||
const extractor::NodeBasedEdge &input_edge) {
|
const extractor::NodeBasedEdge &input_edge) {
|
||||||
output_edge.data.weight = input_edge.weight;
|
output_edge.data.weight = input_edge.weight;
|
||||||
output_edge.data.duration = input_edge.duration;
|
output_edge.data.duration = input_edge.duration;
|
||||||
|
output_edge.data.distance = input_edge.distance;
|
||||||
output_edge.data.flags = input_edge.flags;
|
output_edge.data.flags = input_edge.flags;
|
||||||
output_edge.data.annotation_data = input_edge.annotation_data;
|
output_edge.data.annotation_data = input_edge.annotation_data;
|
||||||
|
|
||||||
BOOST_ASSERT(output_edge.data.weight > 0);
|
BOOST_ASSERT(output_edge.data.weight > 0);
|
||||||
BOOST_ASSERT(output_edge.data.duration > 0);
|
BOOST_ASSERT(output_edge.data.duration > 0);
|
||||||
|
BOOST_ASSERT(output_edge.data.distance >= 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||||
|
@ -113,6 +113,7 @@ static const SegmentWeight MAX_SEGMENT_WEIGHT = INVALID_SEGMENT_WEIGHT - 1;
|
|||||||
static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1;
|
static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1;
|
||||||
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
||||||
static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max();
|
static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max();
|
||||||
|
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||||
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
||||||
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||||
|
|
||||||
|
@ -215,6 +215,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
target,
|
target,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
@ -225,6 +226,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
source,
|
source,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
@ -280,6 +282,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
target,
|
target,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
@ -290,6 +293,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
source,
|
source,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
|
@ -76,6 +76,7 @@ auto LoadAndUpdateEdgeExpandedGraph(const CustomizationConfig &config,
|
|||||||
const partitioner::MultiLevelPartition &mlp,
|
const partitioner::MultiLevelPartition &mlp,
|
||||||
std::vector<EdgeWeight> &node_weights,
|
std::vector<EdgeWeight> &node_weights,
|
||||||
std::vector<EdgeDuration> &node_durations,
|
std::vector<EdgeDuration> &node_durations,
|
||||||
|
std::vector<EdgeDistance> &node_distances,
|
||||||
std::uint32_t &connectivity_checksum)
|
std::uint32_t &connectivity_checksum)
|
||||||
{
|
{
|
||||||
updater::Updater updater(config.updater_config);
|
updater::Updater updater(config.updater_config);
|
||||||
@ -84,6 +85,8 @@ auto LoadAndUpdateEdgeExpandedGraph(const CustomizationConfig &config,
|
|||||||
EdgeID num_nodes = updater.LoadAndUpdateEdgeExpandedGraph(
|
EdgeID num_nodes = updater.LoadAndUpdateEdgeExpandedGraph(
|
||||||
edge_based_edge_list, node_weights, node_durations, connectivity_checksum);
|
edge_based_edge_list, node_weights, node_durations, connectivity_checksum);
|
||||||
|
|
||||||
|
extractor::files::readEdgeBasedNodeDistances(config.GetPath(".osrm.enw"), node_distances);
|
||||||
|
|
||||||
auto directed = partitioner::splitBidirectionalEdges(edge_based_edge_list);
|
auto directed = partitioner::splitBidirectionalEdges(edge_based_edge_list);
|
||||||
|
|
||||||
auto tidied = partitioner::prepareEdgesForUsageInGraph<
|
auto tidied = partitioner::prepareEdgesForUsageInGraph<
|
||||||
@ -124,10 +127,11 @@ int Customizer::Run(const CustomizationConfig &config)
|
|||||||
partitioner::files::readPartition(config.GetPath(".osrm.partition"), mlp);
|
partitioner::files::readPartition(config.GetPath(".osrm.partition"), mlp);
|
||||||
|
|
||||||
std::vector<EdgeWeight> node_weights;
|
std::vector<EdgeWeight> node_weights;
|
||||||
std::vector<EdgeDuration> node_durations; // TODO: to be removed later
|
std::vector<EdgeDuration> node_durations; // TODO: remove when durations are optional
|
||||||
|
std::vector<EdgeDistance> node_distances; // TODO: remove when distances are optional
|
||||||
std::uint32_t connectivity_checksum = 0;
|
std::uint32_t connectivity_checksum = 0;
|
||||||
auto graph = LoadAndUpdateEdgeExpandedGraph(
|
auto graph = LoadAndUpdateEdgeExpandedGraph(
|
||||||
config, mlp, node_weights, node_durations, connectivity_checksum);
|
config, mlp, node_weights, node_durations, node_distances, connectivity_checksum);
|
||||||
BOOST_ASSERT(graph.GetNumberOfNodes() == node_weights.size());
|
BOOST_ASSERT(graph.GetNumberOfNodes() == node_weights.size());
|
||||||
std::for_each(node_weights.begin(), node_weights.end(), [](auto &w) { w &= 0x7fffffff; });
|
std::for_each(node_weights.begin(), node_weights.end(), [](auto &w) { w &= 0x7fffffff; });
|
||||||
util::Log() << "Loaded edge based graph: " << graph.GetNumberOfEdges() << " edges, "
|
util::Log() << "Loaded edge based graph: " << graph.GetNumberOfEdges() << " edges, "
|
||||||
@ -166,8 +170,10 @@ int Customizer::Run(const CustomizationConfig &config)
|
|||||||
util::Log() << "MLD customization writing took " << TIMER_SEC(writing_mld_data) << " seconds";
|
util::Log() << "MLD customization writing took " << TIMER_SEC(writing_mld_data) << " seconds";
|
||||||
|
|
||||||
TIMER_START(writing_graph);
|
TIMER_START(writing_graph);
|
||||||
MultiLevelEdgeBasedGraph shaved_graph{
|
MultiLevelEdgeBasedGraph shaved_graph{std::move(graph),
|
||||||
std::move(graph), std::move(node_weights), std::move(node_durations)};
|
std::move(node_weights),
|
||||||
|
std::move(node_durations),
|
||||||
|
std::move(node_distances)};
|
||||||
customizer::files::writeGraph(
|
customizer::files::writeGraph(
|
||||||
config.GetPath(".osrm.mldgr"), shaved_graph, connectivity_checksum);
|
config.GetPath(".osrm.mldgr"), shaved_graph, connectivity_checksum);
|
||||||
TIMER_STOP(writing_graph);
|
TIMER_STOP(writing_graph);
|
||||||
|
@ -90,7 +90,7 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check whether there is a loop present at the node
|
// check whether there is a loop present at the node
|
||||||
const auto loop_weight = getLoopWeight<false>(facade, node);
|
const auto loop_weight = std::get<0>(getLoopWeight<false>(facade, node));
|
||||||
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
||||||
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
||||||
|
@ -21,18 +21,21 @@ namespace ch
|
|||||||
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
|
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
|
||||||
const NodeID node,
|
const NodeID node,
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
EdgeDuration &duration)
|
EdgeDuration &duration,
|
||||||
|
EdgeDistance &distance)
|
||||||
{ // Special case for CH when contractor creates a loop edge node->node
|
{ // Special case for CH when contractor creates a loop edge node->node
|
||||||
BOOST_ASSERT(weight < 0);
|
BOOST_ASSERT(weight < 0);
|
||||||
|
|
||||||
const auto loop_weight = ch::getLoopWeight<false>(facade, node);
|
const auto loop_weight = ch::getLoopWeight<false>(facade, node);
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT)
|
if (std::get<0>(loop_weight) != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
const auto new_weight_with_loop = weight + loop_weight;
|
const auto new_weight_with_loop = weight + std::get<0>(loop_weight);
|
||||||
if (new_weight_with_loop >= 0)
|
if (new_weight_with_loop >= 0)
|
||||||
{
|
{
|
||||||
weight = new_weight_with_loop;
|
weight = new_weight_with_loop;
|
||||||
duration += ch::getLoopWeight<true>(facade, node);
|
auto result = ch::getLoopWeight<true>(facade, node);
|
||||||
|
duration += std::get<0>(result);
|
||||||
|
distance += std::get<1>(result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,6 +49,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
const NodeID node,
|
const NodeID node,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeDuration duration,
|
const EdgeDuration duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
const PhantomNode &)
|
const PhantomNode &)
|
||||||
{
|
{
|
||||||
@ -63,21 +67,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
const auto edge_weight = data.weight;
|
const auto edge_weight = data.weight;
|
||||||
|
|
||||||
const auto edge_duration = data.duration;
|
const auto edge_duration = data.duration;
|
||||||
|
const auto edge_distance = data.distance;
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
const auto to_weight = weight + edge_weight;
|
const auto to_weight = weight + edge_weight;
|
||||||
const auto to_duration = duration + edge_duration;
|
const auto to_duration = duration + edge_duration;
|
||||||
|
const auto to_distance = distance + edge_distance;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, to_duration});
|
query_heap.Insert(to, to_weight, {node, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight and set new parent
|
// Found a shorter Path -> Update weight and set new parent
|
||||||
else if (std::tie(to_weight, to_duration) <
|
else if (std::tie(to_weight, to_duration) <
|
||||||
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
|
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, to_duration};
|
query_heap.GetData(to) = {node, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,12 +97,14 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const std::vector<NodeBucket> &search_space_with_buckets,
|
const std::vector<NodeBucket> &search_space_with_buckets,
|
||||||
std::vector<EdgeWeight> &weights_table,
|
std::vector<EdgeWeight> &weights_table,
|
||||||
std::vector<EdgeDuration> &durations_table,
|
std::vector<EdgeDuration> &durations_table,
|
||||||
|
std::vector<EdgeDistance> &distances_table,
|
||||||
std::vector<NodeID> &middle_nodes_table,
|
std::vector<NodeID> &middle_nodes_table,
|
||||||
const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto source_weight = query_heap.GetKey(node);
|
const auto source_weight = query_heap.GetKey(node);
|
||||||
const auto source_duration = query_heap.GetData(node).duration;
|
const auto source_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto source_distance = query_heap.GetData(node).distance;
|
||||||
|
|
||||||
// Check if each encountered node has an entry
|
// Check if each encountered node has an entry
|
||||||
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
||||||
@ -109,20 +117,24 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto column_index = current_bucket.column_index;
|
const auto column_index = current_bucket.column_index;
|
||||||
const auto target_weight = current_bucket.weight;
|
const auto target_weight = current_bucket.weight;
|
||||||
const auto target_duration = current_bucket.duration;
|
const auto target_duration = current_bucket.duration;
|
||||||
|
const auto target_distance = current_bucket.distance;
|
||||||
|
|
||||||
auto ¤t_weight = weights_table[row_index * number_of_targets + column_index];
|
auto ¤t_weight = weights_table[row_index * number_of_targets + column_index];
|
||||||
auto ¤t_duration = durations_table[row_index * number_of_targets + column_index];
|
auto ¤t_duration = durations_table[row_index * number_of_targets + column_index];
|
||||||
|
auto ¤t_distance = distances_table[row_index * number_of_targets + column_index];
|
||||||
|
|
||||||
// Check if new weight is better
|
// Check if new weight is better
|
||||||
auto new_weight = source_weight + target_weight;
|
auto new_weight = source_weight + target_weight;
|
||||||
auto new_duration = source_duration + target_duration;
|
auto new_duration = source_duration + target_duration;
|
||||||
|
auto new_distance = source_distance + target_distance;
|
||||||
|
|
||||||
if (new_weight < 0)
|
if (new_weight < 0)
|
||||||
{
|
{
|
||||||
if (addLoopWeight(facade, node, new_weight, new_duration))
|
if (addLoopWeight(facade, node, new_weight, new_duration, new_distance))
|
||||||
{
|
{
|
||||||
current_weight = std::min(current_weight, new_weight);
|
current_weight = std::min(current_weight, new_weight);
|
||||||
current_duration = std::min(current_duration, new_duration);
|
current_duration = std::min(current_duration, new_duration);
|
||||||
|
current_distance = std::min(current_distance, new_distance);
|
||||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,12 +142,13 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
{
|
{
|
||||||
current_weight = new_weight;
|
current_weight = new_weight;
|
||||||
current_duration = new_duration;
|
current_duration = new_duration;
|
||||||
|
current_distance = new_distance;
|
||||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<FORWARD_DIRECTION>(
|
relaxOutgoingEdges<FORWARD_DIRECTION>(
|
||||||
facade, node, source_weight, source_duration, query_heap, phantom_node);
|
facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
||||||
@ -147,172 +160,19 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto target_weight = query_heap.GetKey(node);
|
const auto target_weight = query_heap.GetKey(node);
|
||||||
const auto target_duration = query_heap.GetData(node).duration;
|
const auto target_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto target_distance = query_heap.GetData(node).distance;
|
||||||
const auto parent = query_heap.GetData(node).parent;
|
const auto parent = query_heap.GetData(node).parent;
|
||||||
|
|
||||||
// Store settled nodes in search space bucket
|
// Store settled nodes in search space bucket
|
||||||
search_space_with_buckets.emplace_back(
|
search_space_with_buckets.emplace_back(
|
||||||
node, parent, column_index, target_weight, target_duration);
|
node, parent, column_index, target_weight, target_duration, target_distance);
|
||||||
|
|
||||||
relaxOutgoingEdges<REVERSE_DIRECTION>(
|
relaxOutgoingEdges<REVERSE_DIRECTION>(
|
||||||
facade, node, target_weight, target_duration, query_heap, phantom_node);
|
facade, node, target_weight, target_duration, target_distance, query_heap, phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ch
|
} // namespace ch
|
||||||
|
|
||||||
void retrievePackedPathFromSearchSpace(const NodeID middle_node_id,
|
|
||||||
const unsigned column_index,
|
|
||||||
const std::vector<NodeBucket> &search_space_with_buckets,
|
|
||||||
std::vector<NodeID> &packed_leg)
|
|
||||||
{
|
|
||||||
auto bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
|
||||||
search_space_with_buckets.end(),
|
|
||||||
middle_node_id,
|
|
||||||
NodeBucket::ColumnCompare(column_index));
|
|
||||||
|
|
||||||
NodeID current_node_id = middle_node_id;
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(std::distance(bucket_list.first, bucket_list.second) == 1,
|
|
||||||
"The pointers are not pointing to the same element.");
|
|
||||||
|
|
||||||
while (bucket_list.first->parent_node != current_node_id &&
|
|
||||||
bucket_list.first != search_space_with_buckets.end())
|
|
||||||
{
|
|
||||||
current_node_id = bucket_list.first->parent_node;
|
|
||||||
|
|
||||||
packed_leg.emplace_back(current_node_id);
|
|
||||||
|
|
||||||
bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
|
||||||
search_space_with_buckets.end(),
|
|
||||||
current_node_id,
|
|
||||||
NodeBucket::ColumnCompare(column_index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void calculateDistances(typename SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &query_heap,
|
|
||||||
const DataFacade<ch::Algorithm> &facade,
|
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
|
||||||
const std::vector<std::size_t> &target_indices,
|
|
||||||
const std::size_t row_index,
|
|
||||||
const std::size_t source_index,
|
|
||||||
const PhantomNode &source_phantom,
|
|
||||||
const std::size_t number_of_targets,
|
|
||||||
const std::vector<NodeBucket> &search_space_with_buckets,
|
|
||||||
std::vector<EdgeDistance> &distances_table,
|
|
||||||
const std::vector<NodeID> &middle_nodes_table)
|
|
||||||
{
|
|
||||||
std::vector<NodeID> packed_leg;
|
|
||||||
|
|
||||||
for (auto column_index : util::irange<std::size_t>(0, number_of_targets))
|
|
||||||
{
|
|
||||||
const auto target_index = target_indices[column_index];
|
|
||||||
const auto &target_phantom = phantom_nodes[target_index];
|
|
||||||
|
|
||||||
if (source_index == target_index)
|
|
||||||
{
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = 0.0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID middle_node_id = middle_nodes_table[row_index * number_of_targets + column_index];
|
|
||||||
|
|
||||||
if (middle_node_id == SPECIAL_NODEID) // takes care of one-ways
|
|
||||||
{
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = INVALID_EDGE_DISTANCE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1: Find path from source to middle node
|
|
||||||
ch::retrievePackedPathFromSingleManyToManyHeap(query_heap, middle_node_id, packed_leg);
|
|
||||||
std::reverse(packed_leg.begin(), packed_leg.end());
|
|
||||||
|
|
||||||
packed_leg.push_back(middle_node_id);
|
|
||||||
|
|
||||||
// Step 2: Find path from middle to target node
|
|
||||||
retrievePackedPathFromSearchSpace(
|
|
||||||
middle_node_id, column_index, search_space_with_buckets, packed_leg);
|
|
||||||
|
|
||||||
if (packed_leg.size() == 1 && (needsLoopForward(source_phantom, target_phantom) ||
|
|
||||||
needsLoopBackwards(source_phantom, target_phantom)))
|
|
||||||
{
|
|
||||||
auto weight = ch::getLoopWeight<false>(facade, packed_leg.front());
|
|
||||||
if (weight != INVALID_EDGE_WEIGHT)
|
|
||||||
packed_leg.push_back(packed_leg.front());
|
|
||||||
}
|
|
||||||
if (!packed_leg.empty())
|
|
||||||
{
|
|
||||||
auto annotation =
|
|
||||||
ch::calculateEBGNodeAnnotations(facade, packed_leg.begin(), packed_leg.end());
|
|
||||||
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = annotation;
|
|
||||||
|
|
||||||
// check the direction of travel to figure out how to calculate the offset to/from
|
|
||||||
// the source/target
|
|
||||||
if (source_phantom.forward_segment_id.id == packed_leg.front())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// -->s <-- subtract offset to start at source
|
|
||||||
// ......... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset = source_phantom.GetForwardDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] -= offset;
|
|
||||||
}
|
|
||||||
else if (source_phantom.reverse_segment_id.id == packed_leg.front())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// s<------- <-- subtract offset to start at source
|
|
||||||
// ... <-- want this distance
|
|
||||||
// entry 0---1---2---3 <-- 3 is exit node
|
|
||||||
EdgeDistance offset = source_phantom.GetReverseDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] -= offset;
|
|
||||||
}
|
|
||||||
if (target_phantom.forward_segment_id.id == packed_leg.back())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// ++>t <-- add offset to get to target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset = target_phantom.GetForwardDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] += offset;
|
|
||||||
}
|
|
||||||
else if (target_phantom.reverse_segment_id.id == packed_leg.back())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// <++t <-- add offset to get from target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset = target_phantom.GetReverseDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] += offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// there is no shortcut to unpack. source and target are on the same EBG Node.
|
|
||||||
// if the offset of the target is greater than the offset of the source, subtract it
|
|
||||||
if (target_phantom.GetForwardDistance() > source_phantom.GetForwardDistance())
|
|
||||||
{
|
|
||||||
// --------->t <-- offsets
|
|
||||||
// ->s <-- subtract source offset from target offset
|
|
||||||
// ......... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset =
|
|
||||||
target_phantom.GetForwardDistance() - source_phantom.GetForwardDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// s<--- <-- offsets
|
|
||||||
// t<--------- <-- subtract source offset from target offset
|
|
||||||
// ...... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset =
|
|
||||||
target_phantom.GetReverseDistance() - source_phantom.GetReverseDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
packed_leg.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
||||||
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
@ -320,18 +180,16 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
|||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices,
|
const std::vector<std::size_t> &target_indices,
|
||||||
const bool calculate_distance,
|
const bool /* calculate_distance */,
|
||||||
const bool calculate_duration)
|
const bool /* calculate_duration */)
|
||||||
{
|
{
|
||||||
(void)calculate_duration; // TODO: stub to use when computing durations become optional
|
|
||||||
|
|
||||||
const auto number_of_sources = source_indices.size();
|
const auto number_of_sources = source_indices.size();
|
||||||
const auto number_of_targets = target_indices.size();
|
const auto number_of_targets = target_indices.size();
|
||||||
const auto number_of_entries = number_of_sources * number_of_targets;
|
const auto number_of_entries = number_of_sources * number_of_targets;
|
||||||
|
|
||||||
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
||||||
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
||||||
std::vector<EdgeDistance> distances_table;
|
std::vector<EdgeDistance> distances_table(number_of_entries, MAXIMAL_EDGE_DISTANCE);
|
||||||
std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID);
|
std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID);
|
||||||
|
|
||||||
std::vector<NodeBucket> search_space_with_buckets;
|
std::vector<NodeBucket> search_space_with_buckets;
|
||||||
@ -380,25 +238,10 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
|||||||
search_space_with_buckets,
|
search_space_with_buckets,
|
||||||
weights_table,
|
weights_table,
|
||||||
durations_table,
|
durations_table,
|
||||||
|
distances_table,
|
||||||
middle_nodes_table,
|
middle_nodes_table,
|
||||||
source_phantom);
|
source_phantom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculate_distance)
|
|
||||||
{
|
|
||||||
distances_table.resize(number_of_entries, INVALID_EDGE_DISTANCE);
|
|
||||||
calculateDistances(query_heap,
|
|
||||||
facade,
|
|
||||||
phantom_nodes,
|
|
||||||
target_indices,
|
|
||||||
row_index,
|
|
||||||
source_index,
|
|
||||||
source_phantom,
|
|
||||||
number_of_targets,
|
|
||||||
search_space_with_buckets,
|
|
||||||
distances_table,
|
|
||||||
middle_nodes_table);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_pair(durations_table, distances_table);
|
return std::make_pair(durations_table, distances_table);
|
||||||
|
@ -41,6 +41,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
const NodeID node,
|
const NodeID node,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeDuration duration,
|
const EdgeDuration duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
@ -65,65 +66,77 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
{ // Shortcuts in forward direction
|
{ // Shortcuts in forward direction
|
||||||
auto destination = cell.GetDestinationNodes().begin();
|
auto destination = cell.GetDestinationNodes().begin();
|
||||||
auto shortcut_durations = cell.GetOutDuration(node);
|
auto shortcut_durations = cell.GetOutDuration(node);
|
||||||
|
auto shortcut_distances = cell.GetOutDistance(node);
|
||||||
for (auto shortcut_weight : cell.GetOutWeight(node))
|
for (auto shortcut_weight : cell.GetOutWeight(node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
||||||
BOOST_ASSERT(!shortcut_durations.empty());
|
BOOST_ASSERT(!shortcut_durations.empty());
|
||||||
|
BOOST_ASSERT(!shortcut_distances.empty());
|
||||||
const NodeID to = *destination;
|
const NodeID to = *destination;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
||||||
{
|
{
|
||||||
const auto to_weight = weight + shortcut_weight;
|
const auto to_weight = weight + shortcut_weight;
|
||||||
const auto to_duration = duration + shortcut_durations.front();
|
const auto to_duration = duration + shortcut_durations.front();
|
||||||
|
const auto to_distance = distance + shortcut_distances.front();
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, true, to_duration});
|
query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration, node) <
|
else if (std::tie(to_weight, to_duration, to_distance, node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(query_heap.GetKey(to),
|
||||||
query_heap.GetData(to).duration,
|
query_heap.GetData(to).duration,
|
||||||
|
query_heap.GetData(to).distance,
|
||||||
query_heap.GetData(to).parent))
|
query_heap.GetData(to).parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, true, to_duration};
|
query_heap.GetData(to) = {node, true, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++destination;
|
++destination;
|
||||||
shortcut_durations.advance_begin(1);
|
shortcut_durations.advance_begin(1);
|
||||||
|
shortcut_distances.advance_begin(1);
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(shortcut_durations.empty());
|
BOOST_ASSERT(shortcut_durations.empty());
|
||||||
|
BOOST_ASSERT(shortcut_distances.empty());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Shortcuts in backward direction
|
{ // Shortcuts in backward direction
|
||||||
auto source = cell.GetSourceNodes().begin();
|
auto source = cell.GetSourceNodes().begin();
|
||||||
auto shortcut_durations = cell.GetInDuration(node);
|
auto shortcut_durations = cell.GetInDuration(node);
|
||||||
|
auto shortcut_distances = cell.GetInDistance(node);
|
||||||
for (auto shortcut_weight : cell.GetInWeight(node))
|
for (auto shortcut_weight : cell.GetInWeight(node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
||||||
BOOST_ASSERT(!shortcut_durations.empty());
|
BOOST_ASSERT(!shortcut_durations.empty());
|
||||||
|
BOOST_ASSERT(!shortcut_distances.empty());
|
||||||
const NodeID to = *source;
|
const NodeID to = *source;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
||||||
{
|
{
|
||||||
const auto to_weight = weight + shortcut_weight;
|
const auto to_weight = weight + shortcut_weight;
|
||||||
const auto to_duration = duration + shortcut_durations.front();
|
const auto to_duration = duration + shortcut_durations.front();
|
||||||
|
const auto to_distance = distance + shortcut_distances.front();
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, true, to_duration});
|
query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration, node) <
|
else if (std::tie(to_weight, to_duration, to_distance, node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(query_heap.GetKey(to),
|
||||||
query_heap.GetData(to).duration,
|
query_heap.GetData(to).duration,
|
||||||
|
query_heap.GetData(to).distance,
|
||||||
query_heap.GetData(to).parent))
|
query_heap.GetData(to).parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, true, to_duration};
|
query_heap.GetData(to) = {node, true, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++source;
|
++source;
|
||||||
shortcut_durations.advance_begin(1);
|
shortcut_durations.advance_begin(1);
|
||||||
|
shortcut_distances.advance_begin(1);
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(shortcut_durations.empty());
|
BOOST_ASSERT(shortcut_durations.empty());
|
||||||
|
BOOST_ASSERT(shortcut_distances.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,25 +156,28 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
const auto node_id = DIRECTION == FORWARD_DIRECTION ? node : facade.GetTarget(edge);
|
const auto node_id = DIRECTION == FORWARD_DIRECTION ? node : facade.GetTarget(edge);
|
||||||
const auto node_weight = facade.GetNodeWeight(node_id);
|
const auto node_weight = facade.GetNodeWeight(node_id);
|
||||||
const auto node_duration = facade.GetNodeDuration(node_id);
|
const auto node_duration = facade.GetNodeDuration(node_id);
|
||||||
|
const auto node_distance = facade.GetNodeDistance(node_id);
|
||||||
const auto turn_weight = node_weight + facade.GetWeightPenaltyForEdgeID(turn_id);
|
const auto turn_weight = node_weight + facade.GetWeightPenaltyForEdgeID(turn_id);
|
||||||
const auto turn_duration = node_duration + facade.GetDurationPenaltyForEdgeID(turn_id);
|
const auto turn_duration = node_duration + facade.GetDurationPenaltyForEdgeID(turn_id);
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(node_weight + turn_weight > 0, "edge weight is invalid");
|
BOOST_ASSERT_MSG(node_weight + turn_weight > 0, "edge weight is invalid");
|
||||||
const auto to_weight = weight + turn_weight;
|
const auto to_weight = weight + turn_weight;
|
||||||
const auto to_duration = duration + turn_duration;
|
const auto to_duration = duration + turn_duration;
|
||||||
|
const auto to_distance = distance + node_distance;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, false, to_duration});
|
query_heap.Insert(to, to_weight, {node, false, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight and set new parent
|
// Found a shorter Path -> Update weight and set new parent
|
||||||
else if (std::tie(to_weight, to_duration, node) <
|
else if (std::tie(to_weight, to_duration, to_distance, node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(query_heap.GetKey(to),
|
||||||
query_heap.GetData(to).duration,
|
query_heap.GetData(to).duration,
|
||||||
|
query_heap.GetData(to).distance,
|
||||||
query_heap.GetData(to).parent))
|
query_heap.GetData(to).parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, false, to_duration};
|
query_heap.GetData(to) = {node, false, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,16 +193,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
std::size_t phantom_index,
|
std::size_t phantom_index,
|
||||||
const std::vector<std::size_t> &phantom_indices,
|
const std::vector<std::size_t> &phantom_indices)
|
||||||
const bool calculate_distance)
|
|
||||||
{
|
{
|
||||||
std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT);
|
std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT);
|
||||||
std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION);
|
std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION);
|
||||||
std::vector<EdgeDistance> distances_table;
|
std::vector<EdgeDistance> distances_table(phantom_indices.size(), MAXIMAL_EDGE_DISTANCE);
|
||||||
std::vector<NodeID> middle_nodes_table(phantom_indices.size(), SPECIAL_NODEID);
|
std::vector<NodeID> middle_nodes_table(phantom_indices.size(), SPECIAL_NODEID);
|
||||||
|
|
||||||
// Collect destination (source) nodes into a map
|
// Collect destination (source) nodes into a map
|
||||||
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration>>
|
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration, EdgeDistance>>
|
||||||
target_nodes_index;
|
target_nodes_index;
|
||||||
target_nodes_index.reserve(phantom_indices.size());
|
target_nodes_index.reserve(phantom_indices.size());
|
||||||
for (std::size_t index = 0; index < phantom_indices.size(); ++index)
|
for (std::size_t index = 0; index < phantom_indices.size(); ++index)
|
||||||
@ -201,13 +216,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{phantom_node.forward_segment_id.id,
|
{phantom_node.forward_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
phantom_node.GetForwardWeightPlusOffset(),
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
phantom_node.GetForwardDuration())});
|
phantom_node.GetForwardDuration(),
|
||||||
|
phantom_node.GetForwardDistance())});
|
||||||
if (phantom_node.IsValidReverseTarget())
|
if (phantom_node.IsValidReverseTarget())
|
||||||
target_nodes_index.insert(
|
target_nodes_index.insert(
|
||||||
{phantom_node.reverse_segment_id.id,
|
{phantom_node.reverse_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
phantom_node.GetReverseWeightPlusOffset(),
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
phantom_node.GetReverseDuration())});
|
phantom_node.GetReverseDuration(),
|
||||||
|
phantom_node.GetReverseDistance())});
|
||||||
}
|
}
|
||||||
else if (DIRECTION == REVERSE_DIRECTION)
|
else if (DIRECTION == REVERSE_DIRECTION)
|
||||||
{
|
{
|
||||||
@ -216,13 +233,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{phantom_node.forward_segment_id.id,
|
{phantom_node.forward_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
-phantom_node.GetForwardWeightPlusOffset(),
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
-phantom_node.GetForwardDuration())});
|
-phantom_node.GetForwardDuration(),
|
||||||
|
-phantom_node.GetForwardDistance())});
|
||||||
if (phantom_node.IsValidReverseSource())
|
if (phantom_node.IsValidReverseSource())
|
||||||
target_nodes_index.insert(
|
target_nodes_index.insert(
|
||||||
{phantom_node.reverse_segment_id.id,
|
{phantom_node.reverse_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
-phantom_node.GetReverseWeightPlusOffset(),
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
-phantom_node.GetReverseDuration())});
|
-phantom_node.GetReverseDuration(),
|
||||||
|
-phantom_node.GetReverseDistance())});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,44 +251,51 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
auto &query_heap = *(engine_working_data.many_to_many_heap);
|
auto &query_heap = *(engine_working_data.many_to_many_heap);
|
||||||
|
|
||||||
// Check if node is in the destinations list and update weights/durations
|
// Check if node is in the destinations list and update weights/durations
|
||||||
auto update_values = [&](NodeID node, EdgeWeight weight, EdgeDuration duration) {
|
auto update_values =
|
||||||
auto candidates = target_nodes_index.equal_range(node);
|
[&](NodeID node, EdgeWeight weight, EdgeDuration duration, EdgeDistance distance) {
|
||||||
for (auto it = candidates.first; it != candidates.second;)
|
auto candidates = target_nodes_index.equal_range(node);
|
||||||
{
|
for (auto it = candidates.first; it != candidates.second;)
|
||||||
std::size_t index;
|
|
||||||
EdgeWeight target_weight;
|
|
||||||
EdgeDuration target_duration;
|
|
||||||
std::tie(index, target_weight, target_duration) = it->second;
|
|
||||||
|
|
||||||
const auto path_weight = weight + target_weight;
|
|
||||||
if (path_weight >= 0)
|
|
||||||
{
|
{
|
||||||
const auto path_duration = duration + target_duration;
|
std::size_t index;
|
||||||
|
EdgeWeight target_weight;
|
||||||
|
EdgeDuration target_duration;
|
||||||
|
EdgeDistance target_distance;
|
||||||
|
std::tie(index, target_weight, target_duration, target_distance) = it->second;
|
||||||
|
|
||||||
if (std::tie(path_weight, path_duration) <
|
const auto path_weight = weight + target_weight;
|
||||||
std::tie(weights[index], durations[index]))
|
if (path_weight >= 0)
|
||||||
{
|
{
|
||||||
weights[index] = path_weight;
|
const auto path_duration = duration + target_duration;
|
||||||
durations[index] = path_duration;
|
const auto path_distance = distance + target_distance;
|
||||||
middle_nodes_table[index] = node;
|
|
||||||
|
if (std::tie(path_weight, path_duration, path_distance) <
|
||||||
|
std::tie(weights[index], durations[index], distances_table[index]))
|
||||||
|
{
|
||||||
|
weights[index] = path_weight;
|
||||||
|
durations[index] = path_duration;
|
||||||
|
distances_table[index] = path_distance;
|
||||||
|
middle_nodes_table[index] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove node from destinations list
|
||||||
|
it = target_nodes_index.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove node from destinations list
|
|
||||||
it = target_nodes_index.erase(it);
|
|
||||||
}
|
}
|
||||||
else
|
};
|
||||||
{
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto insert_node = [&](NodeID node, EdgeWeight initial_weight, EdgeDuration initial_duration) {
|
auto insert_node = [&](NodeID node,
|
||||||
|
EdgeWeight initial_weight,
|
||||||
|
EdgeDuration initial_duration,
|
||||||
|
EdgeDistance initial_distance) {
|
||||||
|
|
||||||
// Update single node paths
|
// Update single node paths
|
||||||
update_values(node, initial_weight, initial_duration);
|
update_values(node, initial_weight, initial_duration, initial_distance);
|
||||||
|
|
||||||
query_heap.Insert(node, initial_weight, {node, initial_duration});
|
query_heap.Insert(node, initial_weight, {node, initial_duration, initial_distance});
|
||||||
|
|
||||||
// Place adjacent nodes into heap
|
// Place adjacent nodes into heap
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
@ -292,8 +318,9 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
facade.GetWeightPenaltyForEdgeID(turn_id);
|
facade.GetWeightPenaltyForEdgeID(turn_id);
|
||||||
const auto edge_duration = initial_duration + facade.GetNodeDuration(node_id) +
|
const auto edge_duration = initial_duration + facade.GetNodeDuration(node_id) +
|
||||||
facade.GetDurationPenaltyForEdgeID(turn_id);
|
facade.GetDurationPenaltyForEdgeID(turn_id);
|
||||||
|
const auto edge_distance = initial_distance + facade.GetNodeDistance(node_id);
|
||||||
|
|
||||||
query_heap.Insert(to, edge_weight, {node, edge_duration});
|
query_heap.Insert(to, edge_weight, {node, edge_duration, edge_distance});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -307,14 +334,16 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{
|
{
|
||||||
insert_node(phantom_node.forward_segment_id.id,
|
insert_node(phantom_node.forward_segment_id.id,
|
||||||
-phantom_node.GetForwardWeightPlusOffset(),
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
-phantom_node.GetForwardDuration());
|
-phantom_node.GetForwardDuration(),
|
||||||
|
-phantom_node.GetForwardDistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phantom_node.IsValidReverseSource())
|
if (phantom_node.IsValidReverseSource())
|
||||||
{
|
{
|
||||||
insert_node(phantom_node.reverse_segment_id.id,
|
insert_node(phantom_node.reverse_segment_id.id,
|
||||||
-phantom_node.GetReverseWeightPlusOffset(),
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
-phantom_node.GetReverseDuration());
|
-phantom_node.GetReverseDuration(),
|
||||||
|
-phantom_node.GetReverseDistance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (DIRECTION == REVERSE_DIRECTION)
|
else if (DIRECTION == REVERSE_DIRECTION)
|
||||||
@ -323,14 +352,16 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{
|
{
|
||||||
insert_node(phantom_node.forward_segment_id.id,
|
insert_node(phantom_node.forward_segment_id.id,
|
||||||
phantom_node.GetForwardWeightPlusOffset(),
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
phantom_node.GetForwardDuration());
|
phantom_node.GetForwardDuration(),
|
||||||
|
phantom_node.GetForwardDistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phantom_node.IsValidReverseTarget())
|
if (phantom_node.IsValidReverseTarget())
|
||||||
{
|
{
|
||||||
insert_node(phantom_node.reverse_segment_id.id,
|
insert_node(phantom_node.reverse_segment_id.id,
|
||||||
phantom_node.GetReverseWeightPlusOffset(),
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
phantom_node.GetReverseDuration());
|
phantom_node.GetReverseDuration(),
|
||||||
|
phantom_node.GetReverseDistance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,141 +372,23 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto weight = query_heap.GetKey(node);
|
const auto weight = query_heap.GetKey(node);
|
||||||
const auto duration = query_heap.GetData(node).duration;
|
const auto duration = query_heap.GetData(node).duration;
|
||||||
|
const auto distance = query_heap.GetData(node).distance;
|
||||||
|
|
||||||
// Update values
|
// Update values
|
||||||
update_values(node, weight, duration);
|
update_values(node, weight, duration, distance);
|
||||||
|
|
||||||
// Relax outgoing edges
|
// Relax outgoing edges
|
||||||
relaxOutgoingEdges<DIRECTION>(facade,
|
relaxOutgoingEdges<DIRECTION>(facade,
|
||||||
node,
|
node,
|
||||||
weight,
|
weight,
|
||||||
duration,
|
duration,
|
||||||
|
distance,
|
||||||
query_heap,
|
query_heap,
|
||||||
phantom_nodes,
|
phantom_nodes,
|
||||||
phantom_index,
|
phantom_index,
|
||||||
phantom_indices);
|
phantom_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculate_distance)
|
|
||||||
{
|
|
||||||
// Initialize unpacking heaps
|
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
|
||||||
facade.GetNumberOfNodes(), facade.GetMaxBorderNodeID() + 1);
|
|
||||||
|
|
||||||
distances_table.resize(phantom_indices.size(), INVALID_EDGE_DISTANCE);
|
|
||||||
|
|
||||||
for (unsigned location = 0; location < phantom_indices.size(); ++location)
|
|
||||||
{
|
|
||||||
// Get the "middle" node that is the last node of a path
|
|
||||||
const NodeID middle_node_id = middle_nodes_table[location];
|
|
||||||
if (middle_node_id == SPECIAL_NODEID) // takes care of one-ways
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the packed path from the heap
|
|
||||||
PackedPath packed_path = mld::retrievePackedPathFromSingleManyToManyHeap<DIRECTION>(
|
|
||||||
query_heap, middle_node_id);
|
|
||||||
|
|
||||||
// ... and reverse it to have packed edges in the correct order,
|
|
||||||
if (DIRECTION == FORWARD_DIRECTION)
|
|
||||||
{
|
|
||||||
std::reverse(packed_path.begin(), packed_path.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... unpack path
|
|
||||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
|
||||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
|
||||||
std::vector<NodeID> unpacked_nodes;
|
|
||||||
std::vector<EdgeID> unpacked_edges;
|
|
||||||
|
|
||||||
std::tie(weight, unpacked_nodes, unpacked_edges) =
|
|
||||||
unpackPathAndCalculateDistance(engine_working_data,
|
|
||||||
facade,
|
|
||||||
forward_heap,
|
|
||||||
reverse_heap,
|
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
INVALID_EDGE_WEIGHT,
|
|
||||||
packed_path,
|
|
||||||
middle_node_id,
|
|
||||||
phantom_nodes,
|
|
||||||
phantom_index,
|
|
||||||
phantom_indices);
|
|
||||||
|
|
||||||
// Accumulate the path length without the last node
|
|
||||||
auto annotation = 0.0;
|
|
||||||
|
|
||||||
BOOST_ASSERT(!unpacked_nodes.empty());
|
|
||||||
for (auto node = unpacked_nodes.begin(), last_node = std::prev(unpacked_nodes.end());
|
|
||||||
node != last_node;
|
|
||||||
++node)
|
|
||||||
{
|
|
||||||
annotation += computeEdgeDistance(facade, *node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... and add negative source and positive target offsets
|
|
||||||
// ⚠ for REVERSE_DIRECTION original source and target phantom nodes are swapped
|
|
||||||
// Get source and target phantom nodes
|
|
||||||
// * 1-to-N: source is a single index, target is the corresponding from the indices list
|
|
||||||
// * N-to-1: source is the corresponding from the indices list, target is a single index
|
|
||||||
auto source_phantom_index = phantom_index;
|
|
||||||
auto target_phantom_index = phantom_indices[location];
|
|
||||||
if (DIRECTION == REVERSE_DIRECTION)
|
|
||||||
{
|
|
||||||
std::swap(source_phantom_index, target_phantom_index);
|
|
||||||
}
|
|
||||||
const auto &source_phantom = phantom_nodes[source_phantom_index];
|
|
||||||
const auto &target_phantom = phantom_nodes[target_phantom_index];
|
|
||||||
const NodeID source_node = unpacked_nodes.front();
|
|
||||||
const NodeID target_node = unpacked_nodes.back();
|
|
||||||
|
|
||||||
EdgeDistance source_offset = 0., target_offset = 0.;
|
|
||||||
if (source_phantom.IsValidForwardSource() &&
|
|
||||||
source_phantom.forward_segment_id.id == source_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0
|
|
||||||
// to 3
|
|
||||||
// -->s <-- subtract offset to start at source
|
|
||||||
// ......... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
source_offset = source_phantom.GetForwardDistance();
|
|
||||||
}
|
|
||||||
else if (source_phantom.IsValidReverseSource() &&
|
|
||||||
source_phantom.reverse_segment_id.id == source_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// s<------- <-- subtract offset to start at source
|
|
||||||
// ... <-- want this distance
|
|
||||||
// entry 0---1---2---3 <-- 3 is exit node
|
|
||||||
source_offset = source_phantom.GetReverseDistance();
|
|
||||||
}
|
|
||||||
if (target_phantom.IsValidForwardTarget() &&
|
|
||||||
target_phantom.forward_segment_id.id == target_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0
|
|
||||||
// to 3
|
|
||||||
// ++>t <-- add offset to get to target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
target_offset = target_phantom.GetForwardDistance();
|
|
||||||
}
|
|
||||||
else if (target_phantom.IsValidReverseTarget() &&
|
|
||||||
target_phantom.reverse_segment_id.id == target_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0
|
|
||||||
// to 3
|
|
||||||
// <++t <-- add offset to get from target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
target_offset = target_phantom.GetReverseDistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
distances_table[location] = -source_offset + annotation + target_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(durations, distances_table);
|
return std::make_pair(durations, distances_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,12 +404,14 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const std::vector<NodeBucket> &search_space_with_buckets,
|
const std::vector<NodeBucket> &search_space_with_buckets,
|
||||||
std::vector<EdgeWeight> &weights_table,
|
std::vector<EdgeWeight> &weights_table,
|
||||||
std::vector<EdgeDuration> &durations_table,
|
std::vector<EdgeDuration> &durations_table,
|
||||||
|
std::vector<EdgeDistance> &distances_table,
|
||||||
std::vector<NodeID> &middle_nodes_table,
|
std::vector<NodeID> &middle_nodes_table,
|
||||||
const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto source_weight = query_heap.GetKey(node);
|
const auto source_weight = query_heap.GetKey(node);
|
||||||
const auto source_duration = query_heap.GetData(node).duration;
|
const auto source_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto source_distance = query_heap.GetData(node).distance;
|
||||||
|
|
||||||
// Check if each encountered node has an entry
|
// Check if each encountered node has an entry
|
||||||
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
||||||
@ -509,6 +424,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto column_idx = current_bucket.column_index;
|
const auto column_idx = current_bucket.column_index;
|
||||||
const auto target_weight = current_bucket.weight;
|
const auto target_weight = current_bucket.weight;
|
||||||
const auto target_duration = current_bucket.duration;
|
const auto target_duration = current_bucket.duration;
|
||||||
|
const auto target_distance = current_bucket.distance;
|
||||||
|
|
||||||
// Get the value location in the results tables:
|
// Get the value location in the results tables:
|
||||||
// * row-major direct (row_idx, column_idx) index for forward direction
|
// * row-major direct (row_idx, column_idx) index for forward direction
|
||||||
@ -518,22 +434,26 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
: row_idx + column_idx * number_of_sources;
|
: row_idx + column_idx * number_of_sources;
|
||||||
auto ¤t_weight = weights_table[location];
|
auto ¤t_weight = weights_table[location];
|
||||||
auto ¤t_duration = durations_table[location];
|
auto ¤t_duration = durations_table[location];
|
||||||
|
auto ¤t_distance = distances_table[location];
|
||||||
|
|
||||||
// Check if new weight is better
|
// Check if new weight is better
|
||||||
auto new_weight = source_weight + target_weight;
|
auto new_weight = source_weight + target_weight;
|
||||||
auto new_duration = source_duration + target_duration;
|
auto new_duration = source_duration + target_duration;
|
||||||
|
auto new_distance = source_distance + target_distance;
|
||||||
|
|
||||||
if (new_weight >= 0 &&
|
if (new_weight >= 0 &&
|
||||||
std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration))
|
std::tie(new_weight, new_duration, new_distance) <
|
||||||
|
std::tie(current_weight, current_duration, current_distance))
|
||||||
{
|
{
|
||||||
current_weight = new_weight;
|
current_weight = new_weight;
|
||||||
current_duration = new_duration;
|
current_duration = new_duration;
|
||||||
|
current_distance = new_distance;
|
||||||
middle_nodes_table[location] = node;
|
middle_nodes_table[location] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<DIRECTION>(
|
relaxOutgoingEdges<DIRECTION>(
|
||||||
facade, node, source_weight, source_duration, query_heap, phantom_node);
|
facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
@ -546,18 +466,25 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto target_weight = query_heap.GetKey(node);
|
const auto target_weight = query_heap.GetKey(node);
|
||||||
const auto target_duration = query_heap.GetData(node).duration;
|
const auto target_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto target_distance = query_heap.GetData(node).distance;
|
||||||
const auto parent = query_heap.GetData(node).parent;
|
const auto parent = query_heap.GetData(node).parent;
|
||||||
const auto from_clique_arc = query_heap.GetData(node).from_clique_arc;
|
const auto from_clique_arc = query_heap.GetData(node).from_clique_arc;
|
||||||
|
|
||||||
// Store settled nodes in search space bucket
|
// Store settled nodes in search space bucket
|
||||||
search_space_with_buckets.emplace_back(
|
search_space_with_buckets.emplace_back(
|
||||||
node, parent, from_clique_arc, column_idx, target_weight, target_duration);
|
node, parent, from_clique_arc, column_idx, target_weight, target_duration, target_distance);
|
||||||
|
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
const auto maximal_level = partition.GetNumberOfLevels() - 1;
|
const auto maximal_level = partition.GetNumberOfLevels() - 1;
|
||||||
|
|
||||||
relaxOutgoingEdges<!DIRECTION>(
|
relaxOutgoingEdges<!DIRECTION>(facade,
|
||||||
facade, node, target_weight, target_duration, query_heap, phantom_node, maximal_level);
|
node,
|
||||||
|
target_weight,
|
||||||
|
target_duration,
|
||||||
|
target_distance,
|
||||||
|
query_heap,
|
||||||
|
phantom_node,
|
||||||
|
maximal_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
@ -596,190 +523,13 @@ void retrievePackedPathFromSearchSpace(NodeID middle_node_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
|
||||||
void calculateDistances(typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
|
||||||
const DataFacade<mld::Algorithm> &facade,
|
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
|
||||||
const std::vector<std::size_t> &target_indices,
|
|
||||||
const unsigned row_idx,
|
|
||||||
const std::size_t source_index,
|
|
||||||
const unsigned number_of_sources,
|
|
||||||
const unsigned number_of_targets,
|
|
||||||
const std::vector<NodeBucket> &search_space_with_buckets,
|
|
||||||
std::vector<EdgeDistance> &distances_table,
|
|
||||||
const std::vector<NodeID> &middle_nodes_table,
|
|
||||||
SearchEngineData<mld::Algorithm> &engine_working_data)
|
|
||||||
{
|
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes(),
|
|
||||||
facade.GetMaxBorderNodeID() + 1);
|
|
||||||
|
|
||||||
for (unsigned column_idx = 0; column_idx < number_of_targets; ++column_idx)
|
|
||||||
{
|
|
||||||
// Step 1: Get source and target phantom nodes that were used in the bucketed search
|
|
||||||
auto source_phantom_index = source_index;
|
|
||||||
auto target_phantom_index = target_indices[column_idx];
|
|
||||||
const auto &source_phantom = phantom_nodes[source_phantom_index];
|
|
||||||
const auto &target_phantom = phantom_nodes[target_phantom_index];
|
|
||||||
|
|
||||||
const auto location = DIRECTION == FORWARD_DIRECTION
|
|
||||||
? row_idx * number_of_targets + column_idx
|
|
||||||
: row_idx + column_idx * number_of_sources;
|
|
||||||
|
|
||||||
if (source_phantom_index == target_phantom_index)
|
|
||||||
{
|
|
||||||
distances_table[location] = 0.0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID middle_node_id = middle_nodes_table[location];
|
|
||||||
|
|
||||||
if (middle_node_id == SPECIAL_NODEID) // takes care of one-ways
|
|
||||||
{
|
|
||||||
distances_table[location] = INVALID_EDGE_DISTANCE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2: Find path from source to middle node
|
|
||||||
PackedPath packed_path =
|
|
||||||
mld::retrievePackedPathFromSingleManyToManyHeap<DIRECTION>(query_heap, middle_node_id);
|
|
||||||
|
|
||||||
if (DIRECTION == FORWARD_DIRECTION)
|
|
||||||
{
|
|
||||||
std::reverse(packed_path.begin(), packed_path.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
|
||||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
|
||||||
std::vector<NodeID> unpacked_nodes_from_source;
|
|
||||||
std::vector<EdgeID> unpacked_edges;
|
|
||||||
std::tie(weight, unpacked_nodes_from_source, unpacked_edges) =
|
|
||||||
unpackPathAndCalculateDistance(engine_working_data,
|
|
||||||
facade,
|
|
||||||
forward_heap,
|
|
||||||
reverse_heap,
|
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
INVALID_EDGE_WEIGHT,
|
|
||||||
packed_path,
|
|
||||||
middle_node_id,
|
|
||||||
source_phantom);
|
|
||||||
|
|
||||||
// Step 3: Find path from middle to target node
|
|
||||||
packed_path.clear();
|
|
||||||
retrievePackedPathFromSearchSpace<DIRECTION>(
|
|
||||||
middle_node_id, column_idx, search_space_with_buckets, packed_path);
|
|
||||||
|
|
||||||
if (DIRECTION == REVERSE_DIRECTION)
|
|
||||||
{
|
|
||||||
std::reverse(packed_path.begin(), packed_path.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<NodeID> unpacked_nodes_to_target;
|
|
||||||
std::tie(weight, unpacked_nodes_to_target, unpacked_edges) =
|
|
||||||
unpackPathAndCalculateDistance(engine_working_data,
|
|
||||||
facade,
|
|
||||||
forward_heap,
|
|
||||||
reverse_heap,
|
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
INVALID_EDGE_WEIGHT,
|
|
||||||
packed_path,
|
|
||||||
middle_node_id,
|
|
||||||
target_phantom);
|
|
||||||
|
|
||||||
if (DIRECTION == REVERSE_DIRECTION)
|
|
||||||
{
|
|
||||||
std::swap(unpacked_nodes_to_target, unpacked_nodes_from_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 4: Compute annotation value along the path nodes without the target node
|
|
||||||
auto annotation = 0.0;
|
|
||||||
|
|
||||||
for (auto node = unpacked_nodes_from_source.begin(),
|
|
||||||
last_node = std::prev(unpacked_nodes_from_source.end());
|
|
||||||
node != last_node;
|
|
||||||
++node)
|
|
||||||
{
|
|
||||||
annotation += computeEdgeDistance(facade, *node);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto node = unpacked_nodes_to_target.begin(),
|
|
||||||
last_node = std::prev(unpacked_nodes_to_target.end());
|
|
||||||
node != last_node;
|
|
||||||
++node)
|
|
||||||
{
|
|
||||||
annotation += computeEdgeDistance(facade, *node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5: Get phantom node offsets and compute the annotation value
|
|
||||||
EdgeDistance source_offset = 0., target_offset = 0.;
|
|
||||||
{
|
|
||||||
// ⚠ for REVERSE_DIRECTION original source and target phantom nodes are swapped
|
|
||||||
if (DIRECTION == REVERSE_DIRECTION)
|
|
||||||
{
|
|
||||||
std::swap(source_phantom_index, target_phantom_index);
|
|
||||||
}
|
|
||||||
const auto &source_phantom = phantom_nodes[source_phantom_index];
|
|
||||||
const auto &target_phantom = phantom_nodes[target_phantom_index];
|
|
||||||
|
|
||||||
NodeID source_node = unpacked_nodes_from_source.front();
|
|
||||||
NodeID target_node = unpacked_nodes_to_target.back();
|
|
||||||
|
|
||||||
if (source_phantom.IsValidForwardSource() &&
|
|
||||||
source_phantom.forward_segment_id.id == source_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0
|
|
||||||
// to 3
|
|
||||||
// -->s <-- subtract offset to start at source
|
|
||||||
// ......... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
source_offset = source_phantom.GetForwardDistance();
|
|
||||||
}
|
|
||||||
else if (source_phantom.IsValidReverseSource() &&
|
|
||||||
source_phantom.reverse_segment_id.id == source_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// s<------- <-- subtract offset to start at source
|
|
||||||
// ... <-- want this distance
|
|
||||||
// entry 0---1---2---3 <-- 3 is exit node
|
|
||||||
source_offset = source_phantom.GetReverseDistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target_phantom.IsValidForwardTarget() &&
|
|
||||||
target_phantom.forward_segment_id.id == target_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0
|
|
||||||
// to 3
|
|
||||||
// ++>t <-- add offset to get to target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
target_offset = target_phantom.GetForwardDistance();
|
|
||||||
}
|
|
||||||
else if (target_phantom.IsValidReverseTarget() &&
|
|
||||||
target_phantom.reverse_segment_id.id == target_node)
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0
|
|
||||||
// to 3
|
|
||||||
// <++t <-- add offset to get from target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
target_offset = target_phantom.GetReverseDistance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
distances_table[location] = -source_offset + annotation + target_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
||||||
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices,
|
const std::vector<std::size_t> &target_indices)
|
||||||
const bool calculate_distance)
|
|
||||||
{
|
{
|
||||||
const auto number_of_sources = source_indices.size();
|
const auto number_of_sources = source_indices.size();
|
||||||
const auto number_of_targets = target_indices.size();
|
const auto number_of_targets = target_indices.size();
|
||||||
@ -787,7 +537,7 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
||||||
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
||||||
std::vector<EdgeDistance> distances_table;
|
std::vector<EdgeDistance> distances_table(number_of_entries, INVALID_EDGE_DISTANCE);
|
||||||
std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID);
|
std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID);
|
||||||
|
|
||||||
std::vector<NodeBucket> search_space_with_buckets;
|
std::vector<NodeBucket> search_space_with_buckets;
|
||||||
@ -846,25 +596,9 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
search_space_with_buckets,
|
search_space_with_buckets,
|
||||||
weights_table,
|
weights_table,
|
||||||
durations_table,
|
durations_table,
|
||||||
middle_nodes_table,
|
|
||||||
source_phantom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calculate_distance)
|
|
||||||
{
|
|
||||||
distances_table.resize(number_of_entries, INVALID_EDGE_DISTANCE);
|
|
||||||
calculateDistances<DIRECTION>(query_heap,
|
|
||||||
facade,
|
|
||||||
phantom_nodes,
|
|
||||||
target_indices, // source_indices
|
|
||||||
row_idx,
|
|
||||||
source_index,
|
|
||||||
number_of_sources,
|
|
||||||
number_of_targets,
|
|
||||||
search_space_with_buckets,
|
|
||||||
distances_table,
|
distances_table,
|
||||||
middle_nodes_table,
|
middle_nodes_table,
|
||||||
engine_working_data);
|
source_phantom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,48 +626,29 @@ manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
|||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices,
|
const std::vector<std::size_t> &target_indices,
|
||||||
const bool calculate_distance,
|
const bool /* calculate_distance */,
|
||||||
const bool calculate_duration)
|
const bool /* calculate_duration */)
|
||||||
{
|
{
|
||||||
(void)calculate_duration; // flag stub to use for calculating distances in matrix in mld in the
|
|
||||||
// future
|
|
||||||
|
|
||||||
if (source_indices.size() == 1)
|
if (source_indices.size() == 1)
|
||||||
{ // TODO: check if target_indices.size() == 1 and do a bi-directional search
|
{ // TODO: check if target_indices.size() == 1 and do a bi-directional search
|
||||||
return mld::oneToManySearch<FORWARD_DIRECTION>(engine_working_data,
|
return mld::oneToManySearch<FORWARD_DIRECTION>(
|
||||||
facade,
|
engine_working_data, facade, phantom_nodes, source_indices.front(), target_indices);
|
||||||
phantom_nodes,
|
|
||||||
source_indices.front(),
|
|
||||||
target_indices,
|
|
||||||
calculate_distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_indices.size() == 1)
|
if (target_indices.size() == 1)
|
||||||
{
|
{
|
||||||
return mld::oneToManySearch<REVERSE_DIRECTION>(engine_working_data,
|
return mld::oneToManySearch<REVERSE_DIRECTION>(
|
||||||
facade,
|
engine_working_data, facade, phantom_nodes, target_indices.front(), source_indices);
|
||||||
phantom_nodes,
|
|
||||||
target_indices.front(),
|
|
||||||
source_indices,
|
|
||||||
calculate_distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_indices.size() < source_indices.size())
|
if (target_indices.size() < source_indices.size())
|
||||||
{
|
{
|
||||||
return mld::manyToManySearch<REVERSE_DIRECTION>(engine_working_data,
|
return mld::manyToManySearch<REVERSE_DIRECTION>(
|
||||||
facade,
|
engine_working_data, facade, phantom_nodes, target_indices, source_indices);
|
||||||
phantom_nodes,
|
|
||||||
target_indices,
|
|
||||||
source_indices,
|
|
||||||
calculate_distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mld::manyToManySearch<FORWARD_DIRECTION>(engine_working_data,
|
return mld::manyToManySearch<FORWARD_DIRECTION>(
|
||||||
facade,
|
engine_working_data, facade, phantom_nodes, source_indices, target_indices);
|
||||||
phantom_nodes,
|
|
||||||
source_indices,
|
|
||||||
target_indices,
|
|
||||||
calculate_distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
|
@ -114,6 +114,13 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodeDurations(
|
|||||||
swap(m_edge_based_node_durations, output_node_durations);
|
swap(m_edge_based_node_durations, output_node_durations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::GetEdgeBasedNodeDistances(
|
||||||
|
std::vector<EdgeDistance> &output_node_distances)
|
||||||
|
{
|
||||||
|
using std::swap; // Koenig swap
|
||||||
|
swap(m_edge_based_node_distances, output_node_distances);
|
||||||
|
}
|
||||||
|
|
||||||
std::uint32_t EdgeBasedGraphFactory::GetConnectivityChecksum() const
|
std::uint32_t EdgeBasedGraphFactory::GetConnectivityChecksum() const
|
||||||
{
|
{
|
||||||
return m_connectivity_checksum;
|
return m_connectivity_checksum;
|
||||||
@ -291,8 +298,12 @@ unsigned EdgeBasedGraphFactory::LabelEdgeBasedNodes()
|
|||||||
{
|
{
|
||||||
// heuristic: node-based graph node is a simple intersection with four edges
|
// heuristic: node-based graph node is a simple intersection with four edges
|
||||||
// (edge-based nodes)
|
// (edge-based nodes)
|
||||||
m_edge_based_node_weights.reserve(4 * m_node_based_graph.GetNumberOfNodes());
|
constexpr std::size_t ESTIMATED_EDGE_COUNT = 4;
|
||||||
m_edge_based_node_durations.reserve(4 * m_node_based_graph.GetNumberOfNodes());
|
m_edge_based_node_weights.reserve(ESTIMATED_EDGE_COUNT * m_node_based_graph.GetNumberOfNodes());
|
||||||
|
m_edge_based_node_durations.reserve(ESTIMATED_EDGE_COUNT *
|
||||||
|
m_node_based_graph.GetNumberOfNodes());
|
||||||
|
m_edge_based_node_distances.reserve(ESTIMATED_EDGE_COUNT *
|
||||||
|
m_node_based_graph.GetNumberOfNodes());
|
||||||
nbe_to_ebn_mapping.resize(m_node_based_graph.GetEdgeCapacity(), SPECIAL_NODEID);
|
nbe_to_ebn_mapping.resize(m_node_based_graph.GetEdgeCapacity(), SPECIAL_NODEID);
|
||||||
|
|
||||||
// renumber edge based node of outgoing edges
|
// renumber edge based node of outgoing edges
|
||||||
@ -310,6 +321,7 @@ unsigned EdgeBasedGraphFactory::LabelEdgeBasedNodes()
|
|||||||
|
|
||||||
m_edge_based_node_weights.push_back(edge_data.weight);
|
m_edge_based_node_weights.push_back(edge_data.weight);
|
||||||
m_edge_based_node_durations.push_back(edge_data.duration);
|
m_edge_based_node_durations.push_back(edge_data.duration);
|
||||||
|
m_edge_based_node_distances.push_back(edge_data.distance);
|
||||||
|
|
||||||
BOOST_ASSERT(numbered_edges_count < m_node_based_graph.GetNumberOfEdges());
|
BOOST_ASSERT(numbered_edges_count < m_node_based_graph.GetNumberOfEdges());
|
||||||
nbe_to_ebn_mapping[current_edge] = numbered_edges_count;
|
nbe_to_ebn_mapping[current_edge] = numbered_edges_count;
|
||||||
@ -407,6 +419,8 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
|
|||||||
m_edge_based_node_weights.push_back(ebn_weight);
|
m_edge_based_node_weights.push_back(ebn_weight);
|
||||||
m_edge_based_node_durations.push_back(
|
m_edge_based_node_durations.push_back(
|
||||||
m_edge_based_node_durations[nbe_to_ebn_mapping[eid]]);
|
m_edge_based_node_durations[nbe_to_ebn_mapping[eid]]);
|
||||||
|
m_edge_based_node_distances.push_back(
|
||||||
|
m_edge_based_node_distances[nbe_to_ebn_mapping[eid]]);
|
||||||
|
|
||||||
edge_based_node_id++;
|
edge_based_node_id++;
|
||||||
progress.PrintStatus(progress_counter++);
|
progress.PrintStatus(progress_counter++);
|
||||||
@ -416,6 +430,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
|
|||||||
BOOST_ASSERT(m_edge_based_node_segments.size() == m_edge_based_node_is_startpoint.size());
|
BOOST_ASSERT(m_edge_based_node_segments.size() == m_edge_based_node_is_startpoint.size());
|
||||||
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_weights.size());
|
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_weights.size());
|
||||||
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_durations.size());
|
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_durations.size());
|
||||||
|
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_distances.size());
|
||||||
|
|
||||||
util::Log() << "Generated " << m_number_of_edge_based_nodes << " nodes ("
|
util::Log() << "Generated " << m_number_of_edge_based_nodes << " nodes ("
|
||||||
<< way_restriction_map.NumberOfDuplicatedNodes()
|
<< way_restriction_map.NumberOfDuplicatedNodes()
|
||||||
@ -652,16 +667,17 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
// auto turn_id = m_edge_based_edge_list.size();
|
// auto turn_id = m_edge_based_edge_list.size();
|
||||||
auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
|
auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
|
||||||
auto duration = boost::numeric_cast<EdgeWeight>(edge_data1.duration + duration_penalty);
|
auto duration = boost::numeric_cast<EdgeWeight>(edge_data1.duration + duration_penalty);
|
||||||
|
auto distance = boost::numeric_cast<EdgeDistance>(edge_data1.distance);
|
||||||
|
|
||||||
EdgeBasedEdge edge_based_edge = {
|
EdgeBasedEdge edge_based_edge = {edge_based_node_from,
|
||||||
edge_based_node_from,
|
edge_based_node_to,
|
||||||
edge_based_node_to,
|
SPECIAL_NODEID, // This will be updated once the main
|
||||||
SPECIAL_NODEID, // This will be updated once the main loop
|
// loop completes!
|
||||||
// completes!
|
weight,
|
||||||
weight,
|
duration,
|
||||||
duration,
|
distance,
|
||||||
true,
|
true,
|
||||||
false};
|
false};
|
||||||
|
|
||||||
// We write out the mapping between the edge-expanded edges and the original nodes.
|
// We write out the mapping between the edge-expanded edges and the original nodes.
|
||||||
// Since each edge represents a possible maneuver, external programs can use this to
|
// Since each edge represents a possible maneuver, external programs can use this to
|
||||||
|
@ -387,12 +387,16 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
const auto weight = edge_iterator->weight_data(distance);
|
const auto weight = edge_iterator->weight_data(distance);
|
||||||
const auto duration = edge_iterator->duration_data(distance);
|
const auto duration = edge_iterator->duration_data(distance);
|
||||||
|
|
||||||
|
const auto accurate_distance =
|
||||||
|
util::coordinate_calculation::fccApproximateDistance(source_coord, target_coord);
|
||||||
|
|
||||||
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
|
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
|
||||||
scripting_environment.ProcessSegment(segment);
|
scripting_environment.ProcessSegment(segment);
|
||||||
|
|
||||||
auto &edge = edge_iterator->result;
|
auto &edge = edge_iterator->result;
|
||||||
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
|
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
|
||||||
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
|
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
|
||||||
|
edge.distance = accurate_distance;
|
||||||
|
|
||||||
// assign new node id
|
// assign new node id
|
||||||
const auto node_id = mapExternalToInternalNodeID(
|
const auto node_id = mapExternalToInternalNodeID(
|
||||||
|
@ -242,6 +242,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
std::vector<bool> node_is_startpoint;
|
std::vector<bool> node_is_startpoint;
|
||||||
std::vector<EdgeWeight> edge_based_node_weights;
|
std::vector<EdgeWeight> edge_based_node_weights;
|
||||||
std::vector<EdgeDuration> edge_based_node_durations;
|
std::vector<EdgeDuration> edge_based_node_durations;
|
||||||
|
std::vector<EdgeDistance> edge_based_node_distances;
|
||||||
std::uint32_t ebg_connectivity_checksum = 0;
|
std::uint32_t ebg_connectivity_checksum = 0;
|
||||||
|
|
||||||
// Create a node-based graph from the OSRM file
|
// Create a node-based graph from the OSRM file
|
||||||
@ -322,6 +323,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
node_is_startpoint,
|
node_is_startpoint,
|
||||||
edge_based_node_weights,
|
edge_based_node_weights,
|
||||||
edge_based_node_durations,
|
edge_based_node_durations,
|
||||||
|
edge_based_node_distances,
|
||||||
edge_based_edge_list,
|
edge_based_edge_list,
|
||||||
ebg_connectivity_checksum);
|
ebg_connectivity_checksum);
|
||||||
|
|
||||||
@ -345,8 +347,10 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
|
|
||||||
util::Log() << "Saving edge-based node weights to file.";
|
util::Log() << "Saving edge-based node weights to file.";
|
||||||
TIMER_START(timer_write_node_weights);
|
TIMER_START(timer_write_node_weights);
|
||||||
extractor::files::writeEdgeBasedNodeWeightsDurations(
|
extractor::files::writeEdgeBasedNodeWeightsDurationsDistances(config.GetPath(".osrm.enw"),
|
||||||
config.GetPath(".osrm.enw"), edge_based_node_weights, edge_based_node_durations);
|
edge_based_node_weights,
|
||||||
|
edge_based_node_durations,
|
||||||
|
edge_based_node_distances);
|
||||||
TIMER_STOP(timer_write_node_weights);
|
TIMER_STOP(timer_write_node_weights);
|
||||||
util::Log() << "Done writing. (" << TIMER_SEC(timer_write_node_weights) << ")";
|
util::Log() << "Done writing. (" << TIMER_SEC(timer_write_node_weights) << ")";
|
||||||
|
|
||||||
@ -736,6 +740,7 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
|||||||
std::vector<bool> &node_is_startpoint,
|
std::vector<bool> &node_is_startpoint,
|
||||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||||
std::vector<EdgeDuration> &edge_based_node_durations,
|
std::vector<EdgeDuration> &edge_based_node_durations,
|
||||||
|
std::vector<EdgeDistance> &edge_based_node_distances,
|
||||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||||
std::uint32_t &connectivity_checksum)
|
std::uint32_t &connectivity_checksum)
|
||||||
{
|
{
|
||||||
@ -786,6 +791,7 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
|||||||
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
|
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
|
||||||
edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights);
|
edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights);
|
||||||
edge_based_graph_factory.GetEdgeBasedNodeDurations(edge_based_node_durations);
|
edge_based_graph_factory.GetEdgeBasedNodeDurations(edge_based_node_durations);
|
||||||
|
edge_based_graph_factory.GetEdgeBasedNodeDistances(edge_based_node_distances);
|
||||||
connectivity_checksum = edge_based_graph_factory.GetConnectivityChecksum();
|
connectivity_checksum = edge_based_graph_factory.GetConnectivityChecksum();
|
||||||
|
|
||||||
return number_of_edge_based_nodes;
|
return number_of_edge_based_nodes;
|
||||||
|
@ -415,6 +415,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||||
0, // weight
|
0, // weight
|
||||||
0, // duration
|
0, // duration
|
||||||
|
0, // distance
|
||||||
{}, // geometry id
|
{}, // geometry id
|
||||||
static_cast<AnnotationID>(annotation_data_id),
|
static_cast<AnnotationID>(annotation_data_id),
|
||||||
{true,
|
{true,
|
||||||
@ -450,6 +451,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||||
0, // weight
|
0, // weight
|
||||||
0, // duration
|
0, // duration
|
||||||
|
0, // distance
|
||||||
{}, // geometry id
|
{}, // geometry id
|
||||||
static_cast<AnnotationID>(annotation_data_id),
|
static_cast<AnnotationID>(annotation_data_id),
|
||||||
{false,
|
{false,
|
||||||
|
@ -259,6 +259,7 @@ void GraphCompressor::Compress(
|
|||||||
const auto forward_weight2 = fwd_edge_data2.weight;
|
const auto forward_weight2 = fwd_edge_data2.weight;
|
||||||
const auto forward_duration1 = fwd_edge_data1.duration;
|
const auto forward_duration1 = fwd_edge_data1.duration;
|
||||||
const auto forward_duration2 = fwd_edge_data2.duration;
|
const auto forward_duration2 = fwd_edge_data2.duration;
|
||||||
|
const auto forward_distance2 = fwd_edge_data2.distance;
|
||||||
|
|
||||||
BOOST_ASSERT(0 != forward_weight1);
|
BOOST_ASSERT(0 != forward_weight1);
|
||||||
BOOST_ASSERT(0 != forward_weight2);
|
BOOST_ASSERT(0 != forward_weight2);
|
||||||
@ -267,6 +268,17 @@ void GraphCompressor::Compress(
|
|||||||
const auto reverse_weight2 = rev_edge_data2.weight;
|
const auto reverse_weight2 = rev_edge_data2.weight;
|
||||||
const auto reverse_duration1 = rev_edge_data1.duration;
|
const auto reverse_duration1 = rev_edge_data1.duration;
|
||||||
const auto reverse_duration2 = rev_edge_data2.duration;
|
const auto reverse_duration2 = rev_edge_data2.duration;
|
||||||
|
const auto reverse_distance2 = rev_edge_data2.distance;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Because distances are symmetrical, we only need one
|
||||||
|
// per edge - here we double-check that they match
|
||||||
|
// their mirrors.
|
||||||
|
const auto reverse_distance1 = rev_edge_data1.distance;
|
||||||
|
const auto forward_distance1 = fwd_edge_data1.distance;
|
||||||
|
BOOST_ASSERT(forward_distance1 == reverse_distance2);
|
||||||
|
BOOST_ASSERT(forward_distance2 == reverse_distance1);
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOST_ASSERT(0 != reverse_weight1);
|
BOOST_ASSERT(0 != reverse_weight1);
|
||||||
BOOST_ASSERT(0 != reverse_weight2);
|
BOOST_ASSERT(0 != reverse_weight2);
|
||||||
@ -279,6 +291,10 @@ void GraphCompressor::Compress(
|
|||||||
graph.GetEdgeData(forward_e1).duration += forward_duration2;
|
graph.GetEdgeData(forward_e1).duration += forward_duration2;
|
||||||
graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
|
graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
|
||||||
|
|
||||||
|
// add distance of e2's to e1
|
||||||
|
graph.GetEdgeData(forward_e1).distance += forward_distance2;
|
||||||
|
graph.GetEdgeData(reverse_e1).distance += reverse_distance2;
|
||||||
|
|
||||||
if (node_weight_penalty != INVALID_EDGE_WEIGHT &&
|
if (node_weight_penalty != INVALID_EDGE_WEIGHT &&
|
||||||
node_duration_penalty != MAXIMAL_EDGE_DURATION)
|
node_duration_penalty != MAXIMAL_EDGE_DURATION)
|
||||||
{
|
{
|
||||||
@ -286,6 +302,7 @@ void GraphCompressor::Compress(
|
|||||||
graph.GetEdgeData(reverse_e1).weight += node_weight_penalty;
|
graph.GetEdgeData(reverse_e1).weight += node_weight_penalty;
|
||||||
graph.GetEdgeData(forward_e1).duration += node_duration_penalty;
|
graph.GetEdgeData(forward_e1).duration += node_duration_penalty;
|
||||||
graph.GetEdgeData(reverse_e1).duration += node_duration_penalty;
|
graph.GetEdgeData(reverse_e1).duration += node_duration_penalty;
|
||||||
|
// Note: no penalties for distances
|
||||||
}
|
}
|
||||||
|
|
||||||
// extend e1's to targets of e2's
|
// extend e1's to targets of e2's
|
||||||
|
@ -147,12 +147,15 @@ int Partitioner::Run(const PartitionerConfig &config)
|
|||||||
{
|
{
|
||||||
std::vector<EdgeWeight> node_weights;
|
std::vector<EdgeWeight> node_weights;
|
||||||
std::vector<EdgeDuration> node_durations;
|
std::vector<EdgeDuration> node_durations;
|
||||||
|
std::vector<EdgeDuration> node_distances;
|
||||||
extractor::files::readEdgeBasedNodeWeightsDurations(
|
extractor::files::readEdgeBasedNodeWeightsDurations(
|
||||||
config.GetPath(".osrm.enw"), node_weights, node_durations);
|
config.GetPath(".osrm.enw"), node_weights, node_durations);
|
||||||
|
extractor::files::readEdgeBasedNodeDistances(config.GetPath(".osrm.enw"), node_distances);
|
||||||
util::inplacePermutation(node_weights.begin(), node_weights.end(), permutation);
|
util::inplacePermutation(node_weights.begin(), node_weights.end(), permutation);
|
||||||
util::inplacePermutation(node_durations.begin(), node_durations.end(), permutation);
|
util::inplacePermutation(node_durations.begin(), node_durations.end(), permutation);
|
||||||
extractor::files::writeEdgeBasedNodeWeightsDurations(
|
util::inplacePermutation(node_distances.begin(), node_distances.end(), permutation);
|
||||||
config.GetPath(".osrm.enw"), node_weights, node_durations);
|
extractor::files::writeEdgeBasedNodeWeightsDurationsDistances(
|
||||||
|
config.GetPath(".osrm.enw"), node_weights, node_durations, node_distances);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto &filename = config.GetPath(".osrm.maneuver_overrides");
|
const auto &filename = config.GetPath(".osrm.maneuver_overrides");
|
||||||
|
@ -17,7 +17,8 @@ bool operator!=(const QueryEdge &lhs, const QueryEdge &rhs) { return !(lhs == rh
|
|||||||
std::ostream &operator<<(std::ostream &out, const QueryEdge::EdgeData &data)
|
std::ostream &operator<<(std::ostream &out, const QueryEdge::EdgeData &data)
|
||||||
{
|
{
|
||||||
out << "{" << data.turn_id << ", " << data.shortcut << ", " << data.duration << ", "
|
out << "{" << data.turn_id << ", " << data.shortcut << ", " << data.duration << ", "
|
||||||
<< data.weight << ", " << data.forward << ", " << data.backward << "}";
|
<< data.distance << ", " << data.weight << ", " << data.forward << ", " << data.backward
|
||||||
|
<< "}";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,31 +37,31 @@ BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_graph)
|
|||||||
ContractedEdgeContainer container;
|
ContractedEdgeContainer container;
|
||||||
|
|
||||||
std::vector<QueryEdge> edges;
|
std::vector<QueryEdge> edges;
|
||||||
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{0, 1, {1, false, 3, 3, 6, true, false}});
|
||||||
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{1, 2, {2, false, 3, 3, 6, true, false}});
|
||||||
edges.push_back(QueryEdge{2, 0, {3, false, 3, 6, false, true}});
|
edges.push_back(QueryEdge{2, 0, {3, false, 3, 3, 6, false, true}});
|
||||||
edges.push_back(QueryEdge{2, 1, {4, false, 3, 6, false, true}});
|
edges.push_back(QueryEdge{2, 1, {4, false, 3, 3, 6, false, true}});
|
||||||
container.Insert(edges);
|
container.Insert(edges);
|
||||||
|
|
||||||
edges.clear();
|
edges.clear();
|
||||||
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{0, 1, {1, false, 3, 3, 6, true, false}});
|
||||||
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{1, 2, {2, false, 3, 3, 6, true, false}});
|
||||||
edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
|
edges.push_back(QueryEdge{2, 0, {3, false, 12, 12, 24, false, true}});
|
||||||
edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
|
edges.push_back(QueryEdge{2, 1, {4, false, 12, 12, 24, false, true}});
|
||||||
container.Merge(edges);
|
container.Merge(edges);
|
||||||
|
|
||||||
edges.clear();
|
edges.clear();
|
||||||
edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{1, 4, {5, false, 3, 3, 6, true, false}});
|
||||||
container.Merge(edges);
|
container.Merge(edges);
|
||||||
|
|
||||||
std::vector<QueryEdge> reference_edges;
|
std::vector<QueryEdge> reference_edges;
|
||||||
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
|
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 3, 6, true, false}});
|
||||||
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
|
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 3, 6, true, false}});
|
||||||
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
|
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 3, 6, true, false}});
|
||||||
reference_edges.push_back(QueryEdge{2, 0, {3, false, 3, 6, false, true}});
|
reference_edges.push_back(QueryEdge{2, 0, {3, false, 3, 3, 6, false, true}});
|
||||||
reference_edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
|
reference_edges.push_back(QueryEdge{2, 0, {3, false, 12, 12, 24, false, true}});
|
||||||
reference_edges.push_back(QueryEdge{2, 1, {4, false, 3, 6, false, true}});
|
reference_edges.push_back(QueryEdge{2, 1, {4, false, 3, 3, 6, false, true}});
|
||||||
reference_edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
|
reference_edges.push_back(QueryEdge{2, 1, {4, false, 12, 12, 24, false, true}});
|
||||||
CHECK_EQUAL_COLLECTIONS(container.edges, reference_edges);
|
CHECK_EQUAL_COLLECTIONS(container.edges, reference_edges);
|
||||||
|
|
||||||
auto filters = container.MakeEdgeFilters();
|
auto filters = container.MakeEdgeFilters();
|
||||||
@ -78,22 +79,22 @@ BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_disjoint_graph)
|
|||||||
ContractedEdgeContainer container;
|
ContractedEdgeContainer container;
|
||||||
|
|
||||||
std::vector<QueryEdge> edges;
|
std::vector<QueryEdge> edges;
|
||||||
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{0, 1, {1, false, 3, 3, 6, true, false}});
|
||||||
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{1, 2, {2, false, 3, 3, 6, true, false}});
|
||||||
edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
|
edges.push_back(QueryEdge{2, 0, {3, false, 12, 12, 24, false, true}});
|
||||||
edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
|
edges.push_back(QueryEdge{2, 1, {4, false, 12, 12, 24, false, true}});
|
||||||
container.Merge(edges);
|
container.Merge(edges);
|
||||||
|
|
||||||
edges.clear();
|
edges.clear();
|
||||||
edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
|
edges.push_back(QueryEdge{1, 4, {5, false, 3, 3, 6, true, false}});
|
||||||
container.Merge(edges);
|
container.Merge(edges);
|
||||||
|
|
||||||
std::vector<QueryEdge> reference_edges;
|
std::vector<QueryEdge> reference_edges;
|
||||||
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
|
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 3, 6, true, false}});
|
||||||
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
|
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 3, 6, true, false}});
|
||||||
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
|
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 3, 6, true, false}});
|
||||||
reference_edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
|
reference_edges.push_back(QueryEdge{2, 0, {3, false, 12, 12, 24, false, true}});
|
||||||
reference_edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
|
reference_edges.push_back(QueryEdge{2, 1, {4, false, 12, 12, 24, false, true}});
|
||||||
CHECK_EQUAL_COLLECTIONS(container.edges, reference_edges);
|
CHECK_EQUAL_COLLECTIONS(container.edges, reference_edges);
|
||||||
|
|
||||||
auto filters = container.MakeEdgeFilters();
|
auto filters = container.MakeEdgeFilters();
|
||||||
|
@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE(contract_graph)
|
|||||||
reference_graph.DeleteEdgesTo(1, 3);
|
reference_graph.DeleteEdgesTo(1, 3);
|
||||||
reference_graph.DeleteEdgesTo(4, 3);
|
reference_graph.DeleteEdgesTo(4, 3);
|
||||||
// Insert shortcut
|
// Insert shortcut
|
||||||
reference_graph.InsertEdge(4, 1, {2, 4, 3, 0, true, true, false});
|
reference_graph.InsertEdge(4, 1, {2, 4, 1.0, 3, 0, true, true, false});
|
||||||
|
|
||||||
/* After contracting 4:
|
/* After contracting 4:
|
||||||
*
|
*
|
||||||
|
@ -20,15 +20,19 @@ inline contractor::ContractorGraph makeGraph(const std::vector<TestEdge> &edges)
|
|||||||
unsigned target;
|
unsigned target;
|
||||||
int weight;
|
int weight;
|
||||||
std::tie(start, target, weight) = edge;
|
std::tie(start, target, weight) = edge;
|
||||||
|
int duration = weight * 2;
|
||||||
|
float distance = 1.0;
|
||||||
max_id = std::max(std::max(start, target), max_id);
|
max_id = std::max(std::max(start, target), max_id);
|
||||||
input_edges.push_back(contractor::ContractorEdge{
|
input_edges.push_back(contractor::ContractorEdge{
|
||||||
start,
|
start,
|
||||||
target,
|
target,
|
||||||
contractor::ContractorEdgeData{weight, weight * 2, id++, 0, false, true, false}});
|
contractor::ContractorEdgeData{
|
||||||
|
weight, duration, distance, id++, 0, false, true, false}});
|
||||||
input_edges.push_back(contractor::ContractorEdge{
|
input_edges.push_back(contractor::ContractorEdge{
|
||||||
target,
|
target,
|
||||||
start,
|
start,
|
||||||
contractor::ContractorEdgeData{weight, weight * 2, id++, 0, false, false, true}});
|
contractor::ContractorEdgeData{
|
||||||
|
weight, duration, distance, id++, 0, false, false, true}});
|
||||||
}
|
}
|
||||||
std::sort(input_edges.begin(), input_edges.end());
|
std::sort(input_edges.begin(), input_edges.end());
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector<MockEdge> &mock
|
|||||||
{
|
{
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeDuration duration;
|
EdgeDuration duration;
|
||||||
|
EdgeDistance distance;
|
||||||
bool forward;
|
bool forward;
|
||||||
bool backward;
|
bool backward;
|
||||||
};
|
};
|
||||||
@ -36,8 +37,20 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector<MockEdge> &mock
|
|||||||
for (const auto &m : mock_edges)
|
for (const auto &m : mock_edges)
|
||||||
{
|
{
|
||||||
max_id = std::max<std::size_t>(max_id, std::max(m.start, m.target));
|
max_id = std::max<std::size_t>(max_id, std::max(m.start, m.target));
|
||||||
edges.push_back(Edge{m.start, m.target, m.weight, 2 * m.weight, true, false});
|
edges.push_back(Edge{m.start,
|
||||||
edges.push_back(Edge{m.target, m.start, m.weight, 2 * m.weight, false, true});
|
m.target,
|
||||||
|
m.weight,
|
||||||
|
2 * m.weight,
|
||||||
|
static_cast<EdgeDistance>(1.0),
|
||||||
|
true,
|
||||||
|
false});
|
||||||
|
edges.push_back(Edge{m.target,
|
||||||
|
m.start,
|
||||||
|
m.weight,
|
||||||
|
2 * m.weight,
|
||||||
|
static_cast<EdgeDistance>(1.0),
|
||||||
|
false,
|
||||||
|
true});
|
||||||
}
|
}
|
||||||
std::sort(edges.begin(), edges.end());
|
std::sort(edges.begin(), edges.end());
|
||||||
return partitioner::MultiLevelGraph<EdgeData, osrm::storage::Ownership::Container>(
|
return partitioner::MultiLevelGraph<EdgeData, osrm::storage::Ownership::Container>(
|
||||||
|
@ -31,6 +31,7 @@ inline InputEdge MakeUnitEdge(const NodeID from, const NodeID to)
|
|||||||
to, // target
|
to, // target
|
||||||
1, // weight
|
1, // weight
|
||||||
1, // duration
|
1, // duration
|
||||||
|
1, // distance
|
||||||
GeometryID{0, false}, // geometry_id
|
GeometryID{0, false}, // geometry_id
|
||||||
false, // reversed
|
false, // reversed
|
||||||
NodeBasedEdgeClassification(), // default flags
|
NodeBasedEdgeClassification(), // default flags
|
||||||
|
@ -47,6 +47,7 @@ BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
|
|||||||
to,
|
to,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
|
1,
|
||||||
GeometryID{0, false},
|
GeometryID{0, false},
|
||||||
!allowed,
|
!allowed,
|
||||||
NodeBasedEdgeClassification(),
|
NodeBasedEdgeClassification(),
|
||||||
@ -174,6 +175,7 @@ BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
|
|||||||
to,
|
to,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
|
1,
|
||||||
GeometryID{0, false},
|
GeometryID{0, false},
|
||||||
!allowed,
|
!allowed,
|
||||||
NodeBasedEdgeClassification{
|
NodeBasedEdgeClassification{
|
||||||
@ -277,7 +279,7 @@ BOOST_AUTO_TEST_CASE(skip_degree_two_nodes)
|
|||||||
//
|
//
|
||||||
const auto unit_edge = [](const NodeID from, const NodeID to, bool allowed) {
|
const auto unit_edge = [](const NodeID from, const NodeID to, bool allowed) {
|
||||||
return InputEdge{
|
return InputEdge{
|
||||||
from, to, 1, 1, GeometryID{0, false}, !allowed, NodeBasedEdgeClassification{}, 0};
|
from, to, 1, 1, 1, GeometryID{0, false}, !allowed, NodeBasedEdgeClassification{}, 0};
|
||||||
};
|
};
|
||||||
std::vector<InputEdge> edges = {unit_edge(0, 1, true), // 0
|
std::vector<InputEdge> edges = {unit_edge(0, 1, true), // 0
|
||||||
unit_edge(1, 0, true),
|
unit_edge(1, 0, true),
|
||||||
|
@ -32,9 +32,9 @@ auto makeGraph(const std::vector<MockEdge> &mock_edges)
|
|||||||
max_id = std::max<std::size_t>(max_id, std::max(m.start, m.target));
|
max_id = std::max<std::size_t>(max_id, std::max(m.start, m.target));
|
||||||
|
|
||||||
edges.push_back(InputEdge{
|
edges.push_back(InputEdge{
|
||||||
m.start, m.target, EdgeBasedGraphEdgeData{SPECIAL_NODEID, 1, 1, true, false}});
|
m.start, m.target, EdgeBasedGraphEdgeData{SPECIAL_NODEID, 1, 1, 1, true, false}});
|
||||||
edges.push_back(InputEdge{
|
edges.push_back(InputEdge{
|
||||||
m.target, m.start, EdgeBasedGraphEdgeData{SPECIAL_NODEID, 1, 1, false, true}});
|
m.target, m.start, EdgeBasedGraphEdgeData{SPECIAL_NODEID, 1, 1, 1, false, true}});
|
||||||
}
|
}
|
||||||
std::sort(edges.begin(), edges.end());
|
std::sort(edges.begin(), edges.end());
|
||||||
return DynamicEdgeBasedGraph(max_id + 1, edges);
|
return DynamicEdgeBasedGraph(max_id + 1, edges);
|
||||||
|
Loading…
Reference in New Issue
Block a user