Skip to content

Commit

Permalink
Handle plan_units in Model::from(input)
Browse files Browse the repository at this point in the history
  • Loading branch information
cnpryer committed Jan 18, 2025
1 parent 21f0428 commit 8da512f
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 51 deletions.
28 changes: 3 additions & 25 deletions crates/solver-vrp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// - Store references to `Stop`s in `Model`. `PlanUnit` and `Vehicle` shouldn't need copies of each `Stop` if they aren't modified.
// - Implement traits for interfaces like `PlanUnit`s with different implementations, operators, expressions, etc.
// - Reference parsed input data directly in `Input`.
// - Focusing on ["stop-id"] precedence inputs for stops.
// - Focusing on {"count": Number::Integer} quantity inputs for stops.
// - Focusing on ["stop-id"] single-precedence inputs for stops.
// - Focusing on {"count": i64} quantity inputs for stops.
// - Focusing on ["date", "date"] start time window inputs for stops.
// - Focusing on `u64` [epoch seconds, epoch seconds] as a fixed start and end time for start time window inputs for stops.
// - Focusing on default `Number` and `Float` parsing.
Expand All @@ -19,29 +19,7 @@ use solution::Solution;
mod model;
mod schema;
mod solution;

type Id = String;
type Index = usize;

enum Number {
Integer,
Float(Float),
}

#[derive(Clone, Copy)]
enum Float {
F64(f64),
F32(f32),
}

impl From<Float> for f64 {
fn from(value: Float) -> f64 {
match value {
Float::F64(it) => it,
Float::F32(it) => it as f64,
}
}
}
mod types;

struct Solver {
model: Model,
Expand Down
85 changes: 62 additions & 23 deletions crates/solver-vrp/src/model.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

use crate::{schema::Input, Id, Index};
use crate::{schema::Input, types::Float};
use types::{Id, Index};

pub struct Model {
stops: Stops,
Expand Down Expand Up @@ -28,19 +29,53 @@ impl Model {

impl From<Input> for Model {
fn from(input: Input) -> Self {
let mut stops = Stops(Vec::with_capacity(input.stops.len()));
let mut stop_map = HashMap::with_capacity(input.stops.len());
let stop_count = input.stops.len();
let mut stops_vec = Vec::with_capacity(stop_count);
let mut stop_map = HashMap::with_capacity(stop_count);

for (index, stop) in input.stops.iter().enumerate() {
stops.push(Stop {
let model_stop = Stop {
id: stop.id.clone(),
index,
location: Location {
latitude: stop.location.lat.into(),
longitude: stop.location.lon.into(),
latitude: stop.location.lat,
longitude: stop.location.lon,
},
});
stop_map.insert(&stop.id, index);
};

stop_map.insert(stop.id.as_str(), index);
stops_vec.push(model_stop);
}

let mut plan_units = PlanUnits::new();
let mut plan_unit_set = HashSet::with_capacity(stop_count);

for (index, stop) in input.stops.iter().enumerate() {
if plan_unit_set.contains(&index) {
continue;
}

let mut plan_unit = PlanUnit {
index: plan_units.len(),
stops: vec![index],
};

// Currently only one pickup and one delivery stop is supported.
if stop.precedes.len() > 1 {
panic!("stop {} has too many precedes", stop.id);
}

if let Some(id) = stop.precedes.first() {
let next_index = *stop_map.get(id.as_str()).expect("stop precedes not found");
if plan_unit_set.contains(&next_index) {
panic!("stop {} is already part of a plan unit", id);
}
plan_unit.stops.push(next_index);
plan_unit_set.insert(next_index);
}

plan_unit_set.insert(index);
plan_units.push(plan_unit);
}

let vehicles = Vehicles(
Expand All @@ -55,23 +90,19 @@ impl From<Input> for Model {
.initial_stops
.iter()
.map(|stop| {
stops
.get(
*stop_map
.get(&stop.id)
.expect("initial stop not found in stops"),
)
.unwrap()
.clone()
let stop_index = *stop_map
.get(stop.id.as_str())
.expect("initial stop not found in stops");
stops_vec[stop_index].clone()
})
.collect(),
})
.collect(),
);

Self {
stops,
plan_units: todo!(),
stops: Stops(stops_vec),
plan_units,
vehicles,
}
}
Expand All @@ -83,19 +114,27 @@ impl PlanUnits {
fn new() -> Self {
Self(Vec::new())
}

fn len(&self) -> usize {
self.0.len()
}

fn push(&mut self, plan_unit: PlanUnit) {
self.0.push(plan_unit);
}
}

pub struct PlanUnit {
index: Index,
stops: Vec<Stop>,
stops: Vec<Index>,
}

impl PlanUnit {
pub fn index(&self) -> &Index {
&self.index
}

fn stops(&self) -> &Vec<Stop> {
fn stops(&self) -> &Vec<Index> {
&self.stops
}
}
Expand Down Expand Up @@ -139,8 +178,8 @@ impl Stop {

#[derive(Clone, Copy)]
struct Location {
latitude: f64,
longitude: f64,
latitude: Float,
longitude: Float,
}

pub struct Vehicles(Vec<Vehicle>);
Expand Down
4 changes: 2 additions & 2 deletions crates/solver-vrp/src/schema.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::collections::HashMap;

use crate::{Float, Id, Number};
use types::{Float, Id, Number};

pub struct Input {
pub stops: Vec<Stop>,
pub vehicles: Vec<Vehicle>,
pub distance_matrix: Vec<Vec<f64>>,
pub distance_matrix: Vec<Vec<Number>>,
pub options: Option<()>,
}

Expand Down
2 changes: 1 addition & 1 deletion crates/solver-vrp/src/solution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;

use crate::Index;
use model::{PlanUnit as ModelPlanUnit, Stop as ModelStop};
use types::Index;

pub struct Solution {
vehicles: Vehicles,
Expand Down
17 changes: 17 additions & 0 deletions crates/solver-vrp/src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
pub type Id = String;
pub type Index = usize;

pub enum Number {
Integer(Integer),
Float(Float),
}

#[derive(Clone, Copy)]
pub enum Integer {
I64(i64),
}

#[derive(Clone, Copy)]
pub enum Float {
F64(f64),
}

0 comments on commit 8da512f

Please sign in to comment.