mapbox / mapbox/node-or-tools

Problem when providing pair of pickup and delivery indices

Ouverte
#63 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Langage dominant
C++
Étoiles
155
Forks
47
Métriques de merge des PR
Aucune PR mergée en 30 j

Description

Hey,

There is this issue where providing a pair of pickup and delivery indices would lead to this error message: Unable to find a solution

Expected Behavior

It should return a valid route order based on cost array.

Current Behavior

Returns Unable to find a solution

Steps to Reproduce

  1. Copy node-or-tools/test/vrp.js file content to a new file
  2. Remove all assertions
  3. Add a pair of pickup and delivery indices in searchOpts.
   pickups: [4, 7],
   deliveries: [7, 10]

Context (Environment)

I have a pair of pickup and delivery indices and I want to visit one or more stops before visiting others.

This is my code snippet. You could see that if we remove the pickup and delivery indices, the code will work but after adding aforementioned indices, it returns Unable to find a solution

module.exports = () => {
  const ortools = require('node_or_tools')
  var locations = [
    [0, 0], [0, 1], [0, 2], [0, 3],
    [1, 0], [1, 1], [1, 2], [1, 3],
    [2, 0], [2, 1], [2, 2], [2, 3],
    [3, 0], [3, 1], [3, 2], [3, 3]]

  var depot = 0

  function manhattanDistance(lhs, rhs) {
    return Math.abs(lhs[0] - rhs[0]) + Math.abs(lhs[1] - rhs[1])
  }

  var costMatrix = new Array(locations.length)

  for (var from = 0; from < locations.length; ++from) {
    costMatrix[from] = new Array(locations.length)

    for (var to = 0; to < locations.length; ++to) {
      costMatrix[from][to] = manhattanDistance(locations[from], locations[to])
    }
  }

  var dayStarts = Hours(0)
  var dayEnds = Hours(3)


  var seed = 2147483650

  function ParkMillerRNG(seed) {
    var modulus = 2147483647
    var multiplier = 48271
    var increment = 0
    var state = seed

    return function() {
      state = (multiplier * state + increment) % modulus
      return state / modulus
    }
  }

  var rand = ParkMillerRNG(seed)


  function Seconds(v) {
    return v
  }

  function Minutes(v) {
    return Seconds(v * 60)
  }

  function Hours(v) {
    return Minutes(v * 60)
  }


  var durationMatrix = new Array(locations.length)

  for (var from = 0; from < locations.length; ++from) {
    durationMatrix[from] = new Array(locations.length)

    for (var to = 0; to < locations.length; ++to) {
      var serviceTime = Minutes(3)
      var travelTime = Minutes(costMatrix[from][to])

      durationMatrix[from][to] = serviceTime + travelTime
    }
  }


  var timeWindows = new Array(locations.length)

  for (var at = 0; at < locations.length; ++at) {
    if (at === depot) {
      timeWindows[at] = [dayStarts, dayEnds]
      continue
    }

    var earliest = dayStarts
    var latest = dayEnds - Hours(1)

    var start = rand() * (latest - earliest) + earliest
    var stop = rand() * (latest - start) + start

    timeWindows[at] = [start, stop]
  }


  var demandMatrix = new Array(locations.length)

  for (var from = 0; from < locations.length; ++from) {
    demandMatrix[from] = new Array(locations.length)

    for (var to = 0; to < locations.length; ++to) {
      if (from === depot)
        demandMatrix[from][to] = 0
      else
        demandMatrix[from][to] = 1
    }
  }


  var solverOpts = {
    numNodes: locations.length,
    costs: costMatrix,
    durations: durationMatrix,
    timeWindows: timeWindows,
    demands: demandMatrix
  }

  var VRP = new ortools.VRP(solverOpts)

  var numVehicles = 10
  var timeHorizon = dayEnds - dayStarts
  var vehicleCapacity = 10

// Dummy lock to let vehicle 0 go to location 2 and 3 first - to test route locks
  var routeLocks = new Array(numVehicles)

  for (var vehicle = 0; vehicle < numVehicles; ++vehicle) {
    if (vehicle === 0)
      routeLocks[vehicle] = [2, 3]
    else
      routeLocks[vehicle] = []
  }

  var searchOpts = {
    computeTimeLimit: 1000,
    numVehicles: numVehicles,
    depotNode: depot,
    timeHorizon: timeHorizon,
    vehicleCapacity: vehicleCapacity,
    routeLocks: routeLocks,
    pickups: [4, 7],
    deliveries: [7, 10]
  }

  VRP.Solve(searchOpts, function(err, solution) {


    console.log('**********************')
    console.log(err,solution)
    console.log('**********************')
    function used(v) {
      return v.length == 0 ? 0 : 1
    }

    function addition(l, r) {
      return l + r
    }

    var numVehiclesUsed = solution.routes.map(used).reduce(addition, 0)


    function checkRoute(v) {
      var depotInRoute = v.find(function(u) {
        return u == depot
      })
    }

    function checkTimeWindows(v) {
      v.forEach(function(u) {
      })
    }

    solution.routes.forEach(checkRoute)
    solution.times.forEach(checkTimeWindows)

  })

}

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par node-or-tools/test/vrp.js, reproduisez l’échec en utilisant les pickups, deliveries, routeLocks et time windows indiqués, puis suivez le point d’entrée de VRP.Solve jusqu’au binding. Comparez le cas en échec avec le même exemple sans indices de pickup et de delivery. C’est terminé lorsque l’exemple renvoie un ordre de routes valide sans signaler "Unable to find a solution".

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
cpp, javascript, node.js
Domaine
backend
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.