ExVrp.Native (ExVrp v0.4.2)

Copy Markdown View Source

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 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 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.

Merges two LoadSegments.

Returns pickup amount.

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.

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.

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

create_cost_evaluator(opts)

@spec create_cost_evaluator(keyword()) :: {:ok, reference()} | {:error, term()}

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)

create_duration_segment_nif(duration, time_warp, start_early, start_late, release_time, cum_duration, cum_time_warp, prev_end_late)

@spec create_duration_segment_nif(
  integer(),
  integer(),
  integer(),
  integer(),
  integer(),
  integer(),
  integer(),
  integer()
) :: reference()

Creates a DurationSegment from raw parameters.

create_dynamic_bitset_nif(num_bits)

@spec create_dynamic_bitset_nif(non_neg_integer()) :: reference()

Creates a DynamicBitset with the given number of bits.

create_exchange10_nif(problem_data)

Creates an Exchange10 (relocate) operator.

create_exchange11_nif(problem_data)

Creates an Exchange11 (swap) operator.

create_exchange20_nif(problem_data)

Creates an Exchange20 operator.

create_exchange21_nif(problem_data)

Creates an Exchange21 operator.

create_exchange22_nif(problem_data)

Creates an Exchange22 operator.

create_exchange30_nif(problem_data)

Creates an Exchange30 operator.

create_exchange31_nif(problem_data)

Creates an Exchange31 operator.

create_exchange32_nif(problem_data)

Creates an Exchange32 operator.

create_exchange33_nif(problem_data)

Creates an Exchange33 operator.

create_load_segment_nif(delivery, pickup, load, excess_load)

@spec create_load_segment_nif(integer(), integer(), integer(), integer()) ::
  reference()

Creates a new LoadSegment from raw parameters.

create_local_search(problem_data, seed)

@spec create_local_search(reference(), integer()) :: reference()

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 data
  • seed - Random seed for the RNG

Returns

Reference to the LocalSearch resource.

create_perturbation_manager_nif(min, max)

@spec create_perturbation_manager_nif(integer(), integer()) :: reference()

Creates a PerturbationManager with given min/max perturbations.

create_problem_data(model)

@spec create_problem_data(ExVrp.Model.t()) :: {:ok, reference()} | {:error, term()}

Creates a ProblemData resource from a Model.

create_random_solution(problem_data, opts)

@spec create_random_solution(
  reference(),
  keyword()
) :: {:ok, reference()} | {:error, term()}

Creates a random solution for the given problem data.

create_relocate_with_depot_nif(problem_data)

Creates a RelocateWithDepot operator.

create_rng_from_seed_nif(seed)

@spec create_rng_from_seed_nif(non_neg_integer()) :: reference()

Creates an RNG from a seed.

create_rng_from_state_nif(state)

@spec create_rng_from_state_nif([non_neg_integer()]) ::
  {:ok, reference()} | {:error, term()}

Creates an RNG from a 4-element state list.

create_search_node_nif(problem_data, loc)

Creates a new search node.

create_search_route_nif(problem_data, idx, vehicle_type)

Creates a new search route.

create_solution_from_routes(problem_data, routes)

@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).

create_swap_routes_nif(problem_data)

Creates a SwapRoutes operator.

create_swap_star_nif(problem_data, overlap_tolerance)

Creates a SwapStar operator with overlap_tolerance (0.0 to 1.0, use 1.0 to check all route pairs).

create_swap_tails_nif(problem_data)

Creates a SwapTails operator.

duration_segment_duration_nif(seg)

@spec duration_segment_duration_nif(reference()) :: integer()

Gets the duration of a segment.

duration_segment_end_early_nif(seg)

@spec duration_segment_end_early_nif(reference()) :: integer()

Gets the end_early of a segment.

duration_segment_end_late_nif(seg)

@spec duration_segment_end_late_nif(reference()) :: integer()

Gets the end_late of a segment.

duration_segment_finalise_back_nif(seg)

@spec duration_segment_finalise_back_nif(reference()) :: reference()

Finalises a segment at the back.

duration_segment_finalise_front_nif(seg)

@spec duration_segment_finalise_front_nif(reference()) :: reference()

Finalises a segment at the front.

duration_segment_merge_nif(edge_duration, first, second)

@spec duration_segment_merge_nif(integer(), reference(), reference()) :: reference()

Merges two segments with an edge duration.

duration_segment_prev_end_late_nif(seg)

@spec duration_segment_prev_end_late_nif(reference()) :: integer()

Gets the prev_end_late of a segment.

duration_segment_release_time_nif(seg)

@spec duration_segment_release_time_nif(reference()) :: integer()

Gets the release_time of a segment.

duration_segment_slack_nif(seg)

@spec duration_segment_slack_nif(reference()) :: integer()

Gets the slack of a segment.

duration_segment_start_early_nif(seg)

@spec duration_segment_start_early_nif(reference()) :: integer()

Gets the start_early of a segment.

duration_segment_start_late_nif(seg)

@spec duration_segment_start_late_nif(reference()) :: integer()

Gets the start_late of a segment.

duration_segment_time_warp_nif(seg, max_duration)

@spec duration_segment_time_warp_nif(reference(), integer()) :: integer()

Gets the time warp of a segment, optionally with max_duration constraint.

dynamic_bitset_all_nif(bitset)

@spec dynamic_bitset_all_nif(reference()) :: boolean()

Returns true if all bits are set.

dynamic_bitset_and_nif(a, b)

@spec dynamic_bitset_and_nif(reference(), reference()) :: reference()

Bitwise AND of two bitsets. Returns a new bitset.

dynamic_bitset_any_nif(bitset)

@spec dynamic_bitset_any_nif(reference()) :: boolean()

Returns true if any bit is set.

dynamic_bitset_count_nif(bitset)

@spec dynamic_bitset_count_nif(reference()) :: non_neg_integer()

Returns the number of set bits.

dynamic_bitset_eq_nif(a, b)

@spec dynamic_bitset_eq_nif(reference(), reference()) :: boolean()

Checks if two bitsets are equal.

dynamic_bitset_get_nif(bitset, idx)

@spec dynamic_bitset_get_nif(reference(), non_neg_integer()) :: boolean()

Gets the bit at the given index.

dynamic_bitset_len_nif(bitset)

@spec dynamic_bitset_len_nif(reference()) :: non_neg_integer()

Returns the size (length) of the bitset.

dynamic_bitset_none_nif(bitset)

@spec dynamic_bitset_none_nif(reference()) :: boolean()

Returns true if no bits are set.

dynamic_bitset_not_nif(bitset)

@spec dynamic_bitset_not_nif(reference()) :: reference()

Bitwise NOT of a bitset. Returns a new bitset.

dynamic_bitset_or_nif(a, b)

@spec dynamic_bitset_or_nif(reference(), reference()) :: reference()

Bitwise OR of two bitsets. Returns a new bitset.

dynamic_bitset_reset_all_nif(bitset)

@spec dynamic_bitset_reset_all_nif(reference()) :: reference()

Resets all bits to 0. Returns a new bitset.

dynamic_bitset_set_all_nif(bitset)

@spec dynamic_bitset_set_all_nif(reference()) :: reference()

Sets all bits to 1. Returns a new bitset.

dynamic_bitset_set_bit_nif(bitset, idx, value)

@spec dynamic_bitset_set_bit_nif(reference(), non_neg_integer(), boolean()) ::
  reference()

Sets the bit at the given index. Returns a new bitset.

dynamic_bitset_xor_nif(a, b)

@spec dynamic_bitset_xor_nif(reference(), reference()) :: reference()

Bitwise XOR of two bitsets. Returns a new bitset.

exchange10_apply_nif(op, u, v)

Applies Exchange10 move.

exchange10_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange10 move cost.

exchange11_apply_nif(op, u, v)

Applies Exchange11 move.

exchange11_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange11 move cost.

exchange20_apply_nif(op, u, v)

Applies Exchange20 move.

exchange20_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange20 move cost.

exchange21_apply_nif(op, u, v)

Applies Exchange21 move.

exchange21_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange21 move cost.

exchange22_apply_nif(op, u, v)

Applies Exchange22 move.

exchange22_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange22 move cost.

exchange30_apply_nif(op, u, v)

Applies Exchange30 move.

exchange30_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange30 move cost.

exchange31_apply_nif(op, u, v)

Applies Exchange31 move.

exchange31_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange31 move cost.

exchange32_apply_nif(op, u, v)

Applies Exchange32 move.

exchange32_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange32 move cost.

exchange33_apply_nif(op, u, v)

Applies Exchange33 move.

exchange33_evaluate_nif(op, u, v, evaluator)

Evaluates Exchange33 move cost.

inplace_cost_nif(u_node, v_node, problem_data, cost_evaluator)

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.

insert_cost_nif(u_node, v_node, problem_data, cost_evaluator)

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).

load_segment_delivery_nif(seg)

@spec load_segment_delivery_nif(reference()) :: integer()

Returns delivery amount.

load_segment_excess_load_nif(seg, capacity)

@spec load_segment_excess_load_nif(reference(), integer()) :: integer()

Returns excess load with capacity constraint.

load_segment_finalise_nif(seg, capacity)

@spec load_segment_finalise_nif(reference(), integer()) :: reference()

Finalises a LoadSegment with capacity.

load_segment_load_nif(seg)

@spec load_segment_load_nif(reference()) :: integer()

Returns load.

load_segment_merge_nif(first, second)

@spec load_segment_merge_nif(reference(), reference()) :: reference()

Merges two LoadSegments.

load_segment_pickup_nif(seg)

@spec load_segment_pickup_nif(reference()) :: integer()

Returns pickup amount.

local_search(solution, problem_data, cost_evaluator, opts \\ [])

@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)

local_search_run(local_search, solution, cost_evaluator, timeout_ms \\ 0)

@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 from create_local_search/2
  • solution - Reference to the current solution
  • cost_evaluator - Reference to the cost evaluator

Returns

{:ok, improved_solution} or {:error, reason}

local_search_search_only(solution, problem_data, cost_evaluator, opts \\ [])

@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)

local_search_search_run(local_search, solution, cost_evaluator, timeout_ms \\ 0)

@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 from create_local_search/2
  • solution - Reference to the current solution
  • cost_evaluator - Reference to the cost evaluator

Returns

{:ok, improved_solution} or {:error, reason}

local_search_stats(solution, problem_data, cost_evaluator, opts \\ [])

@spec local_search_stats(reference(), reference(), reference(), keyword()) :: map()

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.

local_search_with_operators(solution, problem_data, cost_evaluator, opts \\ [])

@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)

make_search_route_nif(problem_data, visits, idx, vehicle_type)

Creates a search route from a list of visits.

perturbation_manager_max_perturbations_nif(pm)

@spec perturbation_manager_max_perturbations_nif(reference()) :: integer()

Returns the max_perturbations parameter.

perturbation_manager_min_perturbations_nif(pm)

@spec perturbation_manager_min_perturbations_nif(reference()) :: integer()

Returns the min_perturbations parameter.

perturbation_manager_num_perturbations_nif(pm)

@spec perturbation_manager_num_perturbations_nif(reference()) :: integer()

Returns the current number of perturbations to apply.

perturbation_manager_shuffle_nif(pm, rng)

@spec perturbation_manager_shuffle_nif(reference(), reference()) :: reference()

Shuffles to pick a new random number of perturbations.

problem_data_centroid_nif(problem_data)

@spec problem_data_centroid_nif(reference()) :: {float(), float()}

Gets the centroid (average x, y) of all client locations.

problem_data_clients_nif(problem_data)

@spec problem_data_clients_nif(reference()) :: [
  {integer(), integer(), integer(), integer()}
]

Gets all client data for neighbourhood computation. Returns list of {tw_early, tw_late, service_duration, prize} tuples.

problem_data_distance_matrix_nif(problem_data, profile)

@spec problem_data_distance_matrix_nif(reference(), integer()) :: [[integer()]]

Gets the distance matrix for a specific profile. Returns a nested list of integers.

problem_data_duration_matrix_nif(problem_data, profile)

@spec problem_data_duration_matrix_nif(reference(), integer()) :: [[integer()]]

Gets the duration matrix for a specific profile. Returns a nested list of integers.

problem_data_groups_nif(problem_data)

@spec problem_data_groups_nif(reference()) :: [{[integer()], boolean()}]

Gets client groups for neighbourhood computation. Returns list of {[client_location_indices], mutually_exclusive} tuples.

problem_data_has_time_windows_nif(problem_data)

@spec problem_data_has_time_windows_nif(reference()) :: boolean()

Checks if the problem data has time windows (any non-default TW on clients/depots).

problem_data_num_clients(problem_data)

@spec problem_data_num_clients(reference()) :: non_neg_integer()

Gets the number of clients from ProblemData.

problem_data_num_depots(problem_data)

@spec problem_data_num_depots(reference()) :: non_neg_integer()

Gets the number of depots from ProblemData.

problem_data_num_load_dims(problem_data)

@spec problem_data_num_load_dims(reference()) :: non_neg_integer()

Gets the number of load dimensions from ProblemData.

problem_data_num_locations(problem_data)

@spec problem_data_num_locations(reference()) :: non_neg_integer()

Gets the total number of locations (depots + clients) from ProblemData.

problem_data_num_profiles_nif(problem_data)

@spec problem_data_num_profiles_nif(reference()) :: non_neg_integer()

Gets the number of profiles (distance/duration matrix sets).

problem_data_num_vehicle_types(problem_data)

@spec problem_data_num_vehicle_types(reference()) :: non_neg_integer()

Gets the number of vehicle types from ProblemData.

problem_data_num_vehicles(problem_data)

@spec problem_data_num_vehicles(reference()) :: non_neg_integer()

Gets the total number of vehicles (sum of all vehicle types) from ProblemData.

problem_data_vehicle_types_nif(problem_data)

@spec problem_data_vehicle_types_nif(reference()) :: [
  {integer(), integer(), integer()}
]

Gets vehicle type cost info for neighbourhood computation. Returns list of {unit_distance_cost, unit_duration_cost, profile} tuples.

relocate_with_depot_apply_nif(op, u, v)

Applies RelocateWithDepot move.

relocate_with_depot_evaluate_nif(op, u, v, evaluator)

Evaluates RelocateWithDepot move cost.

relocate_with_depot_supports_nif(problem_data)

@spec relocate_with_depot_supports_nif(reference()) :: boolean()

Checks if RelocateWithDepot is supported for the given problem data.

remove_cost_nif(u_node, problem_data, cost_evaluator)

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).

rng_call_nif(rng)

@spec rng_call_nif(reference()) :: {reference(), non_neg_integer()}

Generates the next random integer. Returns {new_rng, value}.

rng_max_nif()

@spec rng_max_nif() :: non_neg_integer()

Returns the maximum value the RNG can produce (2^32-1).

rng_min_nif()

@spec rng_min_nif() :: non_neg_integer()

Returns the minimum value the RNG can produce (0).

rng_rand_nif(rng)

@spec rng_rand_nif(reference()) :: {reference(), float()}

Generates a random float in [0, 1]. Returns {new_rng, value}.

rng_randint_nif(rng, high)

@spec rng_randint_nif(reference(), non_neg_integer()) ::
  {reference(), non_neg_integer()}

Generates a random integer in [0, high). Returns {new_rng, value}.

rng_state_nif(rng)

@spec rng_state_nif(reference()) :: [non_neg_integer()]

Gets the current RNG state as a 4-element list.

search_node_client_nif(node)

Gets the node's location (client index).

search_node_has_route_nif(node)

Checks if the node has a route assigned.

search_node_idx_nif(node)

Gets the node's index in the route.

search_node_is_depot_nif(node)

Checks if the node is a depot.

search_node_is_end_depot_nif(node)

Checks if the node is an end depot.

search_node_is_reload_depot_nif(node)

Checks if the node is a reload depot.

search_node_is_start_depot_nif(node)

Checks if the node is a start depot.

search_node_trip_nif(node)

Gets the node's trip index.

search_route_append_nif(route, node)

Appends a node to the route.

search_route_capacity_nif(route)

Gets the route capacity (as list).

search_route_centroid_nif(route)

Gets the route centroid.

search_route_clear_nif(route)

Clears the route.

search_route_dist_after_nif(route, idx)

Gets distance after index.

search_route_dist_at_nif(route, idx, profile)

Gets distance at specific index. Profile -1 uses route's default.

search_route_dist_before_nif(route, idx)

Gets distance before index.

search_route_dist_between_nif(route, start, end, profile)

Gets distance between two indices. Profile -1 uses route's default.

search_route_distance_cost_nif(route)

Gets the distance cost.

search_route_distance_nif(route)

Gets the route distance.

search_route_duration_cost_nif(route)

Gets the duration cost.

search_route_duration_nif(route)

Gets the route duration.

search_route_empty_nif(route)

Checks if the route is empty.

search_route_end_depot_nif(route)

Gets the route end depot.

search_route_excess_distance_nif(route)

Gets the route excess distance.

search_route_excess_load_nif(route)

Gets the route excess load (as list).

search_route_fixed_vehicle_cost_nif(route)

Gets the fixed vehicle cost.

search_route_get_node_nif(route, idx)

Gets a node at the given index.

search_route_has_distance_cost_nif(route)

Checks if the route has distance cost.

search_route_has_duration_cost_nif(route)

Checks if the route has duration cost.

search_route_has_excess_distance_nif(route)

Checks if the route has excess distance.

search_route_has_excess_load_nif(route)

Checks if the route has excess load.

search_route_has_time_warp_nif(route)

Checks if the route has time warp.

search_route_idx_nif(route)

Gets the route index.

search_route_insert_nif(route, idx, node)

Inserts a node at the given index.

search_route_is_feasible_nif(route)

Checks if the route is feasible.

search_route_load_nif(route)

Gets the route load (as list).

search_route_max_duration_nif(route)

Gets the route's max duration (shift_duration + max_overtime).

search_route_max_overtime_nif(route)

Gets the route's max overtime.

search_route_max_trips_nif(route)

Gets the max trips allowed for the route.

search_route_num_clients_nif(route)

Gets the number of clients in the route.

search_route_num_depots_nif(route)

Gets the number of depots in the route.

search_route_num_trips_nif(route)

Gets the number of trips in the route.

search_route_overlaps_with_nif(route1, route2, tolerance)

Checks if two routes overlap with the given tolerance (0.0 to 1.0).

search_route_overtime_nif(route)

Gets the route overtime.

search_route_profile_nif(route)

Gets the route profile.

search_route_remove_nif(route, idx)

Removes the node at the given index.

search_route_shift_duration_nif(route)

Gets the route's shift duration.

search_route_size_nif(route)

Gets the route size (total nodes including depots).

search_route_start_depot_nif(route)

Gets the route start depot.

search_route_swap_nif(node1, node2)

Swaps two nodes.

search_route_time_warp_nif(route)

Gets the route time warp.

search_route_unit_distance_cost_nif(route)

Gets the unit distance cost.

search_route_unit_duration_cost_nif(route)

Gets the unit duration cost.

search_route_unit_overtime_cost_nif(route)

Gets the route's unit overtime cost.

search_route_update_nif(route)

Updates the route (recomputes statistics).

search_route_vehicle_type_nif(route)

Gets the route vehicle type.

solution_cost(solution, cost_evaluator)

@spec solution_cost(reference(), reference()) :: non_neg_integer() | :infinity

Computes the cost of a feasible solution. Returns max integer for infeasible.

solution_distance(solution)

@spec solution_distance(reference()) :: non_neg_integer()

solution_duration(solution)

@spec solution_duration(reference()) :: non_neg_integer()

solution_fixed_vehicle_cost(solution)

@spec solution_fixed_vehicle_cost(reference()) :: non_neg_integer()

Returns the total fixed vehicle cost of the solution.

solution_is_complete(solution_ref)

@spec solution_is_complete(reference()) :: boolean()

solution_is_feasible(solution_ref)

@spec solution_is_feasible(reference()) :: boolean()

solution_is_group_feasible(solution_ref)

@spec solution_is_group_feasible(reference()) :: boolean()

solution_num_clients(solution_ref)

@spec solution_num_clients(reference()) :: non_neg_integer()

solution_num_routes(solution_ref)

@spec solution_num_routes(reference()) :: non_neg_integer()

solution_penalised_cost(solution, cost_evaluator)

@spec solution_penalised_cost(reference(), reference()) :: non_neg_integer()

Computes the penalised cost of a solution (feasible or infeasible).

solution_route_centroid(solution, route_idx)

@spec solution_route_centroid(reference(), non_neg_integer()) :: {float(), float()}

Gets the centroid of a specific route as {x, y}.

solution_route_delivery(solution, route_idx)

@spec solution_route_delivery(reference(), non_neg_integer()) :: [non_neg_integer()]

Gets the delivery load of a specific route in a solution.

solution_route_distance(solution, route_idx)

@spec solution_route_distance(reference(), non_neg_integer()) :: non_neg_integer()

Gets the distance of a specific route in a solution.

solution_route_distance_cost(solution, route_idx)

@spec solution_route_distance_cost(reference(), non_neg_integer()) ::
  non_neg_integer()

Gets the distance cost of a specific route.

solution_route_duration(solution, route_idx)

@spec solution_route_duration(reference(), non_neg_integer()) :: non_neg_integer()

Gets the duration of a specific route in a solution.

solution_route_duration_cost(solution, route_idx)

@spec solution_route_duration_cost(reference(), non_neg_integer()) ::
  non_neg_integer()

Gets the duration cost of a specific route.

solution_route_end_depot(solution, route_idx)

@spec solution_route_end_depot(reference(), non_neg_integer()) :: non_neg_integer()

Gets the end depot of a specific route.

solution_route_end_time(solution, route_idx)

@spec solution_route_end_time(reference(), non_neg_integer()) :: non_neg_integer()

Gets the end time of a specific route.

solution_route_excess_distance(solution, route_idx)

@spec solution_route_excess_distance(reference(), non_neg_integer()) ::
  non_neg_integer()

Gets excess distance of a specific route.

solution_route_excess_load(solution, route_idx)

@spec solution_route_excess_load(reference(), non_neg_integer()) :: [
  non_neg_integer()
]

Gets excess load of a specific route (per dimension).

solution_route_has_excess_distance(solution, route_idx)

@spec solution_route_has_excess_distance(reference(), non_neg_integer()) :: boolean()

Checks if a specific route has excess distance.

solution_route_has_excess_load(solution, route_idx)

@spec solution_route_has_excess_load(reference(), non_neg_integer()) :: boolean()

Checks if a specific route has excess load.

solution_route_has_time_warp(solution, route_idx)

@spec solution_route_has_time_warp(reference(), non_neg_integer()) :: boolean()

Checks if a specific route has time warp.

solution_route_is_feasible(solution, route_idx)

@spec solution_route_is_feasible(reference(), non_neg_integer()) :: boolean()

Checks if a specific route in a solution is feasible.

solution_route_num_trips(solution, route_idx)

@spec solution_route_num_trips(reference(), non_neg_integer()) :: non_neg_integer()

Gets the number of trips in a specific route.

solution_route_overtime(solution, route_idx)

@spec solution_route_overtime(reference(), non_neg_integer()) :: non_neg_integer()

Gets overtime of a specific route.

solution_route_pickup(solution, route_idx)

@spec solution_route_pickup(reference(), non_neg_integer()) :: [non_neg_integer()]

Gets the pickup load of a specific route in a solution.

solution_route_prizes(solution, route_idx)

@spec solution_route_prizes(reference(), non_neg_integer()) :: non_neg_integer()

Gets the prizes collected on a specific route.

solution_route_reload_cost(solution, route_idx)

@spec solution_route_reload_cost(reference(), non_neg_integer()) :: non_neg_integer()

Gets the reload cost of a specific route.

solution_route_schedule(solution, route_idx)

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}

solution_route_service_duration(solution, route_idx)

@spec solution_route_service_duration(reference(), non_neg_integer()) ::
  non_neg_integer()

Gets the service duration of a specific route.

solution_route_slack(solution, route_idx)

@spec solution_route_slack(reference(), non_neg_integer()) :: non_neg_integer()

Gets the slack time of a specific route.

solution_route_start_depot(solution, route_idx)

@spec solution_route_start_depot(reference(), non_neg_integer()) :: non_neg_integer()

Gets the start depot of a specific route.

solution_route_start_time(solution, route_idx)

@spec solution_route_start_time(reference(), non_neg_integer()) :: non_neg_integer()

Gets the start time of a specific route.

solution_route_time_warp(solution, route_idx)

@spec solution_route_time_warp(reference(), non_neg_integer()) :: non_neg_integer()

Gets time warp of a specific route.

solution_route_travel_duration(solution, route_idx)

@spec solution_route_travel_duration(reference(), non_neg_integer()) ::
  non_neg_integer()

Gets the travel duration of a specific route.

solution_route_vehicle_type(solution, route_idx)

@spec solution_route_vehicle_type(reference(), non_neg_integer()) :: non_neg_integer()

Gets the vehicle type of a specific route.

solution_route_visits(solution, route_idx)

@spec solution_route_visits(reference(), non_neg_integer()) :: [non_neg_integer()]

Gets the visits (client indices) of a specific route.

solution_route_wait_duration(solution, route_idx)

@spec solution_route_wait_duration(reference(), non_neg_integer()) ::
  non_neg_integer()

Gets the wait duration of a specific route.

solution_routes(solution_ref)

@spec solution_routes(reference()) :: [[non_neg_integer()]]

solution_unassigned(solution)

@spec solution_unassigned(reference()) :: [non_neg_integer()]

swap_routes_apply_nif(op, route1, route2)

Applies SwapRoutes move between two routes.

swap_routes_evaluate_nif(op, route1, route2, evaluator)

Evaluates SwapRoutes move cost between two routes.

swap_star_apply_nif(op, route1, route2)

Applies SwapStar move between two routes.

swap_star_evaluate_nif(op, route1, route2, evaluator)

Evaluates SwapStar move cost between two routes.

swap_tails_apply_nif(op, u, v)

Applies SwapTails move.

swap_tails_evaluate_nif(op, u, v, evaluator)

Evaluates SwapTails move cost.