# `ExVrp.Route`
[🔗](https://github.com/sephianl/ex_vrp/blob/v0.4.2/lib/ex_vrp/route.ex#L1)

Represents a single route in a VRP solution.

A route is a sequence of client visits performed by one vehicle,
starting and ending at designated depots.

## PyVRP Parity

This module provides the same interface as PyVRP's Route class.
Methods like `distance/1`, `duration/1`, etc. require the route
to have a `solution_ref` and `route_idx` set. Use `Solution.route/2`
or `Solution.routes/1` to get Route structs with proper context.

## Example

    {:ok, result} = Solver.solve(model)
    [route | _] = Solution.routes(result.best)

    # Now you can call route methods
    Route.distance(route)
    Route.feasible?(route)

# `t`

```elixir
@type t() :: %ExVrp.Route{
  end_depot: non_neg_integer(),
  route_idx: non_neg_integer() | nil,
  solution_ref: reference() | nil,
  start_depot: non_neg_integer(),
  trips: [ExVrp.Trip.t()],
  vehicle_type: non_neg_integer(),
  visits: [non_neg_integer()]
}
```

# `centroid`

```elixir
@spec centroid(t()) :: {float(), float()}
```

Returns the centroid of this route as {x, y}.

# `delivery`

```elixir
@spec delivery(t()) :: [non_neg_integer()]
```

Returns the total delivery load of this route per dimension.

# `distance`

```elixir
@spec distance(t()) :: non_neg_integer()
```

Returns the distance of this route.

# `distance_cost`

```elixir
@spec distance_cost(t()) :: non_neg_integer()
```

Returns the distance cost of this route.

# `duration`

```elixir
@spec duration(t()) :: non_neg_integer()
```

Returns the duration of this route.

# `duration_cost`

```elixir
@spec duration_cost(t()) :: non_neg_integer()
```

Returns the duration cost of this route.

# `end_depot`

```elixir
@spec end_depot(t()) :: non_neg_integer()
```

Returns the end depot of this route.

# `end_time`

```elixir
@spec end_time(t()) :: non_neg_integer()
```

Returns the end time of this route.

# `excess_distance`

```elixir
@spec excess_distance(t()) :: non_neg_integer()
```

Returns the excess distance of this route.

# `excess_load`

```elixir
@spec excess_load(t()) :: [non_neg_integer()]
```

Returns the excess load of this route per dimension.

# `feasible?`

```elixir
@spec feasible?(t()) :: boolean()
```

Checks if this route is feasible.

# `has_excess_distance?`

```elixir
@spec has_excess_distance?(t()) :: boolean()
```

Checks if this route has excess distance.

# `has_excess_load?`

```elixir
@spec has_excess_load?(t()) :: boolean()
```

Checks if this route has excess load in any dimension.

# `has_time_warp?`

```elixir
@spec has_time_warp?(t()) :: boolean()
```

Checks if this route has time warp.

# `num_clients`

```elixir
@spec num_clients(t()) :: non_neg_integer()
```

Returns the number of clients visited in this route.

This uses the local `visits` field and doesn't require a solution reference.

# `num_trips`

```elixir
@spec num_trips(t()) :: non_neg_integer()
```

Returns the number of trips in this route.

# `overtime`

```elixir
@spec overtime(t()) :: non_neg_integer()
```

Returns the overtime of this route.

# `pickup`

```elixir
@spec pickup(t()) :: [non_neg_integer()]
```

Returns the total pickup load of this route per dimension.

# `prizes`

```elixir
@spec prizes(t()) :: non_neg_integer()
```

Returns the prizes collected on this route.

# `schedule`

```elixir
@spec schedule(t()) :: [
  {non_neg_integer(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
   non_neg_integer(), non_neg_integer()}
]
```

Returns the schedule of this route as a list of ScheduledVisit tuples.

Each tuple contains: {location, trip, start_service, end_service, wait_duration, time_warp}

# `service_duration`

```elixir
@spec service_duration(t()) :: non_neg_integer()
```

Returns the service duration of this route.

# `slack`

```elixir
@spec slack(t()) :: non_neg_integer()
```

Returns the slack time of this route.

# `start_depot`

```elixir
@spec start_depot(t()) :: non_neg_integer()
```

Returns the start depot of this route.

# `start_time`

```elixir
@spec start_time(t()) :: non_neg_integer()
```

Returns the start time of this route.

# `time_warp`

```elixir
@spec time_warp(t()) :: non_neg_integer()
```

Returns the time warp of this route.

# `travel_duration`

```elixir
@spec travel_duration(t()) :: non_neg_integer()
```

Returns the travel duration of this route.

# `vehicle_type`

```elixir
@spec vehicle_type(t()) :: non_neg_integer()
```

Returns the vehicle type of this route.

# `visits`

```elixir
@spec visits(t()) :: [non_neg_integer()]
```

Returns the visits (client indices) of this route.

# `wait_duration`

```elixir
@spec wait_duration(t()) :: non_neg_integer()
```

Returns the wait duration of this route.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
