GIScience / openrouteservice

🌍 The open source route planner api with plenty of features.
https://openrouteservice.org
GNU General Public License v3.0
1.43k stars 392 forks source link

Evaluate priority weightings for cycling profiles #665

Closed aoles closed 4 years ago

aoles commented 4 years ago

Investigate the difference in routing between original GraphHopper's PriorityWeighting and ours OptimizedPriorityWeighting in the context of reducing the number of preparations needed for running CALT with bike profiles.

The original GH weight scaling function based on priorities: image

ORS OptimizedPriorityWeighting: image

What currently happens is that the penalties of WORST (0), AVOID_AT_ALL_COSTS (1) and REACH_DEST (2) are bumped up by multiplying the weights by 1.25. However, the weight of AVOID_IF_POSSIBLE (3) is multiplied by 2.0 increasing it beyond AVOID_AT_ALL_COSTS. Effectively this means rearranging the priorities by stating that AVOID_IF_POSSIBLE is worse than AVOID_AT_ALL_COSTS. The factor for AVOID_IF_POSSIBLE was changed 3 years ago from 1.1 to 2.0 for no apparent reason.

Evaluate the impact of the following alternatives of altering OptimizedPriorityWeighting:

An example where the fastest route makes more sense than the recommended one.

aoles commented 4 years ago

R script for visualizing the weight scaling functions

PRIORITY_CODE = c(
  WORST = 0,
  AVOID_AT_ALL_COSTS = 1,
  REACH_DEST = 2,
  AVOID_IF_POSSIBLE = 3,
  UNCHANGED = 4,
  PREFER = 5, 
  VERY_NICE = 6,
  BEST = 7
)

## priority values returned by the priority encoder
priority <- function(code) code / unname(PRIORITY_CODE["BEST"])

sapply(PRIORITY_CODE, priority)
#>              WORST AVOID_AT_ALL_COSTS         REACH_DEST  AVOID_IF_POSSIBLE 
#>          0.0000000          0.1428571          0.2857143          0.4285714 
#>          UNCHANGED             PREFER          VERY_NICE               BEST 
#>          0.5714286          0.7142857          0.8571429          1.0000000

## original weight scaling function
priorityWeighting <- function(x) 1 / (0.5 + priority(x)) 

## current recommendend weighting
optimizedPriorityWeighting <- function(x) {
  w = 1
  if (x <= PRIORITY_CODE["REACH_DEST"])
    w = w * 1.25
  else if (x <= PRIORITY_CODE["AVOID_IF_POSSIBLE"])
    w = w * 2

  w / (0.5 + priority(x)) 
}

## reduce the factor for priority AVOID_IF_POSSIBLE (3) from 2.0 to 1.25
optimizedPriorityWeightingReduce <- function(x) {
  w = 1
  if (x <= PRIORITY_CODE["AVOID_IF_POSSIBLE"])
    w = w * 1.25

  w / (0.5 + priority(x)) 
}

## scale all "bad" priorities 0-3 equally by 2.0 (increase steepness of the curve)
optimizedPriorityWeightingScale <- function(x) {
  w = 1
  if (x <= PRIORITY_CODE["AVOID_IF_POSSIBLE"])
    w = w * 2

  w / (0.5 + priority(x)) 
}

## plots
plot(PRIORITY_CODE, sapply(PRIORITY_CODE, priorityWeighting), ylim = c(0.5, 4), pch = 16, ylab = "weight scaling")
points(PRIORITY_CODE, sapply(PRIORITY_CODE, optimizedPriorityWeighting), col = "red")
points(PRIORITY_CODE, sapply(PRIORITY_CODE, optimizedPriorityWeightingReduce), col = "green", pch = 3)
points(PRIORITY_CODE, sapply(PRIORITY_CODE, optimizedPriorityWeightingScale), col = "blue", pch = 4)

Created on 2020-04-20 by the reprex package (v0.3.0)

aoles commented 4 years ago

Proposed new priority scaling function for recommended (blue) vs. the GH's default priorityWeighting (black) and current recommended (red).

newPriorityWeighting <- function(x) {
  best = PRIORITY_CODE["BEST"]
  val = priority(x) * best - ceiling(best/2)
  2^(-val/3) 
}

image

aoles commented 4 years ago

Evaluation results of recommended weighting alternatives:

The results were obtained with https://github.com/GIScience/openrouteservice/commit/63b3313d9dcb141ccbf051a8a7b1e485422838f1.