vrp-core 1.25.0

A core algorithms to solve a Vehicle Routing Problem
Documentation
use crate::construction::features::VehicleCapacityDimension;
use crate::models::common::*;
use crate::models::problem::*;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;

pub const DEFAULT_ACTOR_LOCATION: Location = 0;
pub const DEFAULT_ACTOR_TIME_WINDOW: TimeWindow = TimeWindow { start: 0.0, end: 1000.0 };
pub const DEFAULT_VEHICLE_COSTS: Costs =
    Costs { fixed: 0.0, per_distance: 1.0, per_driving_time: 1.0, per_waiting_time: 1.0, per_service_time: 1.0 };

pub fn test_costs() -> Costs {
    DEFAULT_VEHICLE_COSTS
}

pub fn fixed_costs() -> Costs {
    Costs { fixed: 100.0, per_distance: 1.0, per_driving_time: 1.0, per_waiting_time: 1.0, per_service_time: 1.0 }
}

pub fn empty_costs() -> Costs {
    Costs { fixed: 0.0, per_distance: 0.0, per_driving_time: 0.0, per_waiting_time: 0.0, per_service_time: 0.0 }
}

pub fn test_driver() -> Driver {
    test_driver_with_costs(test_costs())
}

pub fn test_driver_with_costs(costs: Costs) -> Driver {
    Driver { costs, ..Driver::empty() }
}

pub fn test_vehicle_detail() -> VehicleDetail {
    VehicleDetail {
        start: Some(VehiclePlace {
            location: 0,
            time: TimeInterval { earliest: Some(DEFAULT_ACTOR_TIME_WINDOW.start), latest: None },
        }),
        end: Some(VehiclePlace {
            location: 0,
            time: TimeInterval { earliest: None, latest: Some(DEFAULT_ACTOR_TIME_WINDOW.end) },
        }),
    }
}

pub fn test_vehicle(profile_idx: usize) -> Vehicle {
    Vehicle {
        profile: Profile::new(profile_idx, None),
        costs: test_costs(),
        dimens: Default::default(),
        details: vec![test_vehicle_detail()],
    }
}

pub fn test_ovrp_vehicle(id: &str) -> Vehicle {
    TestVehicleBuilder::default().id(id).details(vec![VehicleDetail { end: None, ..test_vehicle_detail() }]).build()
}

pub fn test_fleet() -> Fleet {
    FleetBuilder::default().add_driver(test_driver()).add_vehicle(test_vehicle_with_id("v1")).build()
}

pub fn test_vehicle_with_id(id: &str) -> Vehicle {
    let mut dimens = Dimensions::default();
    dimens.set_vehicle_id(id.to_string());

    Vehicle { profile: Profile::default(), costs: test_costs(), dimens, details: vec![test_vehicle_detail()] }
}

pub fn get_vehicle_id(vehicle: &Vehicle) -> &String {
    vehicle.dimens.get_vehicle_id().unwrap()
}

pub fn get_test_actor_from_fleet(fleet: &Fleet, vehicle_id: &str) -> Arc<Actor> {
    fleet.actors.iter().find(|actor| get_vehicle_id(&actor.vehicle) == vehicle_id).unwrap().clone()
}

pub struct TestVehicleBuilder(Vehicle);

impl Default for TestVehicleBuilder {
    fn default() -> Self {
        Self(test_vehicle(0))
    }
}

impl TestVehicleBuilder {
    pub fn id(&mut self, id: &str) -> &mut Self {
        self.0.dimens.set_vehicle_id(id.to_string());
        self
    }

    pub fn profile(&mut self, profile: Profile) -> &mut Self {
        self.0.profile = profile;
        self
    }

    pub fn capacity(&mut self, capacity: i32) -> &mut Self {
        self.0.dimens.set_vehicle_capacity(SingleDimLoad::new(capacity));
        self
    }

    pub fn capacity_mult(&mut self, capacity: Vec<i32>) -> &mut Self {
        self.0.dimens.set_vehicle_capacity(MultiDimLoad::new(capacity));
        self
    }

    pub fn costs(&mut self, costs: Costs) -> &mut Self {
        self.0.costs = costs;
        self
    }

    pub fn details(&mut self, details: Vec<VehicleDetail>) -> &mut Self {
        self.0.details = details;
        self
    }

    pub fn property<K: 'static, T: 'static + Sync + Send>(&mut self, value: T) -> &mut Self {
        self.0.dimens.set_value::<K, _>(value);
        self
    }

    pub fn dimens_mut(&mut self) -> &mut Dimensions {
        &mut self.0.dimens
    }

    pub fn build(&mut self) -> Vehicle {
        std::mem::replace(&mut self.0, test_vehicle(0))
    }
}

pub type GroupKeyFn = Box<dyn Fn(&[Arc<Actor>]) -> Box<dyn Fn(&Actor) -> usize + Send + Sync>>;

#[derive(Default)]
pub struct FleetBuilder {
    drivers: Vec<Driver>,
    vehicles: Vec<Vehicle>,
    group_key_fn: Option<GroupKeyFn>,
}

impl FleetBuilder {
    pub fn add_driver(&mut self, driver: Driver) -> &mut FleetBuilder {
        self.drivers.push(driver);
        self
    }

    pub fn add_vehicle(&mut self, vehicle: Vehicle) -> &mut FleetBuilder {
        self.vehicles.push(vehicle);
        self
    }

    pub fn add_vehicles(&mut self, vehicles: Vec<Vehicle>) -> &mut FleetBuilder {
        self.vehicles.extend(vehicles);
        self
    }

    pub fn with_group_key_fn(&mut self, group_key_fn: GroupKeyFn) -> &mut FleetBuilder {
        self.group_key_fn = Some(group_key_fn);
        self
    }

    pub fn build(&mut self) -> Fleet {
        let drivers = std::mem::take(&mut self.drivers);
        let vehicles = std::mem::take(&mut self.vehicles);

        let drivers = drivers.into_iter().map(Arc::new).collect();
        let vehicles = vehicles.into_iter().map(Arc::new).collect();

        let group_key = self
            .group_key_fn
            .take()
            .unwrap_or_else(|| Box::new(|actors| Box::new(create_details_actor_groups(actors))));

        Fleet::new(drivers, vehicles, group_key)
    }
}

#[allow(clippy::type_complexity)]
pub fn create_details_actor_groups(actors: &[Arc<Actor>]) -> impl Fn(&Actor) -> usize + Send + Sync {
    let unique_type_keys: HashSet<_> = actors.iter().map(|a| a.detail.clone()).collect();

    let type_key_map: HashMap<_, _> = unique_type_keys.into_iter().zip(0_usize..).collect();

    let groups: HashMap<_, _> = actors.iter().map(|a| (a.clone(), *type_key_map.get(&a.detail).unwrap())).collect();

    move |a| *groups.get(a).unwrap()
}