Created
September 3, 2021 12:39
-
-
Save krypt-n/7e07418b1cfa875d9e55077c230bba23 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "routing/osrm_routed_wrapper.h" | |
#include "structures/vroom/input/input.h" | |
#include "structures/vroom/job.h" | |
#include "structures/vroom/vehicle.h" | |
#include "utils/exception.h" | |
void log_solution(const vroom::Solution& sol, bool geometry) { | |
std::cout << "Total cost: " << sol.summary.cost << std::endl; | |
std::cout << "Unassigned: " << sol.summary.unassigned << std::endl; | |
// Log unassigned jobs if any. | |
std::cout << "Unassigned job ids: "; | |
for (const auto& j : sol.unassigned) { | |
std::cout << j.id << ", "; | |
} | |
std::cout << std::endl; | |
// Describe routes in solution. | |
for (const auto& route : sol.routes) { | |
std::cout << "Steps for vehicle " << route.vehicle | |
<< " (cost: " << route.cost; | |
std::cout << " - duration: " << route.duration; | |
std::cout << " - service: " << route.service; | |
if (geometry) { | |
std::cout << " - distance: " << route.distance; | |
} | |
std::cout << ")" << std::endl; | |
// Describe all route steps. | |
for (const auto& step : route.steps) { | |
std::string type; | |
switch (step.step_type) { | |
case vroom::STEP_TYPE::START: | |
type = "Start"; | |
break; | |
case vroom::STEP_TYPE::END: | |
type = "End"; | |
break; | |
case vroom::STEP_TYPE::BREAK: | |
type = "Break"; | |
break; | |
case vroom::STEP_TYPE::JOB: | |
switch (step.job_type) { | |
case vroom::JOB_TYPE::SINGLE: | |
type = "Job"; | |
break; | |
case vroom::JOB_TYPE::PICKUP: | |
type = "Pickup"; | |
break; | |
case vroom::JOB_TYPE::DELIVERY: | |
type = "Delivery"; | |
break; | |
} | |
break; | |
} | |
std::cout << type; | |
// Add job/pickup/delivery/break ids. | |
if (step.step_type != vroom::STEP_TYPE::START and | |
step.step_type != vroom::STEP_TYPE::END) { | |
std::cout << " " << step.id; | |
} | |
// Add location if known. | |
if (step.location.has_coordinates()) { | |
std::cout << " - " << step.location.lon() << ";" << step.location.lat(); | |
} | |
std::cout << " - arrival: " << step.arrival; | |
std::cout << " - duration: " << step.duration; | |
std::cout << " - service: " << step.service; | |
// Add extra step info if geometry is required. | |
if (geometry) { | |
std::cout << " - distance: " << step.distance; | |
} | |
std::cout << std::endl; | |
} | |
} | |
} | |
void run_example_with_osrm() { | |
bool GEOMETRY = true; | |
unsigned amount_dimension = 1; | |
// Set OSRM host and port for "car" profile. | |
vroom::io::Servers servers; | |
servers["car"] = vroom::Server("localhost", "5000"); | |
vroom::Input problem_instance(amount_dimension, servers, vroom::ROUTER::OSRM); | |
problem_instance.set_geometry(GEOMETRY); // Query for route geometry | |
// after solving. | |
// Create one-dimension capacity restrictions to model the situation | |
// where one vehicle can handle 4 jobs with deliveries. | |
vroom::Amount vehicle_capacity(1); | |
vroom::TimeWindow vehicle_tw(28800, 43200); // Working hours. | |
// Default "zero" amount data structures with relevant dimension. | |
vroom::Amount job_delivery(amount_dimension); | |
vroom::Amount job_empty_delivery(amount_dimension); | |
job_delivery[0] = 1; | |
vroom::Amount job_pickup(amount_dimension); | |
vroom::Amount job_empty_pickup(amount_dimension); | |
job_pickup[0] = 1; | |
vroom::Duration service = 5 * 60; // 5 minutes | |
vehicle_capacity[0] = 4; | |
// Define vehicle breaks. | |
vroom::Break break_1(1, {vroom::TimeWindow(32400, 34200)}, 300); | |
vroom::Break break_2(2, {vroom::TimeWindow(34200, 36000)}, 300); | |
// Define vehicles (use std::nullopt for no start or no end). | |
vroom::Location depot(vroom::Coordinates({{2.35044, 48.71764}})); | |
vroom::Vehicle v1(1, // id | |
depot, // start | |
depot, // end | |
"car", // profile | |
vehicle_capacity, // capacity | |
{1, 14}, // skills | |
vehicle_tw, // time window | |
{break_1}); // breaks | |
problem_instance.add_vehicle(v1); | |
vroom::Vehicle v2(2, // id | |
depot, // start | |
depot, // end | |
"car", // profile | |
vehicle_capacity, // capacity | |
{2, 14}, // skills | |
vehicle_tw, // time window | |
{break_2}); // breaks | |
problem_instance.add_vehicle(v2); | |
// Job to be done between 9 and 10 AM. | |
std::vector<vroom::TimeWindow> job_1_tws({{32400, 36000}}); | |
// Set jobs id, location, service time, amount, required skills, | |
// priority and time windows. Constraints that are not required can | |
// be omitted. | |
std::vector<vroom::Job> jobs; | |
jobs.push_back(vroom::Job(1, | |
vroom::Coordinates({{1.98935, 48.701}}), | |
service, | |
job_delivery, | |
job_empty_pickup, | |
{1}, // skills | |
0, // default priority | |
job_1_tws)); | |
jobs.push_back(vroom::Job(2, | |
vroom::Coordinates({{2.03655, 48.61128}}), | |
service, | |
job_empty_delivery, | |
job_pickup, | |
{1})); | |
jobs.push_back(vroom::Job(5, | |
vroom::Coordinates({{2.28325, 48.5958}}), | |
service, | |
job_delivery, | |
job_empty_pickup, | |
{14})); | |
jobs.push_back(vroom::Job(6, | |
vroom::Coordinates({{2.89357, 48.90736}}), | |
service, | |
job_delivery, | |
job_empty_pickup, | |
{14})); | |
for (const auto& j : jobs) { | |
problem_instance.add_job(j); | |
} | |
// Define a shipment. | |
vroom::Skills pd_skills({2}); | |
vroom::Amount pd_amount(amount_dimension); | |
pd_amount[0] = 1; | |
vroom::Job pickup(4, | |
vroom::JOB_TYPE::PICKUP, | |
vroom::Coordinates({{2.41808, 49.22619}}), | |
service, | |
pd_amount, | |
pd_skills); | |
vroom::Job delivery(3, | |
vroom::JOB_TYPE::DELIVERY, | |
vroom::Coordinates({{2.39719, 49.07611}}), | |
service, | |
pd_amount, | |
pd_skills); | |
problem_instance.add_shipment(pickup, delivery); | |
// Skills definitions set the following constraints: | |
// - jobs 1 and 2 can only be served by vehicle 1 | |
// - jobs 3 and 4 can only be served by vehicle 2 | |
// - jobs 5 and 6 can be served by either one of the vehicles | |
// Solve! | |
auto sol = problem_instance.solve(5, // Exploration level. | |
4); // Use 4 threads. | |
log_solution(sol, GEOMETRY); | |
} | |
void run_example_with_custom_matrix() { | |
bool GEOMETRY = false; | |
unsigned amount_dimension = 0; // No capacity constraint. | |
vroom::Input problem_instance(amount_dimension); | |
vroom::Cost blub[18][18] = {{0,34,68,99,128,152,172,187,195,199,195,187,172,152,128,99,68,34}, | |
{34,0,34,67,99,127,151,171,186,194,198,195,186,171,152,127,99,68}, | |
{68,34,0,34,68,99,126,152,171,186,195,198,195,186,172,152,128,99}, | |
{99,67,34,0,35,68,99,127,152,172,186,195,198,195,186,172,152,127}, | |
{128,99,68,35,0,34,67,99,127,151,171,186,195,198,196,186,172,152}, | |
{152,127,99,68,34,0,34,68,99,127,152,172,186,196,198,195,186,171}, | |
{172,151,126,99,67,34,0,34,68,99,127,152,172,186,195,197,195,185}, | |
{187,171,152,127,99,68,34,0,34,68,99,128,152,172,186,195,198,195}, | |
{195,186,171,152,127,99,68,34,0,34,68,99,127,152,171,185,195,198}, | |
{199,194,186,172,151,127,99,68,34,0,34,68,98,127,151,171,186,194}, | |
{195,198,195,186,171,152,127,99,68,34,0,34,67,99,127,151,171,186}, | |
{187,195,198,195,186,172,152,128,99,68,34,0,34,68,99,126,152,171}, | |
{172,186,195,198,195,186,172,152,127,98,67,34,0,35,68,99,127,152}, | |
{152,171,186,195,198,196,186,172,152,127,99,68,35,0,34,67,99,127}, | |
{128,152,172,186,196,198,195,186,171,151,127,99,68,34,0,34,68,99}, | |
{99,127,152,172,186,195,197,195,185,171,151,126,99,67,34,0,34,68}, | |
{68,99,128,152,172,186,195,198,195,186,171,152,127,99,68,34,0,34}, | |
{34,68,99,127,152,171,185,195,198,194,186,171,152,127,99,68,34,0}}; | |
// Define custom matrix and bypass OSRM call. | |
vroom::Matrix<vroom::Cost> matrix_input(18); | |
for(int i = 0; i < 18; i++) { | |
for (int j = 0; j < 18; j++) { | |
matrix_input[i][j] = blub[i][j]; | |
} | |
} | |
problem_instance.set_matrix("car", std::move(matrix_input)); | |
// Define vehicles (use std::nullopt for no start or no end). | |
vroom::Location v_start(0); // index in the provided matrix. | |
vroom::Location v_start2(1); // index in the provided matrix. | |
/* vroom::Location v_end(3); // index in the provided matrix. */ | |
vroom::Vehicle v(0, // id | |
v_start, // start | |
std::nullopt); // end | |
vroom::Vehicle v2(1, // id | |
v_start2, // start | |
std::nullopt); // end | |
problem_instance.add_vehicle(v); | |
problem_instance.add_vehicle(v2); | |
// Define jobs with id and index of location in the matrix | |
// (coordinates are optional). Constraints that are not required can | |
// be omitted. | |
std::vector<vroom::Job> jobs; | |
for (int i = 0; i < 18; ++i) { | |
jobs.push_back(vroom::Job(i, i)); | |
} | |
for (const auto& j : jobs) { | |
problem_instance.add_job(j); | |
} | |
// Solve! | |
auto sol = problem_instance.solve(5, // Exploration level. | |
4); // Use 4 threads. | |
log_solution(sol, GEOMETRY); | |
} | |
int main() { | |
try { | |
/* run_example_with_osrm(); */ | |
run_example_with_custom_matrix(); | |
} catch (const vroom::Exception& e) { | |
std::cerr << "[Error] " << e.message << std::endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment