Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
find_package(PkgConfig REQUIRED)
find_package(Threads REQUIRED)

# Find OpenSSL for vroom library
find_package(OpenSSL REQUIRED)

# resolve vendored libraries
set(date_include_dir ${VALHALLA_SOURCE_DIR}/third_party/date/include)
set(rapidjson_include_dir ${VALHALLA_SOURCE_DIR}/third_party/rapidjson/include)
Expand Down Expand Up @@ -204,6 +207,49 @@ endif()

set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)

# VROOM library configuration
# Check if libvroom.a exists in the vroom lib directory
set(VROOM_LIB_PATH "/Users/boon.boonsiri/local/backup/vroom/lib/libvroom.a")
if(EXISTS ${VROOM_LIB_PATH})
message(STATUS "Found libvroom.a at ${VROOM_LIB_PATH}")
set(VROOM_LIBRARY ${VROOM_LIB_PATH})
set(VROOM_INCLUDE_DIR "/Users/boon.boonsiri/local/backup/vroom/src")

# Create an imported target for vroom
add_library(vroom STATIC IMPORTED)
set_target_properties(vroom PROPERTIES
IMPORTED_LOCATION ${VROOM_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${VROOM_INCLUDE_DIR}
)

# Add required system libraries for vroom
target_link_libraries(vroom INTERFACE
Threads::Threads
OpenSSL::SSL
OpenSSL::Crypto
)

# Check for GLPK (similar to the Makefile logic)
find_path(GLPK_INCLUDE_DIR glpk.h
PATHS /usr/include /usr/local/include
)
if(GLPK_INCLUDE_DIR)
find_library(GLPK_LIBRARY glpk)
if(GLPK_LIBRARY)
message(STATUS "Found GLPK: ${GLPK_LIBRARY}")
target_link_libraries(vroom INTERFACE ${GLPK_LIBRARY})
target_include_directories(vroom INTERFACE ${GLPK_INCLUDE_DIR})
endif()
endif()

set(VROOM_FOUND TRUE)
set(VROOM_FOUND ${VROOM_FOUND} CACHE BOOL "Whether VROOM library was found" FORCE)
else()
message(WARNING "libvroom.a not found at ${VROOM_LIB_PATH}")
set(VROOM_FOUND FALSE)
set(VROOM_FOUND ${VROOM_FOUND} CACHE BOOL "Whether VROOM library was found" FORCE)
endif()

# libprime_server
# see https://gitlab.kitware.com/cmake/cmake/-/issues/19467
set(libprime_server_targets "")
Expand Down Expand Up @@ -313,6 +359,13 @@ if(ENABLE_SERVICES)
endforeach()
endif()

# VROOM library integration with valhalla
if(VROOM_FOUND)
message(STATUS "VROOM library will be linked to valhalla")
else()
message(WARNING "VROOM library not found - vehicle routing features will not be available")
endif()

# add the scripts to the build folder as well
foreach(script valhalla_build_config valhalla_build_elevation
valhalla_build_extract valhalla_build_timezones)
Expand Down
4 changes: 3 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ target_link_libraries(valhalla
$<$<BOOL:${WIN32}>:ws2_32>
PRIVATE
$<$<BOOL:${ENABLE_COVERAGE}>:gcov>
Threads::Threads)
Threads::Threads
$<$<BOOL:${VROOM_FOUND}>:vroom>)


set_target_properties(valhalla PROPERTIES
VERSION "${VERSION}"
Expand Down
1 change: 1 addition & 0 deletions src/thor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set(sources
timedistancematrix.cc
triplegbuilder.cc
unidirectional_astar.cc
vehicle_routing_problem.cc
worker.cc)

set(sources_with_warnings
Expand Down
117 changes: 117 additions & 0 deletions src/thor/vehicle_routing_problem.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include <iostream>
#include <vector>
#include "valhalla/thor/vehicle_routing_problem.h"

#ifdef VROOM_FOUND
#include <vroom/vroom.h>
#endif

namespace valhalla {
namespace thor {

VehicleRoutingSolution solve_vehicle_routing_problem(const VehicleRoutingRequest& request) {
VehicleRoutingSolution solution;


#ifdef VROOM_FOUND
// Create a VROOM problem instance
vroom::Input problem;

// Add vehicles from the request
for (const auto& vehicle : request.vehicles) {
problem.add_vehicle(vroom::Vehicle(vehicle.id, vehicle.start_location, vehicle.end_location));
}

// Add jobs from the request
for (const auto& job : request.jobs) {
problem.add_job(vroom::Job(job.id, job.location, job.service_time));
}

// Set the distance matrix
problem.set_matrix(request.distance_matrix);

// Solve the problem
vroom::Solution vroom_solution = problem.solve();

// Convert VROOM solution to our format
solution.total_cost = vroom_solution.summary.cost;
solution.total_service_time = vroom_solution.summary.service;
solution.total_duration = vroom_solution.summary.duration;
solution.computing_time_ms = vroom_solution.summary.computing_times.solving;

// Convert routes
for (const auto& route : vroom_solution.routes) {
Route route_info;
route_info.vehicle_id = route.vehicle;
route_info.cost = route.cost;
route_info.duration = route.duration;
route_info.service_time = route.service;

// Convert steps
for (const auto& step : route.steps) {
RouteStep step_info;
step_info.type = static_cast<RouteStep::StepType>(step.type);
step_info.location = step.location;
step_info.job_id = step.job;
route_info.steps.push_back(step_info);
}

solution.routes.push_back(route_info);
}

// Convert unassigned jobs
for (const auto& job : vroom_solution.unassigned) {
solution.unassigned_jobs.push_back(job.id);
}
#else
// VROOM not available - return empty solution
solution.total_cost = 0;
solution.total_service_time = 0;
solution.total_duration = 0;
solution.computing_time_ms = 0;
#endif

return solution;
}

// Example function that demonstrates basic VRP usage
VehicleRoutingSolution solve_basic_vrp_example() {
VehicleRoutingRequest request;

// Add one vehicle starting and ending at location 0
Vehicle vehicle;
vehicle.id = 1;
vehicle.start_location = 0;
vehicle.end_location = 0;
request.vehicles.push_back(vehicle);

// Add three jobs
Job job1, job2, job3;
job1.id = 1;
job1.location = 1;
job1.service_time = 300; // 5 minutes

job2.id = 2;
job2.location = 2;
job2.service_time = 300;

job3.id = 3;
job3.location = 3;
job3.service_time = 300;

request.jobs = {job1, job2, job3};

// Define distance matrix (4x4 symmetric matrix)
// Locations: 0 (depot), 1, 2, 3
request.distance_matrix = {
{0, 10, 15, 20}, // from depot to locations
{10, 0, 35, 25}, // from location 1
{15, 35, 0, 30}, // from location 2
{20, 25, 30, 0} // from location 3
};

return solve_vehicle_routing_problem(request);
}

} // namespace thor
} // namespace valhalla
75 changes: 75 additions & 0 deletions valhalla/thor/vehicle_routing_problem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <vector>
#include <cstdint>

namespace valhalla {
namespace thor {

// Forward declaration to avoid including VROOM headers in public interface
struct VehicleRoutingSolution;

// Data structures for vehicle routing problem
struct Vehicle {
uint32_t id;
uint32_t start_location;
uint32_t end_location;
};

struct Job {
uint32_t id;
uint32_t location;
uint32_t service_time; // in seconds
};

struct RouteStep {
enum class StepType {
START = 0,
JOB = 1,
END = 2
};

StepType type;
uint32_t location;
uint32_t job_id;
};

struct Route {
uint32_t vehicle_id;
uint32_t cost;
uint32_t duration;
uint32_t service_time;
std::vector<RouteStep> steps;
};

struct VehicleRoutingRequest {
std::vector<Vehicle> vehicles;
std::vector<Job> jobs;
std::vector<std::vector<uint32_t>> distance_matrix;
};

struct VehicleRoutingSolution {
uint32_t total_cost;
uint32_t total_service_time;
uint32_t total_duration;
uint32_t computing_time_ms;
std::vector<Route> routes;
std::vector<uint32_t> unassigned_jobs;
};

/**
* Solve a vehicle routing problem using VROOM
* @param request The vehicle routing problem request
* @return The solution containing optimal routes
*/
VehicleRoutingSolution solve_vehicle_routing_problem(const VehicleRoutingRequest& request);

/**
* Example function that demonstrates basic VRP usage
* Creates a simple problem with 1 vehicle and 3 jobs
* @return The solution for the example problem
*/
VehicleRoutingSolution solve_basic_vrp_example();

} // namespace thor
} // namespace valhalla
Loading