pyevrp 0.2.1
A production-quality Python library for Electric Vehicle Routing Problems with battery constraints and charging stations
Requires Python: >=3.10
Keywords: battery, charging-stations, electric-vehicles, evrp, logistics, operations-research, optimization, routing, vehicle-routing, vrp

# pyevrp

A production-quality Python library for Electric Vehicle Routing Problems (EVRP) with battery constraints and charging stations.

[![PyPI version](https://badge.fury.io/py/pyevrp.svg)](https://badge.fury.io/py/pyevrp)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

- **Battery-aware routing**: Native support for battery constraints, energy consumption, and state-of-charge tracking
- **Charging stations**: Integrated charging station visits with configurable charging rates
- **Time windows**: Full support for customer time windows (E-VRPTW)
- **Flexible API**: Fluent interface for easy problem definition
- **Benchmark loaders**: Built-in support for Schneider and Solomon benchmark instances
- **Extensible**: Easy to add custom solvers and constraints

## Installation

```bash
pip install pyevrp
```

For development dependencies:

```bash
pip install pyevrp[dev]
```

## Quick Start

```python
from pyevrp import Model, MaxRuntime

# Create a new EVRP model
model = Model("My EVRP")

# Add depot (vehicles start and end here)
model.add_depot(x=0, y=0, tw_early=0, tw_late=480)

# Add customers with demands and time windows
model.add_client(x=10, y=10, demand=5, service_time=10, tw_early=60, tw_late=120)
model.add_client(x=20, y=15, demand=8, service_time=15, tw_early=100, tw_late=200)
model.add_client(x=15, y=25, demand=3, service_time=10, tw_early=150, tw_late=300)

# Add charging stations
model.add_charging_station(x=12, y=12, charging_rate=2.0)

# Add vehicle type with battery specifications
model.add_vehicle_type(
    capacity=50,              # Cargo capacity
    battery_capacity=80,      # Battery capacity in kWh
    consumption_rate=0.2,     # kWh per unit distance
    num_available=5,          # Number of vehicles
    fixed_cost=100,           # Fixed cost per vehicle
    cost_per_km=1.0           # Variable cost per distance
)

# Solve the problem
result = model.solve(stop=MaxRuntime(60))

# Analyze the solution
data = model.data()
print(f"Total cost: {result.cost(data):.2f}")
print(f"Routes used: {result.num_routes}")
print(f"Charging stops: {result.total_charging_stops}")

# Check feasibility
if result.is_feasible(data):
    print("Solution is feasible!")
else:
    for violation in result.get_violations(data):
        print(f"Violation: {violation}")
```

## Loading Benchmark Instances

```python
from pyevrp import SchneiderLoader, SolomonLoader

# Load Schneider E-VRPTW instance
data = SchneiderLoader.load("path/to/instance.txt")

# Load Solomon VRPTW instance (with battery parameters)
data = SolomonLoader.load(
    "path/to/c101.txt",
    battery_capacity=80.0,
    consumption_rate=0.2
)
```

## Stopping Criteria

```python
from pyevrp import MaxIterations, MaxRuntime, NoImprovement, Combined

# Stop after 1000 iterations
stop = MaxIterations(1000)

# Stop after 60 seconds
stop = MaxRuntime(60)

# Stop after 100 iterations without improvement
stop = NoImprovement(100)

# Combine multiple criteria (stops when ANY is met)
stop = Combined.of(
    MaxIterations(10000),
    MaxRuntime(300),
    NoImprovement(500)
)
```

## Solution Analysis

```python
# Get solution statistics
print(f"Total clients served: {result.total_clients}")
print(f"Total distance: {result.total_distance(data):.2f}")
print(f"Total duration: {result.total_duration:.2f}")
print(f"Total charging time: {result.total_charging_time:.2f}")

# Iterate over routes
for i, route in enumerate(result):
    print(f"\nRoute {i + 1}:")
    print(f"  Clients: {route.num_clients}")
    print(f"  Charging stops: {route.num_charging_stops}")
    print(f"  Duration: {route.duration:.2f}")

    for visit in route:
        print(f"  - {visit.visit_type.name} {visit.node_id}: "
              f"arrive={visit.arrival_time:.1f}, "
              f"battery={visit.battery_arrival:.1f} kWh")
```

## API Reference

### Model Components

- `Model` - Fluent interface for building EVRP problems
- `ProblemData` - Immutable problem data container
- `Location` - 2D coordinate (x, y)
- `Client` - Customer with demand, service time, and time window
- `Depot` - Vehicle depot with operating hours
- `ChargingStation` - Charging station with charging rate
- `VehicleType` - Vehicle specification with battery parameters
- `Battery` - Battery specification (capacity, consumption rate, SOC limits)

### Solution Components

- `Solution` - Complete solution with multiple routes
- `Route` - Single vehicle route
- `Visit` - Visit to a node (depot, client, or station)
- `VisitType` - Enum: DEPOT, CLIENT, STATION
- `SolutionValidator` - Constraint validation

### Algorithms

- `GreedyInsertion` - Battery-aware greedy construction heuristic
- `BaseSolver` - Abstract base class for custom solvers

### Stopping Criteria

- `MaxIterations` - Stop after N iterations
- `MaxRuntime` - Stop after N seconds
- `NoImprovement` - Stop after N iterations without improvement
- `TargetCost` - Stop when target cost is reached
- `Combined` - Combine multiple criteria

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Citation

If you use pyevrp in your research, please cite:

```bibtex
@software{pyevrp,
  title = {pyevrp: Electric Vehicle Routing Problem Library for Python},
  year = {2024},
  url = {https://github.com/pyevrp/pyevrp}
}
```

## References

- Schneider, M., Stenger, A., & Goeke, D. (2014). The electric vehicle-routing problem with time windows and recharging stations. Transportation Science, 48(4), 500-520.
- Solomon, M. M. (1987). Algorithms for the vehicle routing and scheduling problems with time window constraints. Operations Research, 35(2), 254-265.