#[cfg(test)]
#[path = "../../../tests/unit/models/problem/fleet_test.rs"]
mod fleet_test;
use crate::models::common::*;
use crate::utils::short_type_name;
use hashbrown::{HashMap, HashSet};
use std::cmp::Ordering::Less;
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct Costs {
pub fixed: f64,
pub per_distance: f64,
pub per_driving_time: f64,
pub per_waiting_time: f64,
pub per_service_time: f64,
}
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct DriverDetail {}
pub struct Driver {
pub costs: Costs,
pub dimens: Dimensions,
pub details: Vec<DriverDetail>,
}
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct VehiclePlace {
pub location: Location,
pub time: TimeInterval,
}
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct VehicleDetail {
pub start: Option<VehiclePlace>,
pub end: Option<VehiclePlace>,
}
pub struct Vehicle {
pub profile: Profile,
pub costs: Costs,
pub dimens: Dimensions,
pub details: Vec<VehicleDetail>,
}
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct ActorDetail {
pub start: Option<VehiclePlace>,
pub end: Option<VehiclePlace>,
pub time: TimeWindow,
}
pub struct Actor {
pub vehicle: Arc<Vehicle>,
pub driver: Arc<Driver>,
pub detail: ActorDetail,
}
impl Debug for Actor {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct(short_type_name::<Self>())
.field("vehicle", &self.vehicle.dimens.get_id().map(|id| id.as_str()).unwrap_or("undef"))
.finish_non_exhaustive()
}
}
pub type ActorGroupKeyFn = Box<dyn Fn(&[Arc<Actor>]) -> Box<dyn Fn(&Arc<Actor>) -> usize + Send + Sync>>;
pub struct Fleet {
pub drivers: Vec<Arc<Driver>>,
pub vehicles: Vec<Arc<Vehicle>>,
pub profiles: Vec<Profile>,
pub actors: Vec<Arc<Actor>>,
pub groups: HashMap<usize, HashSet<Arc<Actor>>>,
}
impl Fleet {
pub fn new(drivers: Vec<Arc<Driver>>, vehicles: Vec<Arc<Vehicle>>, group_key: ActorGroupKeyFn) -> Fleet {
assert_eq!(drivers.len(), 1);
assert!(!vehicles.is_empty());
let profiles: HashMap<usize, Profile> = vehicles.iter().map(|v| (v.profile.index, v.profile.clone())).collect();
let mut profiles = profiles.into_iter().collect::<Vec<_>>();
profiles.sort_by(|(a, _), (b, _)| a.partial_cmp(b).unwrap_or(Less));
let (_, profiles): (Vec<_>, Vec<_>) = profiles.into_iter().unzip();
let actors = vehicles
.iter()
.flat_map(|vehicle| {
vehicle.details.iter().map(|detail| {
Arc::new(Actor {
vehicle: vehicle.clone(),
driver: drivers.first().unwrap().clone(),
detail: ActorDetail {
start: detail.start.clone(),
end: detail.end.clone(),
time: TimeWindow {
start: detail.start.as_ref().and_then(|s| s.time.earliest).unwrap_or(0.),
end: detail.end.as_ref().and_then(|e| e.time.latest).unwrap_or(f64::MAX),
},
},
})
})
})
.collect::<Vec<_>>();
let group_key = (*group_key)(&actors);
let groups = actors.iter().cloned().fold(HashMap::new(), |mut acc, actor| {
acc.entry((*group_key)(&actor)).or_insert_with(HashSet::new).insert(actor.clone());
acc
});
Fleet { drivers, vehicles, profiles, actors, groups }
}
}
impl Debug for Fleet {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct(short_type_name::<Self>())
.field("vehicles", &self.vehicles.len())
.field("drivers", &self.drivers.len())
.field("profiles", &self.profiles.len())
.field("actors", &self.actors.len())
.field("groups", &self.groups.len())
.finish()
}
}
impl PartialEq<Actor> for Actor {
fn eq(&self, other: &Actor) -> bool {
std::ptr::eq(self, other)
}
}
impl Eq for Actor {}
impl Hash for Actor {
fn hash<H: Hasher>(&self, state: &mut H) {
let address = self as *const Actor;
address.hash(state);
}
}