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