Merge pull request #5251 from Project-OSRM/danpat_cache_distances

Pre-calculate distance values
This commit is contained in:
Daniel Patterson 2018-10-30 16:14:47 -07:00 committed by GitHub
commit cb1db646f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 782 additions and 984 deletions

View File

@ -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)

View File

@ -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 |

View File

@ -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
""" """
ab ef ab ef
\ /
dc hg dc hg
ij mn ij mn
/ \
lkpo lkpo
""" """
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

View File

@ -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;

View File

@ -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

View File

@ -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);
} }
}; };
} }

View File

@ -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};
} }
} }
} }

View File

@ -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;
}; };
} }

View File

@ -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;
}; };

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -34,8 +34,7 @@ class RoutingAlgorithmsInterface
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes, ManyToManySearch(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 = 0;
const bool calculate_duration) const = 0;
virtual routing_algorithms::SubMatchingList virtual routing_algorithms::SubMatchingList
MapMatching(const routing_algorithms::CandidateLists &candidates_list, MapMatching(const routing_algorithms::CandidateLists &candidates_list,
@ -88,8 +87,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes, ManyToManySearch(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 final override;
const bool calculate_duration) const final override;
routing_algorithms::SubMatchingList routing_algorithms::SubMatchingList
MapMatching(const routing_algorithms::CandidateLists &candidates_list, MapMatching(const routing_algorithms::CandidateLists &candidates_list,
@ -198,8 +196,7 @@ std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes, RoutingAlgorithms<Algorithm>::ManyToManySearch(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
const bool calculate_duration) const
{ {
BOOST_ASSERT(!phantom_nodes.empty()); BOOST_ASSERT(!phantom_nodes.empty());
@ -222,8 +219,7 @@ RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &p
phantom_nodes, phantom_nodes,
std::move(source_indices), std::move(source_indices),
std::move(target_indices), std::move(target_indices),
calculate_distance, calculate_distance);
calculate_duration);
} }
template <typename Algorithm> template <typename Algorithm>

View File

@ -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)
{ {
} }
@ -94,8 +97,7 @@ manyToManySearch(SearchEngineData<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);
} // namespace routing_algorithms } // namespace routing_algorithms
} // namespace engine } // namespace engine

View File

@ -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()});
} }
} }

View File

@ -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);
} }
/** /**

View File

@ -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,

View File

@ -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)
{ {
} }
}; };

View File

@ -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}
{ {
} }

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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))
{ {
} }

View File

@ -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.");

View File

@ -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()};
} }

View File

@ -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);
} }

View File

@ -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));
} }

View File

@ -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;

View File

@ -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_*/

View File

@ -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());

View File

@ -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();

View File

@ -6,8 +6,12 @@ var fs = require('fs');
var name = process.argv[2]; var name = process.argv[2];
var cmd = process.argv.slice(3).join(' '); var cmd = process.argv.slice(3).join(' ');
var start = Date.now(); var start = Date.now();
exec(cmd, (err) => { exec(cmd, (err, stdout, stderr) => {
if (err) return console.log(err); if (err) {
console.log(stdout);
console.log(stderr);
return process.exit(err.code);
}
var stop = +new Date(); var stop = +new Date();
var time = (stop - start) / 1000.; var time = (stop - start) / 1000.;
fs.appendFileSync('/tmp/osrm.timings', `${name}\t${time}`, 'utf-8'); fs.appendFileSync('/tmp/osrm.timings', `${name}\t${time}`, 'utf-8');

View File

@ -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,

View File

@ -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);

View File

@ -86,7 +86,7 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
bool request_duration = params.annotations & api::TableParameters::AnnotationsType::Duration; bool request_duration = params.annotations & api::TableParameters::AnnotationsType::Duration;
auto result_tables_pair = algorithms.ManyToManySearch( auto result_tables_pair = algorithms.ManyToManySearch(
snapped_phantoms, params.sources, params.destinations, request_distance, request_duration); snapped_phantoms, params.sources, params.destinations, request_distance);
if ((request_duration && result_tables_pair.first.empty()) || if ((request_duration && result_tables_pair.first.empty()) ||
(request_distance && result_tables_pair.second.empty())) (request_distance && result_tables_pair.second.empty()))

View File

@ -217,10 +217,7 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
// compute the duration table of all phantom nodes // compute the duration table of all phantom nodes
auto result_duration_table = util::DistTableWrapper<EdgeWeight>( auto result_duration_table = util::DistTableWrapper<EdgeWeight>(
algorithms algorithms.ManyToManySearch(snapped_phantoms, {}, {}, /*requestDistance*/ false).first,
.ManyToManySearch(
snapped_phantoms, {}, {}, /*requestDistance*/ false, /*requestDuration*/ true)
.first,
number_of_locations); number_of_locations);
if (result_duration_table.size() == 0) if (result_duration_table.size() == 0)

View File

@ -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)

View File

@ -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,29 @@ 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 &current_weight = weights_table[row_index * number_of_targets + column_index]; auto &current_weight = weights_table[row_index * number_of_targets + column_index];
EdgeDistance nulldistance = 0;
auto &current_duration = durations_table[row_index * number_of_targets + column_index]; auto &current_duration = durations_table[row_index * number_of_targets + column_index];
auto &current_distance =
distances_table.empty() ? nulldistance
: 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 +147,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 +165,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 +185,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)
{ {
(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(calculate_distance ? number_of_entries : 0,
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 +243,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);

View File

@ -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);
} }
} }
@ -182,11 +198,12 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
{ {
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(calculate_distance ? phantom_indices.size() : 0,
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 +218,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 +235,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 +253,55 @@ 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;
EdgeDistance nulldistance = 0;
auto &current_distance =
distances_table.empty() ? nulldistance : distances_table[index];
if (std::tie(path_weight, path_duration, path_distance) <
std::tie(weights[index], durations[index], current_distance))
{
weights[index] = path_weight;
durations[index] = path_duration;
current_distance = 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 +324,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 +340,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 +358,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 +378,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 +410,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 +430,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
@ -519,21 +441,27 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
auto &current_weight = weights_table[location]; auto &current_weight = weights_table[location];
auto &current_duration = durations_table[location]; auto &current_duration = durations_table[location];
EdgeDistance nulldistance = 0;
auto &current_distance = distances_table.empty() ? nulldistance : 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 +474,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,182 +531,6 @@ 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,
@ -787,7 +546,8 @@ 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(calculate_distance ? number_of_entries : 0,
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 +606,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,12 +636,8 @@ 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)
{ {
(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>(engine_working_data,

View File

@ -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

View File

@ -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(

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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");

View File

@ -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();

View File

@ -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:
* *

View File

@ -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());

View File

@ -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>(

View File

@ -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

View File

@ -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),

View File

@ -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);