October 2025
A hands-on workshop for solving Vehicle Routing Problems (VRP) with Time Windows using Timefold Solver. Participants will learn to customize optimization constraints and build their own routing solutions.
- Java >= 17
- Python 3.10.12
- pip (Python package manager)
Note
Timefold requires the JVM to run, so you'll need to install that first
macOS:
brew install openjdkAfter installation, symlink it for macOS to recognize it:
sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdkWindows:
- Download OpenJDK from Adoptium or Oracle
- Run the installer and follow the installation wizard
- The installer will automatically set up the
JAVA_HOMEenvironment variable
Verify installation:
java -version-
Clone the repository:
git clone <repository-url> cd o4a-vrp-workshop-2025
-
Create a virtual environment (recommended):
Using standard venv:
python3.10 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
Using pyenv:
pyenv install 3.10.12 pyenv local 3.10.12 pyenv virtualenv 3.10.12 o4a-vrp pyenv activate o4a-vrp -
Install dependencies:
pip install -r requirements.txt
-
Run the web interface:
gradio gradio_interface.py
Using the
gradiocommand allos the interface to listen to changes in the code and a refresh is sufficient to load them in -
Access the web interface: Open your browser and go to
http://localhost:7860 -
Alternative: Run the solver directly:
python -m src.solver.solver
The easiest way to customize the routing optimization is by adding your own constraints. Here's how:
Navigate to src/solver/constraints.py
Copy and modify the example template:
def my_custom_constraint(constraint_factory):
"""Your constraint description here"""
return (constraint_factory
.for_each(Vehicle)
# Your condition here (when to apply penalty)
.filter(lambda vehicle: len(vehicle.visits) > 8)
.penalize(HardMediumSoftScore.ONE_SOFT,
# Your penalty calculation here
lambda vehicle: (len(vehicle.visits) - 8) * 50)
.as_constraint("My constraint name"))Find the ACTIVE_CONSTRAINTS list at the bottom of the file and add your function:
ACTIVE_CONSTRAINTS = [
vehicle_capacity_constraint,
time_window_constraint,
minimize_vehicles_constraint,
# Add your constraint here:
my_custom_constraint,
]Your constraint will automatically be loaded and used by the solver!
Use different penalty levels to prioritize your constraints:
HardMediumSoftScore.ONE_HARD: Must be satisfied (violation = infeasible solution)HardMediumSoftScore.ONE_MEDIUM: High priority (like minimizing vehicles)HardMediumSoftScore.ONE_SOFT: Lower priority optimization goals
vehicle.visits: List of assigned customersvehicle.capacity: Maximum capacityvehicle.home_location: Depot locationvehicle.get_total_demand(): Total demand of assigned customersvehicle.get_total_distance(): Total travel distance
customer.location: Location with x, y coordinatescustomer.demand: Resource demand (weight, volume, etc.)customer.ready_time: Earliest service timecustomer.due_time: Latest service timecustomer.service_time: Time needed to serve customer
o4a-vrp-workshop-2025/
├── src/
│ ├── solver/
│ │ ├── constraints.py # Add your constraints here!
│ │ ├── domain.py # Data models
│ │ └── solver.py # Main solver logic
│ └── io/
│ └── dataloaders.py # Data loading utilities
├── data/ # Dataset files
├── gradio_interface.py # Web interface
├── requirements.txt # Python dependencies
└── README.md # This file
- Start Simple: Begin by modifying the example constraint
- Test Incrementally: Add one constraint at a time
- Use Helper Functions: Break complex logic into separate functions
- Check the Logs: The solver shows which constraints are active
- Experiment: Try different penalty values and see how they affect routes
- Run the application:
gradio gradio_interface.py - Load a dataset in the web interface
- Click "Solve" to see your constraints in action
- Check the console output for constraint details
- Visualize the results on the map
If you encounter issues installing Timefold:
pip install --upgrade pip
pip install timefold --no-cache-dir- Check Python version:
python --version(should be 3.8+) - Verify all packages are installed:
pip list | grep -E "(timefold|gradio|matplotlib)" - Try running the solver directly:
python -m src.solver.solver
- Check syntax in your constraint function
- Ensure your constraint is added to
ACTIVE_CONSTRAINTS - Check console output for error messages
This workshop is for educational purposes. Please check individual package licenses for production use.