vrp-pragmatic 1.19.1

An extension logic for solving rich VRP
Documentation
use vrp_core::models::common::{Distance, Timestamp};

use crate::format::problem::*;
use crate::format::solution::*;
use crate::format::Location;
use crate::format_time;
use crate::helpers::*;

type CommuteData = Option<(f64, Distance, Timestamp, Timestamp)>;

struct ActivityData {
    job_id: String,
    location: Option<f64>,
    a_type: String,
    time: Option<(Timestamp, Timestamp)>,
    commute: Option<(CommuteData, CommuteData)>,
}

impl ActivityData {
    #[allow(clippy::type_complexity)]
    pub fn new(
        data: (&str, Option<f64>, &str, Option<(Timestamp, Timestamp)>, Option<(CommuteData, CommuteData)>),
    ) -> Self {
        Self { job_id: data.0.to_string(), location: data.1, a_type: data.2.to_string(), time: data.3, commute: data.4 }
    }
}

impl From<ActivityData> for Activity {
    fn from(activity: ActivityData) -> Self {
        let convert_expected_commute_info = |commute: CommuteData| {
            commute.map(|commute| CommuteInfo {
                location: (commute.0, 0.).to_loc(),
                distance: commute.1,
                time: Interval { start: format_time(commute.2), end: format_time(commute.3) },
            })
        };

        Activity {
            job_id: activity.job_id,
            activity_type: activity.a_type,
            location: activity.location.map(|loc| (loc, 0.).to_loc()),
            time: activity.time.map(|(start, end)| Interval { start: format_time(start), end: format_time(end) }),
            job_tag: None,
            commute: activity.commute.map(|(fwd, bak)| Commute {
                forward: convert_expected_commute_info(fwd),
                backward: convert_expected_commute_info(bak),
            }),
        }
    }
}

struct StopData {
    location: Location,
    distance: i64,
    load: i32,
    parking: i64,
    time: (Timestamp, Timestamp),
    activities: Vec<ActivityData>,
}

impl StopData {
    pub fn new(data: (f64, i64, i32, i64, (Timestamp, Timestamp), Vec<ActivityData>)) -> Self {
        Self {
            location: (data.0, 0.).to_loc(),
            distance: data.1,
            load: data.2,
            parking: data.3,
            time: data.4,
            activities: data.5,
        }
    }
}

impl From<StopData> for Stop {
    fn from(stop: StopData) -> Self {
        Stop::Point(PointStop {
            location: stop.location,
            time: Schedule { arrival: format_time(stop.time.0), departure: format_time(stop.time.1) },
            distance: stop.distance,
            parking: if stop.parking > 0 {
                Some(Interval { start: format_time(stop.time.0), end: format_time(stop.time.0 + stop.parking as f64) })
            } else {
                None
            },
            load: vec![stop.load],
            activities: stop.activities.into_iter().map(ActivityData::into).collect(),
        })
    }
}

fn create_statistic(data: (f64, i64, i64, (i64, i64, i64, i64))) -> Statistic {
    Statistic {
        cost: data.0,
        distance: data.1,
        duration: data.2,
        times: Timing {
            driving: data.3 .0,
            serving: data.3 .1,
            commuting: data.3 .2,
            parking: data.3 .3,
            ..Timing::default()
        },
    }
}

fn create_test_problem(jobs_data: &[(f64, &str)], capacity: i32, clustering: Clustering) -> Problem {
    Problem {
        plan: Plan {
            jobs: jobs_data
                .iter()
                .enumerate()
                .map(|(idx, &(loc, j_type))| match j_type {
                    "delivery" => create_delivery_job(&format!("job{}", idx + 1), (loc, 0.)),
                    "pickup" => create_pickup_job(&format!("job{}", idx + 1), (loc, 0.)),
                    _ => unreachable!(),
                })
                .collect(),
            clustering: Some(clustering),
            ..create_empty_plan()
        },
        fleet: Fleet {
            vehicles: vec![VehicleType {
                shifts: vec![create_default_open_vehicle_shift()],
                ..create_vehicle_with_capacity("my_vehicle", vec![capacity])
            }],
            ..create_default_fleet()
        },
        ..create_empty_problem()
    }
}

mod basic_vicinity_test;
mod capacity_vicinity_test;
mod profile_vicinity_test;
mod specific_vicinity_test;