How to Cover Locations

In this use case we are given a number of planning locations. A planning location is typically a customer with an activity. The activity of a customer is usually a cost or weight associated with it. Furthermore, we may also be given cluster facilities. A cluster facility is typically a base from which you want to cover certain customers. A cost or weight can be given to each cluster facility.

A cluster is nothing but a geographical area around a cluster facility that contains or covers all customers that are a given distance or driving time (covering horizon in cover location options) away from that facility.

Note that if cluster facilities are not specified, the software chooses cluster facilities from amongst the planning locations and assumes that the cost of each facility is one.

In the simplest case, each given planning location has an activity of one, and each given cluster facility has cost one. Let us assume that we have 200 planning locations in total. Then:

  • Max. allowed cost goal of 5 means cover as many planning locations as possible with at most 5 clusters.
  • Min. coverage goal of 160 means cover at least 160 (out of 200) planning locations with as few clusters as possible.

Now the cost of a cluster facility can also be considered as

  • the cost of opening an office/facility at the specified location, or
  • the cost of relocating the field workers to the specified location, or
a combination of other factors. Similarly, the cost of a customer or a planning location can also be the profit this customer brings to you, or something else.

Going back to the example above with 200 customers or planning locations. Imagine that each customer means a profit of 10 Euro to the company. In addition, you input a list of 10 cluster facilities, 5 costing 1000 Euro and 5 costing 5000 Euro each. In this case:

  • Max. allowed cost goal of 20000 Euro means cover as many customers as possible with clusters that cost at most 20000 Euro in total.
  • Min. coverage goal of 1400 Euro means cover customers with a total profit of at least 1400 Euro with clusters that cost as less as possible.

Benefits

  • Suggests which clusters cover the given locations.
  • Creating clusters which are geographically compact, based on actual kilometres of road and travel times, to reduce travel time and maximise time with the customer.
  • Provides a cost-profit-analysis.
  • Enables calculation and analysis of different scenarios in a short time.

Prerequisites

  • Installed and licensed PTV xCluster Server

Programming Guide

To call coverLocations specify the locations and the coverLocationsOptions with the optimization goal (minimum coverage and maximum cost) and the covering horizon. In this example the minimum coverage is used. It defines the minimum acceptable percentage of covered location activities:

var locationA = { "location": { "id": "locationA", "routeLocation": { "$type" : "OffRoadRouteLocation", "offRoadCoordinate": { "x": 5.939532, "y": 49.932788 } } }, "activity": 1 }; var locationB = { "location": { "id": "locationB", "routeLocation": { "$type" : "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.086895, "y": 49.918391 } } }, "activity": 1 }; var locationC = { "location": { "id": "locationC", "routeLocation": { "$type" : "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.002422, "y": 49.51459 } } }, "activity": 1 }; xcluster.coverLocations({ "planningLocations": [locationA, locationB, locationC], "coverLocationsOptions": { "coveringHorizon": { "$type": "DistanceBasedHorizon", "distance": "20000" }, "optimizationGoal": { "$type": "MinimumCoverageGoal", "minimumCoverage": "90" } }, "distanceMode": { "$type": "DirectDistance" } }, coverLocationsCompleted); function coverLocationsCompleted(clusterResponse, exception) { var result = ''; for (clusterIdx = 0; clusterIdx < clusterResponse.clusteredLocations.length; clusterIdx++) { result += 'cluster '+ clusterResponse.clusteredLocations[clusterIdx].clusterId + ':'; var locationIds = clusterResponse.clusteredLocations[clusterIdx].locationIds; for (locationIdx = 0; locationIdx < locationIds.length; locationIdx++) { result += ' '; result += locationIds[locationIdx]; } if (clusterIdx < clusterResponse.clusteredLocations.length - 1) { result += ', '; } } print(result); }

Related Topics

The following topics might be relevant for this use case.