| Title: | Vehicle Routing Problem Solver Built on 'PyVRP' |
| Version: | 0.2.0 |
| Description: | A 'tidyverse'-style interface to high-performance vehicle routing problem (VRP) solving. Vendors the C++ core of the 'PyVRP' solver (https://github.com/PyVRP/PyVRP) and rewires it through 'cpp11', with no 'Python' runtime dependency. Supports the capacitated VRP, time windows, multiple depots, heterogeneous fleets, prize-collecting and multi-trip variants, driven by an iterated local search metaheuristic. |
| License: | MIT + file LICENSE |
| URL: | https://github.com/StrategicProjects/vrpr, https://strategicprojects.github.io/vrpr/ |
| BugReports: | https://github.com/StrategicProjects/vrpr/issues |
| Encoding: | UTF-8 |
| Depends: | R (≥ 4.3) |
| Imports: | cli, rlang, stats, tibble, vctrs |
| LinkingTo: | cpp11 |
| Suggests: | ggplot2, knitr, reticulate, rmarkdown, testthat (≥ 3.0.0), withr |
| VignetteBuilder: | knitr |
| Config/testthat/edition: | 3 |
| SystemRequirements: | C++20, GNU make |
| Config/roxygen2/version: | 8.0.0 |
| NeedsCompilation: | yes |
| Packaged: | 2026-09-28 19:33:30 UTC; leite |
| Author: | Andre Leite [aut, cre], Marcos Wasilew [aut], Hugo Vasconcelos [aut], Carlos Amorim [aut], Diogo Bezerra [aut], Niels Wouda [ctb, cph] (author of the vendored PyVRP C++ core), Thibaut Vidal [cph] (HGS-CVRP, parts of the vendored C++ core), ORTEC [cph] (HGS-DIMACS, parts of the vendored C++ core) |
| Maintainer: | Andre Leite <leite@castlab.org> |
| Repository: | CRAN |
| Date/Publication: | 2026-09-28 20:10:02 UTC |
vrpr: Vehicle Routing Problem Solver Built on 'PyVRP'
Description
A 'tidyverse'-style interface to high-performance vehicle routing problem (VRP) solving. Vendors the C++ core of the 'PyVRP' solver (https://github.com/PyVRP/PyVRP) and rewires it through 'cpp11', with no 'Python' runtime dependency. Supports the capacitated VRP, time windows, multiple depots, heterogeneous fleets, prize-collecting and multi-trip variants, driven by an iterated local search metaheuristic.
Author(s)
Maintainer: Andre Leite leite@castlab.org
Authors:
Andre Leite leite@castlab.org
Marcos Wasilew marcos.wasilew@gmail.com
Hugo Vasconcelos hugo.vasconcelos@ufpe.br
Carlos Amorim carlos.agaf@ufpe.br
Diogo Bezerra diogo.bezerra@ufpe.br
Other contributors:
Niels Wouda (author of the vendored PyVRP C++ core) [contributor, copyright holder]
Thibaut Vidal (HGS-CVRP, parts of the vendored C++ core) [copyright holder]
ORTEC (HGS-DIMACS, parts of the vendored C++ core) [copyright holder]
See Also
Useful links:
Report bugs at https://github.com/StrategicProjects/vrpr/issues
Add a mutually exclusive group of clients
Description
Defines a group from which at most one client is visited (or exactly one if
required = TRUE). Useful for prize-collecting with exclusive alternatives
(e.g. serving one of several equivalent points). Clients in the group
automatically become optional (individual required = FALSE); use prize to
encourage a visit.
Usage
add_client_group(model, clients, required = FALSE)
Arguments
model |
A |
clients |
Vector of client numbers (1-based, in the order of
|
required |
If |
Value
The updated vrpr_model.
Add clients to the model
Description
Add clients to the model
Usage
add_clients(model, data)
Arguments
model |
A |
data |
A tibble/data.frame with at least the columns |
Value
The updated vrpr_model.
Add a depot to the model
Description
Add a depot to the model
Usage
add_depot(model, x, y, tw_early = 0, tw_late = Inf, service = 0)
Arguments
model |
A |
x, y |
Depot coordinates. |
tw_early, tw_late |
Depot time window (opening/closing). |
service |
Service time at the depot (e.g. loading), per trip. |
Value
The updated vrpr_model.
Add shipments (pickup and delivery pairs) to the model
Description
A shipment is a paired pickup and delivery: the same vehicle must pick up the goods at the pickup point and drop them off at the delivery point, with the pickup happening first, in the same trip. This models the classic pickup-and-delivery problem (PDPTW when combined with time windows).
Usage
add_shipments(model, data)
Arguments
model |
A |
data |
A tibble/data.frame with at least the columns |
Value
The updated vrpr_model.
Add a vehicle type to the model
Description
Add a vehicle type to the model
Usage
add_vehicle_type(
model,
num_available,
capacity,
fixed_cost = 0,
tw_early = 0,
tw_late = Inf,
max_duration = Inf,
unit_distance_cost = 1,
unit_duration_cost = 0,
depot = 1L,
start_depot = depot,
end_depot = depot,
reload_depots = integer(0),
max_reloads = Inf
)
Arguments
model |
A |
num_available |
Number of vehicles available of this type. |
capacity |
Vehicle capacity. |
fixed_cost |
Fixed cost per vehicle used. |
tw_early, tw_late |
Vehicle shift time window (start/end). |
max_duration |
Maximum route duration. |
unit_distance_cost, unit_duration_cost |
Variable cost per unit of
distance and of duration for this type. Varying these (and |
depot |
Index (1-based) of the depot vehicles of this type start from and
return to. Shortcut to set |
start_depot, end_depot |
Indices (1-based) of the start and end depots, in
the order of |
reload_depots |
Indices (1-based) of depots where vehicles of this type may reload/empty mid-route, enabling multi-trip routes. Empty (default) = no reloading. |
max_reloads |
Maximum number of reloads per route. |
Details
Call add_vehicle_type() several times for a fleet with multiple
vehicle types (different capacities, costs, shifts or depots).
Value
The updated vrpr_model.
Cost of a result or solution
Description
Cost of a result or solution
Usage
cost(x, ...)
Arguments
x |
A |
... |
Unused. |
Value
The objective cost (a numeric scalar); Inf if no feasible solution
was found.
ILS solver parameters
Description
ILS solver parameters
Usage
ils_params(
num_neighbours = 50L,
min_perturbations = 1L,
max_perturbations = 25L,
history_length = 300L,
num_iters_no_improvement = 150000L,
exhaustive_on_best = TRUE
)
Arguments
num_neighbours |
Granular neighbourhood size (activities per neighbourhood). Default 50, as in PyVRP. |
min_perturbations, max_perturbations |
Range of perturbations per iteration. |
history_length |
Length of the late-acceptance history (> 0). Default 300, as in PyVRP. |
num_iters_no_improvement |
Iterations without improvement before restarting from the best. |
exhaustive_on_best |
Refine each new best with an exhaustive search? |
Value
A list of parameters.
Plot a VRP model (depots and clients only)
Description
Plot a VRP model (depots and clients only)
Usage
## S3 method for class 'vrpr_model'
plot(x, ...)
Arguments
x |
A |
... |
Unused. |
Value
A ggplot object.
Plot the solution of a VRP result
Description
Draws depots, clients and the routes (one colour per route) over the instance coordinates. Unvisited optional clients (prize-collecting) appear as hollow circles.
Usage
## S3 method for class 'vrpr_result'
plot(x, show_clients = TRUE, ...)
Arguments
x |
A |
show_clients |
Reserved; clients are always drawn. |
... |
Unused. |
Value
A ggplot object.
Read a VRPTW instance in Solomon format
Description
Reads VRPTW instances in Solomon (and Gehring-Homberger) format, with the
VEHICLE section (number and capacity) and the CUSTOMER table (coordinates,
demand, time window and service time). Customer 0 is the depot.
Usage
read_solomon(path, num_vehicles = NULL)
Arguments
path |
Path to the file. |
num_vehicles |
Number of vehicles; if |
Value
A vrp_model() ready for vrp_solve().
Read an instance in VRPLIB / TSPLIB format
Description
Reads CVRP (and VRPTW) instances in VRPLIB/CVRPLIB format (extended TSPLIB),
such as the X set by Uchoa et al. Supports Euclidean coordinates
(EDGE_WEIGHT_TYPE : EUC_2D); time-window and service-time sections are read
when present.
Usage
read_vrplib(path, num_vehicles = NULL)
Arguments
path |
Path to the |
num_vehicles |
Number of available vehicles. If |
Value
A vrp_model() ready for vrp_solve().
Routes of a solution, in long (tidy) format
Description
Routes of a solution, in long (tidy) format
Usage
routes(x, ...)
Arguments
x |
|
... |
Unused. |
Value
A tibble with one row per client, pickup or delivery visit:
route_id, depot (start depot, 1-based), position, activity
("client", "pickup" or "delivery"), client (client number, NA
for shipment visits), shipment (shipment number, NA for client
visits), trip, vehicle_type, start_service (start of service) and
wait (waiting time). The last two are only meaningful with time windows
(VRPTW); depot varies in the MDVRP; trip in multi-trip routes.
Cost of a solution
Description
Cost of a solution
Usage
solution_cost(solution, cost_evaluator = NULL)
Arguments
solution |
|
cost_evaluator |
A |
Value
The penalised cost (a numeric scalar). For feasible solutions this
is the objective cost; the feasible attribute reports feasibility.
One-row summary of a result (tibble)
Description
One-row summary of a result (tibble)
Usage
## S3 method for class 'vrpr_result'
summary(object, ...)
Arguments
object |
A |
... |
Unused. |
Value
A one-row tibble with cost, feasibility, number of routes, iterations and runtime.
Unplanned activities of a solution
Description
Optional clients and shipments that are not part of any route (prize-collecting problems).
Usage
unplanned(x, ...)
Arguments
x |
A |
... |
Unused. |
Value
A tibble with columns activity ("client" or "pickup"/
"delivery") and index (1-based client or shipment number).
Unvisited optional clients
Description
In prize-collecting problems, clients with required = FALSE may be left out
if the prize does not offset the routing cost.
Usage
unvisited_clients(x, ...)
Arguments
x |
A |
... |
Unused. |
Value
An integer vector of the (1-based) client numbers not visited.
Cost evaluator (CostEvaluator)
Description
Creates a penalised-cost evaluator. Penalties multiply constraint violations (load, time window, maximum distance) to form the smoothed cost the solver minimises. For a feasible solution, the penalised cost equals the objective cost.
Usage
vrp_cost_evaluator(load_penalties = 1, tw_penalty = 1, dist_penalty = 1)
Arguments
load_penalties |
Penalty per unit of excess load, per load dimension. A scalar is recycled across all dimensions. |
tw_penalty |
Penalty per unit of time warp (time-window violation). |
dist_penalty |
Penalty per unit of distance above the maximum. |
Value
A vrpr_cost_evaluator object.
Build a vehicle routing (VRP) model
Description
vrp_model() creates an empty model to which depots, clients and vehicle
types are added via the pipe (|>). It is the tidy equivalent of PyVRP's
Model class – the data boundary uses tibbles, not one object at a time.
Usage
vrp_model()
Value
A vrpr_model object.
Examples
clients <- tibble::tibble(
x = c(10, 25, 40), y = c(5, 30, 12),
demand = c(10, 15, 8)
)
m <- vrp_model() |>
add_depot(x = 0, y = 0) |>
add_clients(clients) |>
add_vehicle_type(num_available = 5, capacity = 100)
m
Assemble the problem data (ProblemData) from a model
Description
Builds PyVRP's C++ ProblemData structure from a vrp_model(). Locations
follow vrpr's convention: depots first (low indices), then clients, then one
pickup and one delivery location per shipment.
Usage
vrp_problem_data(model, distance = NULL, duration = NULL)
Arguments
model |
A |
distance, duration |
Matrices ( |
Details
Integer measures (distance, duration, cost, load) travel as R numeric with
integer semantics; non-integer values are rejected at the C++ boundary. Use
Inf for "unconstrained" limits (e.g. tw_late).
Value
A vrpr_problem_data object (a wrapper around a C++ external pointer).
Generate a random solution
Description
Generate a random solution
Usage
vrp_random_solution(problem_data, seed = 42L)
Arguments
problem_data |
|
seed |
Integer seed. |
Value
A vrpr_solution object.
Build a solution from explicit routes
Description
Build a solution from explicit routes
Usage
vrp_solution(problem_data, routes)
Arguments
problem_data |
|
routes |
A list of integer vectors; each vector is a route given as client numbers (1..n_clients), in visit order. All routes use the first vehicle type. |
Value
A vrpr_solution object.
Solve a VRP model
Description
Runs the iterated local search (ILS) solver on a model, using PyVRP's vendored C++ core.
Usage
vrp_solve(model, stop, seed = 42L, params = ils_params(), display = TRUE)
Arguments
model |
A |
stop |
A stopping criterion (see vrpr_stop), e.g. |
seed |
Integer seed for reproducibility. |
params |
Solver parameters (see |
display |
Show progress via |
Value
A vrpr_result object with the best solution, cost, routes and run
statistics. Use cost(), routes() and summary() to inspect it.
Examples
clients <- tibble::tibble(
x = c(10, 25, 40, 15), y = c(5, 30, 12, 22),
demand = c(10, 15, 8, 12)
)
res <- vrp_model() |>
add_depot(x = 0, y = 0) |>
add_clients(clients) |>
add_vehicle_type(num_available = 3, capacity = 50) |>
vrp_solve(stop = max_iterations(200), display = FALSE)
cost(res)
routes(res)
Solver stopping criteria
Description
Control when the iterated local search loop should terminate. Each function
returns a callable object (closure) that the solver invokes every iteration,
receiving the cost of the current best solution and returning TRUE to stop.
Usage
max_runtime(seconds)
max_iterations(max_iters)
no_improvement(n)
first_feasible()
Arguments
seconds |
Maximum run time, in seconds. |
max_iters |
Maximum number of iterations. |
n |
Number of consecutive iterations without improvement before stopping. |
Details
These are the R equivalent of PyVRP's pyvrp.stop module.
Value
An object of class vrpr_stop: a function
function(best_cost, feasible) returning TRUE/FALSE.