Low-level NIF bindings to PyVRP C++ core.
This module provides direct bindings to the C++ implementation.
Users should prefer the high-level API in ExVrp and ExVrp.Model.
Summary
Functions
Creates a CostEvaluator with penalty parameters.
Creates a DurationSegment from raw parameters.
Creates a DynamicBitset with the given number of bits.
Creates an Exchange10 (relocate) operator.
Creates an Exchange11 (swap) operator.
Creates an Exchange20 operator.
Creates an Exchange21 operator.
Creates an Exchange22 operator.
Creates an Exchange30 operator.
Creates an Exchange31 operator.
Creates an Exchange32 operator.
Creates an Exchange33 operator.
Creates a new LoadSegment from raw parameters.
Creates a persistent LocalSearch resource.
Creates a PerturbationManager with given min/max perturbations.
Creates a ProblemData resource from a Model.
Creates a random solution for the given problem data.
Creates a RelocateWithDepot operator.
Creates an RNG from a seed.
Creates an RNG from a 4-element state list.
Creates a new search node.
Creates a new search route.
Creates a solution from explicit routes.
Creates a SwapRoutes operator.
Creates a SwapStar operator with overlap_tolerance (0.0 to 1.0, use 1.0 to check all route pairs).
Creates a SwapTails operator.
Gets the duration of a segment.
Gets the end_early of a segment.
Gets the end_late of a segment.
Finalises a segment at the back.
Finalises a segment at the front.
Merges two segments with an edge duration.
Gets the prev_end_late of a segment.
Gets the release_time of a segment.
Gets the slack of a segment.
Gets the start_early of a segment.
Gets the start_late of a segment.
Gets the time warp of a segment, optionally with max_duration constraint.
Returns true if all bits are set.
Bitwise AND of two bitsets. Returns a new bitset.
Returns true if any bit is set.
Returns the number of set bits.
Checks if two bitsets are equal.
Gets the bit at the given index.
Returns the size (length) of the bitset.
Returns true if no bits are set.
Bitwise NOT of a bitset. Returns a new bitset.
Bitwise OR of two bitsets. Returns a new bitset.
Resets all bits to 0. Returns a new bitset.
Sets all bits to 1. Returns a new bitset.
Sets the bit at the given index. Returns a new bitset.
Bitwise XOR of two bitsets. Returns a new bitset.
Applies Exchange10 move.
Evaluates Exchange10 move cost.
Applies Exchange11 move.
Evaluates Exchange11 move cost.
Applies Exchange20 move.
Evaluates Exchange20 move cost.
Applies Exchange21 move.
Evaluates Exchange21 move cost.
Applies Exchange22 move.
Evaluates Exchange22 move cost.
Applies Exchange30 move.
Evaluates Exchange30 move cost.
Applies Exchange31 move.
Evaluates Exchange31 move cost.
Applies Exchange32 move.
Evaluates Exchange32 move cost.
Applies Exchange33 move.
Evaluates Exchange33 move cost.
Computes the delta cost of inserting node U in place of node V.
Computes the delta cost of inserting node U after node V in V's route.
Returns delivery amount.
Returns excess load with capacity constraint.
Finalises a LoadSegment with capacity.
Returns load.
Merges two LoadSegments.
Returns pickup amount.
Performs local search on a solution.
Runs local search using a persistent LocalSearch resource.
Performs search-only local search (no perturbation).
Runs search-only (no perturbation) using a persistent LocalSearch resource.
Performs local search and returns operator statistics.
Performs local search with specific operators.
Creates a search route from a list of visits.
Returns the max_perturbations parameter.
Returns the min_perturbations parameter.
Returns the current number of perturbations to apply.
Shuffles to pick a new random number of perturbations.
Gets the centroid (average x, y) of all client locations.
Gets all client data for neighbourhood computation. Returns list of {tw_early, tw_late, service_duration, prize} tuples.
Gets the distance matrix for a specific profile. Returns a nested list of integers.
Gets the duration matrix for a specific profile. Returns a nested list of integers.
Gets client groups for neighbourhood computation. Returns list of {[client_location_indices], mutually_exclusive} tuples.
Checks if the problem data has time windows (any non-default TW on clients/depots).
Gets the number of clients from ProblemData.
Gets the number of depots from ProblemData.
Gets the number of load dimensions from ProblemData.
Gets the total number of locations (depots + clients) from ProblemData.
Gets the number of profiles (distance/duration matrix sets).
Gets the number of vehicle types from ProblemData.
Gets the total number of vehicles (sum of all vehicle types) from ProblemData.
Gets vehicle type cost info for neighbourhood computation. Returns list of {unit_distance_cost, unit_duration_cost, profile} tuples.
Applies RelocateWithDepot move.
Evaluates RelocateWithDepot move cost.
Checks if RelocateWithDepot is supported for the given problem data.
Computes the delta cost of removing node U from its route.
Generates the next random integer. Returns {new_rng, value}.
Returns the maximum value the RNG can produce (2^32-1).
Returns the minimum value the RNG can produce (0).
Generates a random float in [0, 1]. Returns {new_rng, value}.
Generates a random integer in [0, high). Returns {new_rng, value}.
Gets the current RNG state as a 4-element list.
Gets the node's location (client index).
Checks if the node has a route assigned.
Gets the node's index in the route.
Checks if the node is a depot.
Checks if the node is an end depot.
Checks if the node is a reload depot.
Checks if the node is a start depot.
Gets the node's trip index.
Appends a node to the route.
Gets the route capacity (as list).
Gets the route centroid.
Clears the route.
Gets distance after index.
Gets distance at specific index. Profile -1 uses route's default.
Gets distance before index.
Gets distance between two indices. Profile -1 uses route's default.
Gets the distance cost.
Gets the route distance.
Gets the duration cost.
Gets the route duration.
Checks if the route is empty.
Gets the route end depot.
Gets the route excess distance.
Gets the route excess load (as list).
Gets the fixed vehicle cost.
Gets a node at the given index.
Checks if the route has distance cost.
Checks if the route has duration cost.
Checks if the route has excess distance.
Checks if the route has excess load.
Checks if the route has time warp.
Gets the route index.
Inserts a node at the given index.
Checks if the route is feasible.
Gets the route load (as list).
Gets the route's max duration (shift_duration + max_overtime).
Gets the route's max overtime.
Gets the max trips allowed for the route.
Gets the number of clients in the route.
Gets the number of depots in the route.
Gets the number of trips in the route.
Checks if two routes overlap with the given tolerance (0.0 to 1.0).
Gets the route overtime.
Gets the route profile.
Removes the node at the given index.
Gets the route's shift duration.
Gets the route size (total nodes including depots).
Gets the route start depot.
Swaps two nodes.
Gets the route time warp.
Gets the unit distance cost.
Gets the unit duration cost.
Gets the route's unit overtime cost.
Updates the route (recomputes statistics).
Gets the route vehicle type.
Computes the cost of a feasible solution. Returns max integer for infeasible.
Returns the total fixed vehicle cost of the solution.
Computes the penalised cost of a solution (feasible or infeasible).
Gets the centroid of a specific route as {x, y}.
Gets the delivery load of a specific route in a solution.
Gets the distance of a specific route in a solution.
Gets the distance cost of a specific route.
Gets the duration of a specific route in a solution.
Gets the duration cost of a specific route.
Gets the end depot of a specific route.
Gets the end time of a specific route.
Gets excess distance of a specific route.
Gets excess load of a specific route (per dimension).
Checks if a specific route has excess distance.
Checks if a specific route has excess load.
Checks if a specific route has time warp.
Checks if a specific route in a solution is feasible.
Gets the number of trips in a specific route.
Gets overtime of a specific route.
Gets the pickup load of a specific route in a solution.
Gets the prizes collected on a specific route.
Gets the reload cost of a specific route.
Returns the schedule of a route as a list of ScheduledVisit tuples.
Gets the service duration of a specific route.
Gets the slack time of a specific route.
Gets the start depot of a specific route.
Gets the start time of a specific route.
Gets time warp of a specific route.
Gets the travel duration of a specific route.
Gets the vehicle type of a specific route.
Gets the visits (client indices) of a specific route.
Gets the wait duration of a specific route.
Applies SwapRoutes move between two routes.
Evaluates SwapRoutes move cost between two routes.
Applies SwapStar move between two routes.
Evaluates SwapStar move cost between two routes.
Applies SwapTails move.
Evaluates SwapTails move cost.
Functions
Creates a CostEvaluator with penalty parameters.
Options
:load_penalties- List of penalties for each load dimension (required):tw_penalty- Time window violation penalty (required):dist_penalty- Distance constraint violation penalty (required)
@spec create_duration_segment_nif( integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer() ) :: reference()
Creates a DurationSegment from raw parameters.
@spec create_dynamic_bitset_nif(non_neg_integer()) :: reference()
Creates a DynamicBitset with the given number of bits.
Creates an Exchange10 (relocate) operator.
Creates an Exchange11 (swap) operator.
Creates an Exchange20 operator.
Creates an Exchange21 operator.
Creates an Exchange22 operator.
Creates an Exchange30 operator.
Creates an Exchange31 operator.
Creates an Exchange32 operator.
Creates an Exchange33 operator.
Creates a new LoadSegment from raw parameters.
Creates a persistent LocalSearch resource.
This pre-computes neighbours (O(n²)) and creates all operators once. The resource can be reused across iterations for significant speedup.
The seed initializes the RNG which is stored and reused across all calls, matching PyVRP's behavior where one RNG is created at algorithm start.
Parameters
problem_data- Reference to the problem dataseed- Random seed for the RNG
Returns
Reference to the LocalSearch resource.
Creates a PerturbationManager with given min/max perturbations.
@spec create_problem_data(ExVrp.Model.t()) :: {:ok, reference()} | {:error, term()}
Creates a ProblemData resource from a Model.
Creates a random solution for the given problem data.
Creates a RelocateWithDepot operator.
@spec create_rng_from_seed_nif(non_neg_integer()) :: reference()
Creates an RNG from a seed.
@spec create_rng_from_state_nif([non_neg_integer()]) :: {:ok, reference()} | {:error, term()}
Creates an RNG from a 4-element state list.
Creates a new search node.
Creates a new search route.
@spec create_solution_from_routes(reference(), [[non_neg_integer()]]) :: {:ok, reference()} | {:error, term()}
Creates a solution from explicit routes.
Routes is a list of lists of client IDs (integers). Client IDs are 1-indexed (depot is 0, clients start at 1).
Creates a SwapRoutes operator.
Creates a SwapStar operator with overlap_tolerance (0.0 to 1.0, use 1.0 to check all route pairs).
Creates a SwapTails operator.
Gets the duration of a segment.
Gets the end_early of a segment.
Gets the end_late of a segment.
Finalises a segment at the back.
Finalises a segment at the front.
Merges two segments with an edge duration.
Gets the prev_end_late of a segment.
Gets the release_time of a segment.
Gets the slack of a segment.
Gets the start_early of a segment.
Gets the start_late of a segment.
Gets the time warp of a segment, optionally with max_duration constraint.
Returns true if all bits are set.
Bitwise AND of two bitsets. Returns a new bitset.
Returns true if any bit is set.
@spec dynamic_bitset_count_nif(reference()) :: non_neg_integer()
Returns the number of set bits.
Checks if two bitsets are equal.
@spec dynamic_bitset_get_nif(reference(), non_neg_integer()) :: boolean()
Gets the bit at the given index.
@spec dynamic_bitset_len_nif(reference()) :: non_neg_integer()
Returns the size (length) of the bitset.
Returns true if no bits are set.
Bitwise NOT of a bitset. Returns a new bitset.
Bitwise OR of two bitsets. Returns a new bitset.
Resets all bits to 0. Returns a new bitset.
Sets all bits to 1. Returns a new bitset.
@spec dynamic_bitset_set_bit_nif(reference(), non_neg_integer(), boolean()) :: reference()
Sets the bit at the given index. Returns a new bitset.
Bitwise XOR of two bitsets. Returns a new bitset.
Applies Exchange10 move.
Evaluates Exchange10 move cost.
Applies Exchange11 move.
Evaluates Exchange11 move cost.
Applies Exchange20 move.
Evaluates Exchange20 move cost.
Applies Exchange21 move.
Evaluates Exchange21 move cost.
Applies Exchange22 move.
Evaluates Exchange22 move cost.
Applies Exchange30 move.
Evaluates Exchange30 move cost.
Applies Exchange31 move.
Evaluates Exchange31 move cost.
Applies Exchange32 move.
Evaluates Exchange32 move cost.
Applies Exchange33 move.
Evaluates Exchange33 move cost.
Computes the delta cost of inserting node U in place of node V.
U must not be in a route, V must be in a route. Returns 0 if the move is not possible.
Computes the delta cost of inserting node U after node V in V's route.
Returns 0 if the move is not possible (e.g., inserting a depot).
Returns delivery amount.
Returns excess load with capacity constraint.
Finalises a LoadSegment with capacity.
Returns load.
Merges two LoadSegments.
Returns pickup amount.
@spec local_search(reference(), reference(), reference(), keyword()) :: {:ok, reference()} | {:error, term()}
Performs local search on a solution.
Options
:exhaustive- Whether to run exhaustive search (default: false)
@spec local_search_run(reference(), reference(), reference(), non_neg_integer()) :: {:ok, reference()} | {:error, term()}
Runs local search using a persistent LocalSearch resource.
This avoids recreating neighbours and operators on each call.
Equivalent to Python's ls(solution, cost_eval) (with perturbation).
Uses the stored RNG which advances across calls (matching PyVRP).
Parameters
local_search- Reference to LocalSearch resource fromcreate_local_search/2solution- Reference to the current solutioncost_evaluator- Reference to the cost evaluator
Returns
{:ok, improved_solution} or {:error, reason}
@spec local_search_search_only(reference(), reference(), reference(), keyword()) :: {:ok, reference()} | {:error, term()}
Performs search-only local search (no perturbation).
This matches PyVRP's ls.search() method which is used for the initial solution.
Unlike local_search/4 (which calls operator() with perturbation), this calls
the search() method directly after shuffling.
Used by Solver.solve/2 to create the initial solution: PyVRP: init = ls.search(Solution(data, []), pm.max_cost_evaluator())
Options
:seed- Random seed for shuffling (default: 42)
@spec local_search_search_run( reference(), reference(), reference(), non_neg_integer() ) :: {:ok, reference()} | {:error, term()}
Runs search-only (no perturbation) using a persistent LocalSearch resource.
Used for initial solution construction.
Equivalent to Python's ls.search(solution, cost_eval).
Uses the stored RNG which advances across calls (matching PyVRP).
Parameters
local_search- Reference to LocalSearch resource fromcreate_local_search/2solution- Reference to the current solutioncost_evaluator- Reference to the cost evaluator
Returns
{:ok, improved_solution} or {:error, reason}
Performs local search and returns operator statistics.
Returns a map with:
:local_search- Map with:num_moves,:num_improving,:num_updates:operators- List of maps with:name,:num_evaluations,:num_applications
Same options as local_search_with_operators/4.
@spec local_search_with_operators(reference(), reference(), reference(), keyword()) :: {:ok, reference()} | {:error, term()}
Performs local search with specific operators.
Options
:node_operators- List of operator names (atoms)::exchange10/:relocate- Relocate a single node:exchange11/:swap11- Swap two nodes:exchange20/:relocate2- Relocate two consecutive nodes:exchange21/:swap21- Exchange 2 nodes for 1:exchange22/:swap22- Exchange 2 nodes for 2:exchange30/:relocate3- Relocate three consecutive nodes:exchange31/:swap31- Exchange 3 nodes for 1:exchange32/:swap32- Exchange 3 nodes for 2:exchange33/:swap33- Exchange 3 nodes for 3:swap_tails- Swap route tails:relocate_with_depot- Relocate with depot reload (multi-trip)
:route_operators- List of route operator names::swap_star- SWAP* operator (Vidal et al.):swap_routes- Swap entire routes
:exhaustive- Whether to run exhaustive search (default: false)
Creates a search route from a list of visits.
Returns the max_perturbations parameter.
Returns the min_perturbations parameter.
Returns the current number of perturbations to apply.
Shuffles to pick a new random number of perturbations.
Gets the centroid (average x, y) of all client locations.
Gets all client data for neighbourhood computation. Returns list of {tw_early, tw_late, service_duration, prize} tuples.
Gets the distance matrix for a specific profile. Returns a nested list of integers.
Gets the duration matrix for a specific profile. Returns a nested list of integers.
Gets client groups for neighbourhood computation. Returns list of {[client_location_indices], mutually_exclusive} tuples.
Checks if the problem data has time windows (any non-default TW on clients/depots).
@spec problem_data_num_clients(reference()) :: non_neg_integer()
Gets the number of clients from ProblemData.
@spec problem_data_num_depots(reference()) :: non_neg_integer()
Gets the number of depots from ProblemData.
@spec problem_data_num_load_dims(reference()) :: non_neg_integer()
Gets the number of load dimensions from ProblemData.
@spec problem_data_num_locations(reference()) :: non_neg_integer()
Gets the total number of locations (depots + clients) from ProblemData.
@spec problem_data_num_profiles_nif(reference()) :: non_neg_integer()
Gets the number of profiles (distance/duration matrix sets).
@spec problem_data_num_vehicle_types(reference()) :: non_neg_integer()
Gets the number of vehicle types from ProblemData.
@spec problem_data_num_vehicles(reference()) :: non_neg_integer()
Gets the total number of vehicles (sum of all vehicle types) from ProblemData.
Gets vehicle type cost info for neighbourhood computation. Returns list of {unit_distance_cost, unit_duration_cost, profile} tuples.
Applies RelocateWithDepot move.
Evaluates RelocateWithDepot move cost.
Checks if RelocateWithDepot is supported for the given problem data.
Computes the delta cost of removing node U from its route.
Returns 0 if the move is not possible (e.g., removing a depot, node not in route).
@spec rng_call_nif(reference()) :: {reference(), non_neg_integer()}
Generates the next random integer. Returns {new_rng, value}.
@spec rng_max_nif() :: non_neg_integer()
Returns the maximum value the RNG can produce (2^32-1).
@spec rng_min_nif() :: non_neg_integer()
Returns the minimum value the RNG can produce (0).
Generates a random float in [0, 1]. Returns {new_rng, value}.
@spec rng_randint_nif(reference(), non_neg_integer()) :: {reference(), non_neg_integer()}
Generates a random integer in [0, high). Returns {new_rng, value}.
@spec rng_state_nif(reference()) :: [non_neg_integer()]
Gets the current RNG state as a 4-element list.
Gets the node's location (client index).
Checks if the node has a route assigned.
Gets the node's index in the route.
Checks if the node is a depot.
Checks if the node is an end depot.
Checks if the node is a reload depot.
Checks if the node is a start depot.
Gets the node's trip index.
Appends a node to the route.
Gets the route capacity (as list).
Gets the route centroid.
Clears the route.
Gets distance after index.
Gets distance at specific index. Profile -1 uses route's default.
Gets distance before index.
Gets distance between two indices. Profile -1 uses route's default.
Gets the distance cost.
Gets the route distance.
Gets the duration cost.
Gets the route duration.
Checks if the route is empty.
Gets the route end depot.
Gets the route excess distance.
Gets the route excess load (as list).
Gets the fixed vehicle cost.
Gets a node at the given index.
Checks if the route has distance cost.
Checks if the route has duration cost.
Checks if the route has excess distance.
Checks if the route has excess load.
Checks if the route has time warp.
Gets the route index.
Inserts a node at the given index.
Checks if the route is feasible.
Gets the route load (as list).
Gets the route's max duration (shift_duration + max_overtime).
Gets the route's max overtime.
Gets the max trips allowed for the route.
Gets the number of clients in the route.
Gets the number of depots in the route.
Gets the number of trips in the route.
Checks if two routes overlap with the given tolerance (0.0 to 1.0).
Gets the route overtime.
Gets the route profile.
Removes the node at the given index.
Gets the route's shift duration.
Gets the route size (total nodes including depots).
Gets the route start depot.
Swaps two nodes.
Gets the route time warp.
Gets the unit distance cost.
Gets the unit duration cost.
Gets the route's unit overtime cost.
Updates the route (recomputes statistics).
Gets the route vehicle type.
@spec solution_cost(reference(), reference()) :: non_neg_integer() | :infinity
Computes the cost of a feasible solution. Returns max integer for infeasible.
@spec solution_distance(reference()) :: non_neg_integer()
@spec solution_duration(reference()) :: non_neg_integer()
@spec solution_fixed_vehicle_cost(reference()) :: non_neg_integer()
Returns the total fixed vehicle cost of the solution.
@spec solution_num_clients(reference()) :: non_neg_integer()
@spec solution_num_routes(reference()) :: non_neg_integer()
@spec solution_penalised_cost(reference(), reference()) :: non_neg_integer()
Computes the penalised cost of a solution (feasible or infeasible).
@spec solution_route_centroid(reference(), non_neg_integer()) :: {float(), float()}
Gets the centroid of a specific route as {x, y}.
@spec solution_route_delivery(reference(), non_neg_integer()) :: [non_neg_integer()]
Gets the delivery load of a specific route in a solution.
@spec solution_route_distance(reference(), non_neg_integer()) :: non_neg_integer()
Gets the distance of a specific route in a solution.
@spec solution_route_distance_cost(reference(), non_neg_integer()) :: non_neg_integer()
Gets the distance cost of a specific route.
@spec solution_route_duration(reference(), non_neg_integer()) :: non_neg_integer()
Gets the duration of a specific route in a solution.
@spec solution_route_duration_cost(reference(), non_neg_integer()) :: non_neg_integer()
Gets the duration cost of a specific route.
@spec solution_route_end_depot(reference(), non_neg_integer()) :: non_neg_integer()
Gets the end depot of a specific route.
@spec solution_route_end_time(reference(), non_neg_integer()) :: non_neg_integer()
Gets the end time of a specific route.
@spec solution_route_excess_distance(reference(), non_neg_integer()) :: non_neg_integer()
Gets excess distance of a specific route.
@spec solution_route_excess_load(reference(), non_neg_integer()) :: [ non_neg_integer() ]
Gets excess load of a specific route (per dimension).
@spec solution_route_has_excess_distance(reference(), non_neg_integer()) :: boolean()
Checks if a specific route has excess distance.
@spec solution_route_has_excess_load(reference(), non_neg_integer()) :: boolean()
Checks if a specific route has excess load.
@spec solution_route_has_time_warp(reference(), non_neg_integer()) :: boolean()
Checks if a specific route has time warp.
@spec solution_route_is_feasible(reference(), non_neg_integer()) :: boolean()
Checks if a specific route in a solution is feasible.
@spec solution_route_num_trips(reference(), non_neg_integer()) :: non_neg_integer()
Gets the number of trips in a specific route.
@spec solution_route_overtime(reference(), non_neg_integer()) :: non_neg_integer()
Gets overtime of a specific route.
@spec solution_route_pickup(reference(), non_neg_integer()) :: [non_neg_integer()]
Gets the pickup load of a specific route in a solution.
@spec solution_route_prizes(reference(), non_neg_integer()) :: non_neg_integer()
Gets the prizes collected on a specific route.
@spec solution_route_reload_cost(reference(), non_neg_integer()) :: non_neg_integer()
Gets the reload cost of a specific route.
@spec solution_route_schedule(reference(), non_neg_integer()) :: [ {non_neg_integer(), non_neg_integer(), non_neg_integer(), non_neg_integer(), non_neg_integer(), non_neg_integer()} ]
Returns the schedule of a route as a list of ScheduledVisit tuples.
Each tuple contains: {location, trip, start_service, end_service, wait_duration, time_warp}
@spec solution_route_service_duration(reference(), non_neg_integer()) :: non_neg_integer()
Gets the service duration of a specific route.
@spec solution_route_slack(reference(), non_neg_integer()) :: non_neg_integer()
Gets the slack time of a specific route.
@spec solution_route_start_depot(reference(), non_neg_integer()) :: non_neg_integer()
Gets the start depot of a specific route.
@spec solution_route_start_time(reference(), non_neg_integer()) :: non_neg_integer()
Gets the start time of a specific route.
@spec solution_route_time_warp(reference(), non_neg_integer()) :: non_neg_integer()
Gets time warp of a specific route.
@spec solution_route_travel_duration(reference(), non_neg_integer()) :: non_neg_integer()
Gets the travel duration of a specific route.
@spec solution_route_vehicle_type(reference(), non_neg_integer()) :: non_neg_integer()
Gets the vehicle type of a specific route.
@spec solution_route_visits(reference(), non_neg_integer()) :: [non_neg_integer()]
Gets the visits (client indices) of a specific route.
@spec solution_route_wait_duration(reference(), non_neg_integer()) :: non_neg_integer()
Gets the wait duration of a specific route.
@spec solution_routes(reference()) :: [[non_neg_integer()]]
@spec solution_unassigned(reference()) :: [non_neg_integer()]
Applies SwapRoutes move between two routes.
Evaluates SwapRoutes move cost between two routes.
Applies SwapStar move between two routes.
Evaluates SwapStar move cost between two routes.
Applies SwapTails move.
Evaluates SwapTails move cost.