PyVRP

The top-level pyvrp module exposes several core classes needed to run the VRP solver. These include the core GeneticAlgorithm, and the Population that manages a Solution pool. Most classes take parameter objects that allow for advanced configuration - but sensible defaults are also provided. Finally, after running, the GeneticAlgorithm returns a Result object. This object can be used to obtain the best observed solution, and detailed runtime statistics.

Hint

Have a look at the examples to see how these classes relate!

class Model

A simple interface for modelling vehicle routing problems with PyVRP.

Attributes:
locations

Returns all locations (depots and clients) in the current model.

vehicle_types

Returns the vehicle types in the current model.

Methods

add_client(x, y[, demand, service_duration, ...])

Adds a client with the given attributes to the model.

add_depot(x, y[, tw_early, tw_late])

Adds a depot with the given attributes to the model.

add_edge(frm, to, distance[, duration])

Adds an edge \((i, j)\) between frm (\(i\)) and to (\(j\)).

add_vehicle_type(capacity, num_available)

Adds a vehicle type with the given number of available vehicles of given capacity to the model.

data()

Creates and returns a ProblemData instance from this model's attributes.

from_data(data)

Constructs a model instance from the given data.

solve(stop[, seed])

Solve this model.

property locations : list[Client]

Returns all locations (depots and clients) in the current model. The clients in the routes of the solution returned by solve() can be used to index these locations.

property vehicle_types : list[VehicleType]

Returns the vehicle types in the current model. The routes of the solution returned by solve() have a property vehicle_type() that can be used to index these vehicle types.

classmethod from_data(data: ProblemData) Model

Constructs a model instance from the given data.

Parameters:
data

Problem data to feed into the model.

Returns:
Model

A model instance representing the given data.

add_client(x: int, y: int, demand: int = 0, service_duration: int = 0, tw_early: int = 0, tw_late: int = 0, release_time: int = 0, prize: int = 0, required: bool = True) Client

Adds a client with the given attributes to the model. Returns the created Client instance.

add_depot(x: int, y: int, tw_early: int = 0, tw_late: int = 0) Client

Adds a depot with the given attributes to the model. Returns the created Client instance.

Warning

PyVRP does not yet support multi-depot VRPs. For now, only one depot can be added to the model.

add_edge(frm: Client, to: Client, distance: int, duration: int = 0) Edge

Adds an edge \((i, j)\) between frm (\(i\)) and to (\(j\)). The edge can be given distance and duration attributes. Distance is required, but the default duration is zero. Returns the created edge.

Raises:
ValueError

When either distance or duration is a negative value.

add_vehicle_type(capacity: int, num_available: int) VehicleType

Adds a vehicle type with the given number of available vehicles of given capacity to the model. Returns the created vehicle type.

Raises:
ValueError

When the number of available vehicles or capacity is not a positive value.

data() ProblemData

Creates and returns a ProblemData instance from this model’s attributes.

solve(stop: StoppingCriterion, seed: int = 0) Result

Solve this model.

Parameters:
stop

Stopping criterion to use.

seed, optional

Seed value to use for the PRNG, by default 0.

Returns:
Result

The solution result object, containing the best found solution.

class Edge(frm: Client, to: Client, distance: int, duration: int)

Stores an edge connecting two locations.

Attributes:
distance
duration
frm
to
class GeneticAlgorithmParams(repair_probability: float = 0.8, nb_iter_no_improvement: int = 20000)

Parameters for the genetic algorithm.

Parameters:
repair_probability

Probability (in \([0, 1]\)) of repairing an infeasible solution. If the reparation makes the solution feasible, it is also added to the population in the same iteration.

nb_iter_no_improvement

Number of iterations without any improvement needed before a restart occurs.

Raises:
ValueError

When repair_probability is not in \([0, 1]\), or nb_iter_no_improvement is negative.

Attributes:
repair_probability

Probability of repairing an infeasible solution.

nb_iter_no_improvement

Number of iterations without improvement before a restart occurs.

class GeneticAlgorithm(data: ProblemData, penalty_manager: PenaltyManager, rng: RandomNumberGenerator, population: Population, search_method: SearchMethod, crossover_op: CrossoverOperator, initial_solutions: Collection[Solution], params: GeneticAlgorithmParams = GeneticAlgorithmParams(repair_probability=0.8, nb_iter_no_improvement=20000))

Creates a GeneticAlgorithm instance.

Parameters:
data

Data object describing the problem to be solved.

penalty_manager

Penalty manager to use.

rng

Random number generator.

population

Population to use.

search_method

Search method to use.

crossover_op

Crossover operator to use for generating offspring.

initial_solutions

Initial solutions to use to initialise the population.

params

Genetic algorithm parameters. If not provided, a default will be used.

Raises:
ValueError

When the population is empty.

Methods

run(stop)

Runs the genetic algorithm with the provided stopping criterion.

run(stop: StoppingCriterion)

Runs the genetic algorithm with the provided stopping criterion.

Parameters:
stop

Stopping criterion to use. The algorithm runs until the first time the stopping criterion returns True.

Returns:
Result

A Result object, containing statistics and the best found solution.

class PenaltyParams(init_capacity_penalty: int = 20, init_time_warp_penalty: int = 6, repair_booster: int = 12, num_registrations_between_penalty_updates: int = 50, penalty_increase: float = 1.34, penalty_decrease: float = 0.32, target_feasible: float = 0.43)

The penalty manager parameters.

Parameters:
init_capacity_penalty

Initial penalty on excess capacity. This is the amount by which one unit of excess load capacity is penalised in the objective, at the start of the search.

init_time_warp_penalty

Initial penalty on time warp. This is the amount by which one unit of time warp (time window violations) is penalised in the objective, at the start of the search.

repair_booster

A repair booster value \(r \ge 1\). This value is used to temporarily multiply the current penalty terms, to force feasibility. See also get_booster_cost_evaluator().

num_registrations_between_penalty_updates

Number of feasibility registrations between penalty value updates. The penalty manager updates the penalty terms every once in a while based on recent feasibility registrations. This parameter controls how often such updating occurs.

penalty_increase

Amount \(p_i \ge 1\) by which the current penalties are increased when insufficient feasible solutions (see target_feasible) have been found amongst the most recent registrations. The penalty values \(v\) are updated as \(v \gets p_i v\).

penalty_decrease

Amount \(p_d \in [0, 1]\) by which the current penalties are decreased when sufficient feasible solutions (see target_feasible) have been found amongst the most recent registrations. The penalty values \(v\) are updated as \(v \gets p_d v\).

target_feasible

Target percentage \(p_f \in [0, 1]\) of feasible registrations in the last num_registrations_between_penalty_updates registrations. This percentage is used to update the penalty terms: when insufficient feasible solutions have been registered, the penalties are increased; similarly, when too many feasible solutions have been registered, the penalty terms are decreased. This ensures a balanced population, with a fraction \(p_f\) feasible and a fraction \(1 - p_f\) infeasible solutions.

Attributes:
init_capacity_penalty

Initial penalty on excess capacity.

init_time_warp_penalty

Initial penalty on time warp.

repair_booster

A repair booster value.

num_registrations_between_penalty_updates

Number of feasibility registrations between penalty value updates.

penalty_increase

Amount \(p_i \ge 1\) by which the current penalties are increased when insufficient feasible solutions (see target_feasible) have been found amongst the most recent registrations.

penalty_decrease

Amount \(p_d \in [0, 1]\) by which the current penalties are decreased when sufficient feasible solutions (see target_feasible) have been found amongst the most recent registrations.

target_feasible

Target percentage \(p_f \in [0, 1]\) of feasible registrations in the last num_registrations_between_penalty_updates registrations.

class PenaltyManager(params: PenaltyParams = PenaltyParams(init_capacity_penalty=20, init_time_warp_penalty=6, repair_booster=12, num_registrations_between_penalty_updates=50, penalty_increase=1.34, penalty_decrease=0.32, target_feasible=0.43))

Creates a PenaltyManager instance.

This class manages time warp and load penalties, and provides penalty terms for given time warp and load values. It updates these penalties based on recent history, and can be used to provide a temporary penalty booster object that increases the penalties for a short duration.

Parameters:
params, optional

PenaltyManager parameters. If not provided, a default will be used.

Methods

get_booster_cost_evaluator()

Get a cost evaluator for the boosted current penalty values.

get_cost_evaluator()

Get a cost evaluator for the current penalty values.

register_load_feasible(is_load_feasible)

Registers another capacity feasibility result.

register_time_feasible(is_time_feasible)

Registers another time feasibility result.

register_load_feasible(is_load_feasible: bool)

Registers another capacity feasibility result. The current load penalty is updated once sufficiently many results have been gathered.

Parameters:
is_load_feasible

Boolean indicating whether the last solution was feasible w.r.t. the capacity constraint.

register_time_feasible(is_time_feasible: bool)

Registers another time feasibility result. The current time warp penalty is updated once sufficiently many results have been gathered.

Parameters:
is_time_feasible

Boolean indicating whether the last solution was feasible w.r.t. the time constraint.

get_cost_evaluator() CostEvaluator

Get a cost evaluator for the current penalty values.

Returns:
CostEvaluator

A CostEvaluator instance that uses the current penalty values.

get_booster_cost_evaluator()

Get a cost evaluator for the boosted current penalty values.

Returns:
CostEvaluator

A CostEvaluator instance that uses the booster penalty values.

class PopulationParams
Attributes:
generation_size
lb_diversity
max_pop_size
min_pop_size
nb_close
nb_elite
ub_diversity
class Population(diversity_op: Callable[[Solution, Solution], float], params: PopulationParams = <pyvrp._pyvrp.PopulationParams object>)

Creates a Population instance.

Parameters:
diversity_op

Operator to use to determine pairwise diversity between solutions. Have a look at pyvrp.diversity for available operators.

params, optional

Population parameters. If not provided, a default will be used.

Methods

add(solution, cost_evaluator)

Adds the given solution to the population.

clear()

Clears the population by removing all solutions currently in the population.

get_tournament(rng, cost_evaluator[, k])

Selects a solution from this population by k-ary tournament, based on the (internal) fitness values of the selected solutions.

num_feasible()

Returns the number of feasible solutions in the population.

num_infeasible()

Returns the number of infeasible solutions in the population.

select(rng, cost_evaluator[, k])

Selects two (if possible non-identical) parents by tournament, subject to a diversity restriction.

__iter__() Generator[Solution, None, None]

Iterates over the solutions contained in this population.

Yields:
iterable

An iterable object of solutions.

__len__() int

Returns the current population size.

Returns:
int

Population size.

num_feasible() int

Returns the number of feasible solutions in the population.

Returns:
int

Number of feasible solutions.

num_infeasible() int

Returns the number of infeasible solutions in the population.

Returns:
int

Number of infeasible solutions.

add(solution: Solution, cost_evaluator: CostEvaluator)

Adds the given solution to the population. Survivor selection is automatically triggered when the population reaches its maximum size.

Parameters:
solution

Solution to add to the population.

cost_evaluator

CostEvaluator to use to compute the cost.

clear()

Clears the population by removing all solutions currently in the population.

select(rng: RandomNumberGenerator, cost_evaluator: CostEvaluator, k: int = 2) tuple[Solution, Solution]

Selects two (if possible non-identical) parents by tournament, subject to a diversity restriction.

Parameters:
rng

Random number generator.

cost_evaluator

Cost evaluator to use when computing the fitness.

k

The number of solutions to draw for the tournament. Defaults to two, which results in a binary tournament.

Returns:
tuple

A solution pair (parents).

get_tournament(rng: RandomNumberGenerator, cost_evaluator: CostEvaluator, k: int = 2) Solution

Selects a solution from this population by k-ary tournament, based on the (internal) fitness values of the selected solutions.

Parameters:
rng

Random number generator.

cost_evaluator

Cost evaluator to use when computing the fitness.

k

The number of solutions to draw for the tournament. Defaults to two, which results in a binary tournament.

Returns:
Solution

The selected solution.

read(where: str | ~pathlib.Path, instance_format: str = 'vrplib', round_func: str | ~typing.Callable[[~numpy.ndarray], ~numpy.ndarray] = <function no_rounding>) ProblemData

Reads the VRPLIB file at the given location, and returns a ProblemData instance.

Parameters:
where

File location to read. Assumes the data on the given location is in VRPLIB format.

instance_format, optional

File format of the instance to read, one of 'vrplib' (default) or 'solomon'.

round_func, optional

Optional rounding function. Will be applied to round data if the data is not already integer. This can either be a function or a string:

  • 'round' rounds the values to the nearest integer;

  • 'trunc' truncates the values to be integral;

  • 'trunc1' or 'dimacs' scale and truncate to the nearest decimal;

  • 'none' does no rounding. This is the default.

Returns:
ProblemData

Data instance constructed from the read data.

Raises:
TypeError

When round_func does not name a rounding function, or is not callable.

ValueError

When the data file does not provide information on the problem size.

read_solution(where: str | Path) list[list[int]]

Reads a solution in VRPLIB format from file at the given location, and returns the routes contained in it.

Parameters:
where

File location to read. Assumes the solution in the file on the given location is in VRPLIB solution format.

Returns:
list

List of routes, where each route is a list of client numbers.

class Result(best: Solution, stats: Statistics, num_iterations: int, runtime: float)

Stores the outcomes of a single run. An instance of this class is returned once the GeneticAlgorithm completes.

Parameters:
best

The best observed solution.

stats

A Statistics object containing runtime statistics.

num_iterations

Number of iterations performed by the genetic algorithm.

runtime

Total runtime of the main genetic algorithm loop.

Raises:
ValueError

When the number of iterations or runtime are negative.

Methods

cost()

Returns the cost (objective) value of the best solution.

is_feasible()

Returns whether the best solution is feasible.

cost() float

Returns the cost (objective) value of the best solution. Returns inf if the best solution is infeasible.

Returns:
float

Objective value.

is_feasible() bool

Returns whether the best solution is feasible.

Returns:
bool

True when the solution is feasible, False otherwise.

show_versions()

This function prints version information that is useful when filing bug reports.

Examples

Calling this function should print information like the following (dependency versions in your local installation will likely differ):

>>> import pyvrp
>>> pyvrp.show_versions()
INSTALLED VERSIONS
------------------
     pyvrp: 1.0.0
     numpy: 1.24.2
matplotlib: 3.7.0
    vrplib: 1.0.1
      tqdm: 4.64.1
     tomli: 2.0.1
    Python: 3.9.13
class Statistics(runtimes: ~typing.List[float] = <factory>, num_iterations: int = 0, feas_stats: ~typing.List[~pyvrp.Statistics._Datum] = <factory>, infeas_stats: ~typing.List[~pyvrp.Statistics._Datum] = <factory>)

The Statistics object tracks various (population-level) statistics of genetic algorithm runs. This can be helpful in analysing the algorithm’s performance.

Methods

collect_from(population, cost_evaluator)

Collects statistics from the given population object.

from_csv(where[, delimiter])

Reads a Statistics object from the CSV file at the given filesystem location.

to_csv(where[, delimiter, quoting])

Writes this Statistics object to the given location, as a CSV file.

collect_from(population: Population, cost_evaluator: CostEvaluator)

Collects statistics from the given population object.

Parameters:
population

Population instance to collect statistics from.

cost_evaluator

CostEvaluator used to compute costs for solutions.

classmethod from_csv(where: Path | str, delimiter: str = ',', **kwargs)

Reads a Statistics object from the CSV file at the given filesystem location.

Parameters:
where

Filesystem location to read from.

delimiter

Value separator. Default comma.

kwargs

Additional keyword arguments. These are passed to csv.DictReader.

Returns:
Statistics

Statistics object populated with the data read from the given filesystem location.

to_csv(where: Path | str, delimiter: str = ',', quoting: int = 0, **kwargs)

Writes this Statistics object to the given location, as a CSV file.

Parameters:
where

Filesystem location to write to.

delimiter

Value separator. Default comma.

quoting

Quoting strategy. Default only quotes values when necessary.

kwargs

Additional keyword arguments. These are passed to csv.DictWriter.

class CostEvaluator(capacity_penalty: int, tw_penalty: int)

Creates a CostEvaluator instance.

This class contains time warp and load penalties, and can compute penalties for a given time warp and load.

Parameters:
capacity_penalty

The penalty for each unit of excess load over the vehicle capacity.

tw_penalty

The penalty for each unit of time warp.

Methods

cost(self, solution)

Evaluates and returns the cost/objective of the given solution.

load_penalty(self, load, capacity)

Computes the total excess capacity penalty for the given load.

penalised_cost(self, solution)

Computes a smoothed objective (penalised cost) for a given solution.

tw_penalty(self, time_warp)

Computes the time warp penalty for the given time warp.

cost(self, solution: pyvrp._pyvrp.Solution) int

Evaluates and returns the cost/objective of the given solution. Hand-waving some details, let \(x_{ij} \in \{ 0, 1 \}\) indicate if edge \((i, j)\) is used in the solution encoded by the given solution, and \(y_i \in \{ 0, 1 \}\) indicate if client \(i\) is visited. The objective is then given by

\[\sum_{(i, j)} d_{ij} x_{ij} + \sum_{i} p_i (1 - y_i),\]

where the first part lists the distance costs, and the second part the prizes of the unvisited clients.

load_penalty(self, load: int, capacity: int) int

Computes the total excess capacity penalty for the given load.

penalised_cost(self, solution: pyvrp._pyvrp.Solution) int

Computes a smoothed objective (penalised cost) for a given solution.

tw_penalty(self, time_warp: int) int

Computes the time warp penalty for the given time warp.

class Route(data: ProblemData, visits: list[int], vehicle_type: int)

A simple class that stores the route plan and some statistics.

Methods

centroid(self)

Center point of the client locations on this route.

demand(self)

Total client demand on this route.

distance(self)

Total distance travelled on this route.

duration(self)

Total route duration, including travel, service and waiting time.

end_time(self)

End time of the route.

excess_load(self)

Demand in excess of the vehicle's capacity.

has_excess_load(self)

has_time_warp(self)

is_feasible(self)

prizes(self)

Total prize value collected on this route.

release_time(self)

Earliest time at which this route can leave the depot.

service_duration(self)

Total duration of service on this route.

slack(self)

Time by which departure from the depot can be delayed without resulting in (additional) time warp or increased route duration.

start_time(self)

Start time of this route.

time_warp(self)

Amount of time warp incurred on this route.

travel_duration(self)

Total duration of travel on this route.

vehicle_type(self)

Index of the type of vehicle used on this route.

visits(self)

Route visits, as a list of clients.

wait_duration(self)

Total waiting duration on this route.

centroid(self) tuple[float, float]

Center point of the client locations on this route.

demand(self) int

Total client demand on this route.

distance(self) int

Total distance travelled on this route.

duration(self) int

Total route duration, including travel, service and waiting time.

end_time(self) int

End time of the route. This is equivalent to start_time + duration - time_warp.

excess_load(self) int

Demand in excess of the vehicle’s capacity.

has_excess_load(self) bool
has_time_warp(self) bool
is_feasible(self) bool
prizes(self) int

Total prize value collected on this route.

release_time(self) int

Earliest time at which this route can leave the depot. Follows from the release times of clients visited on this route.

Note

The route’s release time should not be later than its start time, unless the route has time warp.

service_duration(self) int

Total duration of service on this route.

slack(self) int

Time by which departure from the depot can be delayed without resulting in (additional) time warp or increased route duration.

start_time(self) int

Start time of this route. This is the earliest possible time at which the route can leave the depot and have a minimal duration and time warp. If there is positive slack(), the start time can be delayed by at most slack() time units without increasing the total (minimal) route duration, or time warp.

Note

It may be possible to leave before the start time (if the depot time window allows for it). That will introduce additional waiting time, such that the route duration will then no longer be minimal. Delaying departure by more than slack() time units always increases time warp, which could turn the route infeasible.

time_warp(self) int

Amount of time warp incurred on this route.

travel_duration(self) int

Total duration of travel on this route.

vehicle_type(self) int

Index of the type of vehicle used on this route.

visits(self) list[int]

Route visits, as a list of clients.

wait_duration(self) int

Total waiting duration on this route.

class Solution(data: ProblemData, routes: list[Route] | list[list[int]])

Encodes VRP solutions.

Parameters:
data

Data instance.

routes

Route list to use. Can be a list of Route objects, or a lists of client visits. In case of the latter, all routes are assigned vehicles of the first type. That need not be a feasible assignment!

Raises:
RuntimeError

When the given solution is invalid in one of several ways. In particular when the number of routes in the routes argument exceeds num_vehicles, when an empty route has been passed as part of routes, when too many vehicles of a particular type have been used, or when a client is visited more than once.

Methods

distance(self)

Returns the total distance over all routes.

excess_load(self)

Returns the total excess load over all routes.

get_neighbours(self)

Returns a list of neighbours for each client, by index.

get_routes(self)

The solution's routing decisions.

has_excess_load(self)

Returns whether this solution violates capacity constraints.

has_time_warp(self)

Returns whether this solution violates time window constraints.

is_complete(self)

Returns whether this solution is complete, which it is when it has all required clients.

is_feasible(self)

Whether this solution is feasible.

make_random

make_random(

num_clients(self)

Number of clients in this solution.

num_routes(self)

Number of routes in this solution.

prizes(self)

Returns the total collected prize value over all routes.

time_warp(self)

Returns the total time warp load over all routes.

uncollected_prizes(self)

Total prize value of all clients not visited in this solution.

distance(self) int

Returns the total distance over all routes.

Returns:
int

Total distance over all routes.

excess_load(self) int

Returns the total excess load over all routes.

Returns:
int

Total excess load over all routes.

get_neighbours(self) list[tuple[int, int]]

Returns a list of neighbours for each client, by index. Also includes the depot at index 0, which only neighbours itself.

Returns:
list

A list of (pred, succ) tuples that encode for each client their predecessor and successors in this solutions’s routes.

get_routes(self) list[pyvrp._pyvrp.Route]

The solution’s routing decisions.

Returns:
list

A list of routes. Each Route starts and ends at the depot (0), but that is implicit: the depot is not part of the returned routes.

has_excess_load(self) bool

Returns whether this solution violates capacity constraints.

Returns:
bool

True if the solution is not capacity feasible, False otherwise.

has_time_warp(self) bool

Returns whether this solution violates time window constraints.

Returns:
bool

True if the solution is not time window feasible, False otherwise.

is_complete(self) bool

Returns whether this solution is complete, which it is when it has all required clients.

Returns:
bool

True if the solution visits all required clients, False otherwise.

is_feasible(self) bool

Whether this solution is feasible. This is a shorthand for checking has_excess_load(), has_time_warp(), and is_complete().

Returns:
bool

Whether the solution of this solution is feasible with respect to capacity and time window constraints, and has all required clients.

make_random()
make_random(

data: ProblemData, rng: RandomNumberGenerator,

) -> Solution

Creates a randomly generated solution.

Parameters:
data

Data instance.

rng

Random number generator to use.

Returns:
Solution

The randomly generated solution.

num_clients(self) int

Number of clients in this solution.

Returns:
int

Number of clients in this solution.

num_routes(self) int

Number of routes in this solution.

Returns:
int

Number of routes.

prizes(self) int

Returns the total collected prize value over all routes.

Returns:
int

Value of collected prizes.

time_warp(self) int

Returns the total time warp load over all routes.

Returns:
int

Total time warp over all routes.

uncollected_prizes(self) int

Total prize value of all clients not visited in this solution.

Returns:
int

Value of uncollected prizes.

class Client(x: int, y: int, demand: int = 0, service_duration: int = 0, tw_early: int = 0, tw_late: int = 0, release_time: int = 0, prize: int = 0, required: bool = True)

Simple data object storing all client data as (read-only) properties.

Parameters:
x

Horizontal coordinate of this client, that is, the ‘x’ part of the client’s (x, y) location tuple.

y

Vertical coordinate of this client, that is, the ‘y’ part of the client’s (x, y) location tuple.

demand

The amount this client’s demanding. Default 0.

service_duration

This client’s service duration, that is, the amount of time we need to visit the client for. Service should start (but not necessarily end) within the [tw_early, tw_late] interval. Default 0.

tw_early

Earliest time at which we can visit this client. Default 0.

tw_late

Latest time at which we can visit this client. Default 0.

release_time

Earliest time at which this client is released, that is, the earliest time at which a vehicle may leave the depot to visit this client. Default 0.

prize

Prize collected by visiting this client. Default 0.

required

Whether this client must be part of a feasible solution. Default True.

Attributes:
demand
prize
release_time
required
service_duration
tw_early
tw_late
x
y
class VehicleType(capacity: int, num_available: int)

Simple data object storing all vehicle type data as properties.

Attributes:
capacity

Capacity (maximum total demand) of this vehicle type.

num_available

Number of vehicles of this type that are available.

depot

Depot associated with these vehicles.

class ProblemData(clients: list[Client], vehicle_types: list[VehicleType], distance_matrix: list[list[int]], duration_matrix: list[list[int]])

Creates a problem data instance. This instance contains all information needed to solve the vehicle routing problem.

Parameters:
clients

List of clients. The first client (at index 0) is assumed to be the depot. The time window for the depot is assumed to describe the overall time horizon. The depot should have 0 demand and 0 service duration.

vehicle_types

List of vehicle types in the problem instance.

distance_matrix

A matrix that gives the distances between clients (and the depot at index 0).

duration_matrix

A matrix that gives the travel times between clients (and the depot at index 0).

Attributes:
num_clients

Number of clients in this problem instance.

num_vehicle_types

Number of vehicles in this problem instance.

num_vehicles

Number of vehicle types in this problem instance.

Methods

centroid(self)

Center point of all client locations (excluding the depot).

client(self, client)

Returns client data for the given client.

dist(self, first, second)

Returns the travel distance between the first and second argument, according to this instance's travel distance matrix.

duration(self, first, second)

Returns the travel duration between the first and second argument, according to this instance's travel duration matrix.

vehicle_type(self, vehicle_type)

Returns vehicle type data for the given vehicle type.

centroid(self) tuple[float, float]

Center point of all client locations (excluding the depot).

Returns:
tuple

Centroid of all client locations.

client(self, client: int) pyvrp._pyvrp.Client

Returns client data for the given client.

Parameters:
client

Client number whose information to retrieve.

Returns:
Client

A simple data object containing the requested client’s information.

dist(self, first: int, second: int) int

Returns the travel distance between the first and second argument, according to this instance’s travel distance matrix.

Parameters:
first

Client or depot number.

second

Client or depot number.

Returns:
int

Travel distance between the given clients.

duration(self, first: int, second: int) int

Returns the travel duration between the first and second argument, according to this instance’s travel duration matrix.

Parameters:
first

Client or depot number.

second

Client or depot number.

Returns:
int

Travel duration between the given clients.

property num_clients : int

Number of clients in this problem instance.

Returns:
int

Number of clients in the instance.

property num_vehicle_types : int

Number of vehicles in this problem instance.

Returns:
int

Number of vehicles in this problem instance.

property num_vehicles : int

Number of vehicle types in this problem instance.

Returns:
int

Number of vehicle types in this problem instance.

vehicle_type(self, vehicle_type: int) pyvrp._pyvrp.VehicleType

Returns vehicle type data for the given vehicle type.

Parameters:
vehicle_type

Vehicle type number whose information to retrieve.

Returns:
VehicleType

A simple data object containing the vehicle type information.

class RandomNumberGenerator(seed: int)

This class implements a XOR-shift pseudo-random number generator (RNG). It generates the next number of a sequence by repeatedly taking the ‘exclusive or’ (the ^ operator) of a number with a bit-shifted version of itself. See here for more details.

Parameters:
seed

Seed used to set the initial RNG state.

Methods

__call__(self)

max()

min()

rand(self)

randint(self, high)

__call__(self) int
max() int
min() int
rand(self) float
randint(self, high: int) int
exception EmptySolutionWarning

Raised when an empty solution is being added to the Population. This is not forbidden, per se, but very odd.

exception ScalingWarning

Raised when the distance or duration values in the problem are very large, which could cause the algorithm to start using forbidden edges as well.