use fixedbitset::FixedBitSet;
use smallvec::SmallVec;
use crate::K;
use crate::algorithm::boarding::BoardingTree;
use crate::algorithm::boarding::Step;
use crate::ids::StopIdx;
use crate::label::Label;
use crate::time::SecondOfDay;
#[derive(Debug, Clone)]
pub(crate) struct LabelBag<L: Label> {
items: SmallVec<[L; 8]>,
}
impl<L: Label> LabelBag<L> {
pub(crate) fn new() -> Self {
Self {
items: SmallVec::new(),
}
}
pub(crate) fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub(crate) fn iter(&self) -> impl Iterator<Item = &L> {
self.items.iter()
}
pub(crate) fn insert(&mut self, new: L) -> bool {
for item in &self.items {
if item.dominates(&new) {
return false;
}
}
self.items.retain(|item| !new.dominates(item));
self.items.push(new);
true
}
pub(crate) fn min_arrival(&self) -> SecondOfDay {
self.items
.iter()
.map(|l| l.arrival())
.min()
.unwrap_or(SecondOfDay::MAX)
}
pub(crate) fn dominates_label(&self, candidate: &L) -> bool {
self.items.iter().any(|item| item.dominates(candidate))
}
pub(crate) fn clear(&mut self) {
self.items.clear();
}
}
impl<L: Label> Default for LabelBag<L> {
fn default() -> Self {
Self::new()
}
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn insert_into_bag<L: Label>(
labels: &mut [Vec<LabelBag<L>>],
best_arrival: &mut [LabelBag<L>],
board_detail: &mut BoardingTree,
out: &mut Vec<StopIdx>,
ever_reached: &mut FixedBitSet,
targets: &[(StopIdx, crate::time::Duration)],
k: K,
stop: StopIdx,
label: L,
step: Step,
) -> bool {
if all_targets_dominate(best_arrival, targets, &label) {
return false;
}
let added = labels[k][stop.idx()].insert(label);
if !added {
return false;
}
board_detail.insert((k, stop, label.arrival()), step);
best_arrival[stop.idx()].insert(label);
ever_reached.insert(stop.idx());
out.push(stop);
true
}
pub(crate) fn all_targets_dominate<L: Label>(
best_arrival: &[LabelBag<L>],
targets: &[(StopIdx, crate::time::Duration)],
label: &L,
) -> bool {
!targets.is_empty()
&& targets
.iter()
.all(|&(t, _)| best_arrival[t.idx()].dominates_label(label))
}