use crate::{
raptor::{MAX_ROUNDS, Parent, ServingRoute, Target, Update},
repository::Repository,
shared::{Time, time},
};
use bitvec::prelude::*;
use std::mem;
pub struct Allocator {
pub(crate) tau_star: Vec<Option<Time>>,
pub(crate) marked_stops: BitVec<usize, Lsb0>,
pub(crate) active: Vec<u32>,
pub(crate) active_mask: BitVec<usize, Lsb0>,
pub(crate) prev_labels: Vec<Option<Time>>,
pub(crate) curr_labels: Vec<Option<Time>>,
pub(crate) parents: Vec<Option<Parent>>,
pub(crate) updates: Vec<Update>,
pub(crate) stop_count: usize,
pub(crate) routes_serving_stops: Vec<ServingRoute>,
pub(crate) target: Target,
pub(crate) round: usize,
}
impl Allocator {
pub fn new(repository: &Repository) -> Self {
Self {
tau_star: vec![None; repository.stops.len()],
marked_stops: bitvec!(usize, Lsb0; 0; repository.stops.len()),
prev_labels: vec![None; repository.stops.len()],
curr_labels: vec![None; repository.stops.len()],
parents: vec![None; repository.stops.len() * MAX_ROUNDS],
updates: Vec::with_capacity(1024),
active: vec![u32::MAX; repository.raptor_routes.len()],
active_mask: bitvec!(usize, Lsb0; 0; repository.raptor_routes.len()),
stop_count: repository.stops.len(),
routes_serving_stops: Vec::with_capacity(64),
target: Target::new(),
round: 0,
}
}
pub fn reset(&mut self) {
self.tau_star.fill(None);
self.marked_stops.fill(false);
self.prev_labels.fill(None);
self.curr_labels.fill(None);
self.parents.fill(None);
self.active.fill(u32::MAX);
self.active_mask.fill(false);
self.updates.clear();
self.routes_serving_stops.clear();
self.target.clear();
self.round = 0;
}
pub(crate) fn run_updates(&mut self) {
self.updates.iter().for_each(|update| {
let best_time = self.tau_star[update.stop_idx as usize].unwrap_or(time::MAX);
if update.arrival_time < best_time {
self.curr_labels[update.stop_idx as usize] = Some(update.arrival_time);
self.parents[flat_matrix(self.round, update.stop_idx as usize, self.stop_count)] =
Some(update.parent);
self.tau_star[update.stop_idx as usize] = Some(update.arrival_time);
self.marked_stops.set(update.stop_idx as usize, true);
}
});
self.updates.clear();
}
pub(crate) fn run_updates_reverse(&mut self) {
self.updates.iter().for_each(|update| {
let best_time = self.tau_star[update.stop_idx as usize].unwrap_or(time::MIN);
if update.arrival_time > best_time {
self.curr_labels[update.stop_idx as usize] = Some(update.arrival_time);
self.parents[flat_matrix(self.round, update.stop_idx as usize, self.stop_count)] =
Some(update.parent);
self.tau_star[update.stop_idx as usize] = Some(update.arrival_time);
self.marked_stops.set(update.stop_idx as usize, true);
}
});
self.updates.clear();
}
pub(crate) fn get_parents(&self, round: usize) -> &[Option<Parent>] {
let offset = self.stop_count * round;
&self.parents[offset..offset + self.stop_count]
}
pub(crate) fn swap_labels(&mut self) {
mem::swap(&mut self.curr_labels, &mut self.prev_labels);
self.curr_labels.fill(None);
}
pub(crate) fn next_round(&mut self) {
self.round += 1;
}
}
pub struct LazyBuffer<T> {
buffer: Option<Vec<T>>,
capacity: usize,
}
impl<T> LazyBuffer<T> {
pub fn new(capacity: usize) -> Self {
Self {
buffer: None,
capacity,
}
}
pub fn push(&mut self, value: T) {
if let Some(buffer) = &mut self.buffer {
buffer.push(value);
} else {
let mut buffer = Vec::with_capacity(self.capacity);
buffer.push(value);
self.buffer = Some(buffer);
}
}
pub fn take(mut self) -> Option<Vec<T>> {
self.buffer.take()
}
pub fn swap(&mut self) -> Vec<T> {
self.buffer.take().unwrap_or_default()
}
}
#[inline(always)] pub(crate) fn flat_matrix(outer: usize, inner: usize, count: usize) -> usize {
(outer * count) + inner
}
#[test]
fn flat_matrix_test() {
let a = flat_matrix(0, 0, 10);
let b = flat_matrix(0, 1, 10);
assert_eq!(a + 1, b);
let a = flat_matrix(1, 0, 10);
let b = flat_matrix(1, 1, 10);
assert_eq!(a + 1, b);
let a = flat_matrix(2, 0, 10);
let b = flat_matrix(2, 1, 10);
assert_eq!(a + 1, b);
let a = flat_matrix(0, 0, 10);
let b = flat_matrix(1, 0, 10);
assert_eq!(a + 10, b);
}