use std::cmp::Reverse;
use std::collections::BinaryHeap;
use fixedbitset::FixedBitSet;
use smallvec::SmallVec;
use crate::K;
use crate::Timetable;
use crate::algorithm::boarding::BoardingTree;
use crate::algorithm::boarding::Step;
use crate::algorithm::label_bag::LabelBag;
use crate::algorithm::label_bag::insert_into_bag;
use crate::ids::StopIdx;
use crate::label::Label;
use crate::time::SecondOfDay;
#[allow(clippy::too_many_arguments)]
pub(crate) fn relax_footpaths_round_closed<T: Timetable + ?Sized, L: Label>(
timetable: &T,
ctx: &L::Ctx,
k: K,
labels: &mut [Vec<LabelBag<L>>],
best_arrival: &mut [LabelBag<L>],
board_detail: &mut BoardingTree,
sources: &FixedBitSet,
targets: &[(StopIdx, crate::time::Duration)],
out: &mut Vec<StopIdx>,
ever_reached: &mut FixedBitSet,
) {
let mut staged: SmallVec<[L; 8]> = SmallVec::new();
for stop_bit in sources.ones() {
let stop = StopIdx::new(stop_bit as u32);
if labels[k][stop.idx()].is_empty() {
continue;
}
staged.clear();
staged.extend(labels[k][stop.idx()].iter().copied());
for &p_dash in timetable.get_footpaths_from(stop) {
let walk = timetable.get_transfer_time(stop, p_dash);
for source_label in &staged {
let via_walk = source_label.extend_by_footpath(ctx, stop, p_dash, walk);
insert_into_bag(
labels,
best_arrival,
board_detail,
out,
ever_reached,
targets,
k,
p_dash,
via_walk,
Step::Walked {
from: stop,
parent_arrival: source_label.arrival(),
},
);
}
}
}
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn relax_footpaths_round<T: Timetable + ?Sized, L: Label>(
timetable: &T,
ctx: &L::Ctx,
k: K,
labels: &mut [Vec<LabelBag<L>>],
best_arrival: &mut [LabelBag<L>],
board_detail: &mut BoardingTree,
sources: &FixedBitSet,
targets: &[(StopIdx, crate::time::Duration)],
out: &mut Vec<StopIdx>,
heap: &mut BinaryHeap<Reverse<(SecondOfDay, u32)>>,
ever_reached: &mut FixedBitSet,
) {
heap.clear();
for bit in sources.ones() {
let min_arr = labels[k][bit].min_arrival();
if min_arr != SecondOfDay::MAX {
heap.push(Reverse((min_arr, bit as u32)));
}
}
let mut staged: SmallVec<[L; 8]> = SmallVec::new();
while let Some(Reverse((arrival, stop_bit))) = heap.pop() {
let stop = StopIdx::new(stop_bit);
let stop_min = labels[k][stop.idx()].min_arrival();
if arrival > stop_min {
continue;
}
staged.clear();
staged.extend(labels[k][stop.idx()].iter().copied());
for &p_dash in timetable.get_footpaths_from(stop) {
let walk = timetable.get_transfer_time(stop, p_dash);
let mut any_added = false;
for source_label in &staged {
let via_walk = source_label.extend_by_footpath(ctx, stop, p_dash, walk);
if insert_into_bag(
labels,
best_arrival,
board_detail,
out,
ever_reached,
targets,
k,
p_dash,
via_walk,
Step::Walked {
from: stop,
parent_arrival: source_label.arrival(),
},
) {
any_added = true;
}
}
if any_added {
heap.push(Reverse((
labels[k][p_dash.idx()].min_arrival(),
p_dash.get(),
)));
}
}
}
}