Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reached à la Trip-based #134

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
Draft
27 changes: 24 additions & 3 deletions include/nigiri/routing/pareto_set.h
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
#pragma once

#include <cinttypes>
#include <concepts>
#include <tuple>
#include <vector>

namespace nigiri {

template <typename T>
concept HasDominates = requires(T x) {
{ x.dominates(x) } -> std::convertible_to<bool>;
};

template <typename T>
struct pareto_set {
using iterator = typename std::vector<T>::iterator;
using const_iterator = typename std::vector<T>::const_iterator;

size_t size() const { return els_.size(); }

std::tuple<bool, iterator, iterator> add(T&& el) {
std::tuple<bool, iterator, iterator> add(T&& el)
requires HasDominates<T>
{
return add_with_fn(std::move(el),
[](auto&& a, auto&& b) { return a.dominates(b); });
}

template <typename Fn>
std::tuple<bool, iterator, iterator> add(T&& el, Fn&& dominates)
requires(!HasDominates<T>)
{
return add_with_fn(std::move(el), std::forward<Fn>(dominates));
}

template <typename Fn>
std::tuple<bool, iterator, iterator> add_with_fn(T&& el, Fn&& dominates) {
auto n_removed = std::size_t{0};
for (auto i = 0U; i < els_.size(); ++i) {
if (els_[i].dominates(el)) {
if (dominates(els_[i], el)) {
return {false, end(), std::next(begin(), i)};
}
if (el.dominates(els_[i])) {
if (dominates(el, els_[i])) {
n_removed++;
continue;
}
Expand Down
19 changes: 19 additions & 0 deletions include/nigiri/routing/raptor/printable_transport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <ostream>

#include "nigiri/timetable.h"

namespace nigiri::routing {

struct pt {
friend std::ostream& operator<<(std::ostream& out, pt const& pt) {
out << "(src=" << pt.tt_.dbg(pt.t_.t_idx_)
<< ", name=" << pt.tt_.transport_name(pt.t_.t_idx_) << ")";
return out;
}
timetable const& tt_;
transport t_;
};

} // namespace nigiri::routing
63 changes: 44 additions & 19 deletions include/nigiri/routing/raptor/raptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "nigiri/special_stations.h"
#include "nigiri/timetable.h"
#include "nigiri/types.h"
#include "printable_transport.h"

namespace nigiri::routing {

Expand Down Expand Up @@ -102,6 +103,9 @@ struct raptor {
for (auto const& [l, _] : td_dist_to_end_) {
state_.end_reachable_.set(to_idx(l), true);
}
for (auto& r : state_.r_.route_transport_stops_) {
r.clear();
}
}

algo_stats_t get_stats() const { return stats_; }
Expand Down Expand Up @@ -144,7 +148,7 @@ struct raptor {

trace_print_init_state();

for (auto k = 1U; k != end_k; ++k) {
for (auto k = std::uint8_t{1U}; k != end_k; ++k) {
for (auto i = 0U; i != n_locations_; ++i) {
for (auto v = 0U; v != Vias + 1; ++v) {
best_[i][v] = get_best(round_times_[k][i][v], best_[i][v]);
Expand Down Expand Up @@ -243,7 +247,7 @@ struct raptor {
}

template <bool WithClaszFilter, bool WithBikeFilter>
bool loop_routes(unsigned const k) {
bool loop_routes(std::uint8_t const k) {
auto any_marked = false;
state_.route_mark_.for_each_set_bit([&](auto const r_idx) {
auto const r = route_idx_t{r_idx};
Expand Down Expand Up @@ -712,7 +716,7 @@ struct raptor {
}

template <bool WithSectionBikeFilter>
bool update_route(unsigned const k, route_idx_t const r) {
bool update_route(std::uint8_t const k, route_idx_t const r) {
auto const stop_seq = tt_.route_location_seq_[r];
bool any_marked = false;

Expand Down Expand Up @@ -801,22 +805,38 @@ struct raptor {
is_better(by_transport, higher_v_best) &&
lb_[l_idx] != kUnreachable &&
is_better(by_transport + dir(lb_[l_idx]), time_at_dest_[k])) {
trace_upd(
"┊ │k={} v={}->{} name={}, dbg={}, time_by_transport={}, "
"BETTER THAN current_best={} => update, {} marking station "
"{}!\n",
k, v, target_v, tt_.transport_name(et[v].t_idx_),
tt_.dbg(et[v].t_idx_), to_unix(by_transport),
to_unix(current_best[v]),
!is_better(by_transport, current_best[v]) ? "NOT" : "",
location{tt_, stp.location_idx()});

++stats_.n_earliest_arrival_updated_by_route_;
tmp_[l_idx][target_v] =
get_best(by_transport, tmp_[l_idx][target_v]);
state_.station_mark_.set(l_idx, true);
current_best[v] = by_transport;
any_marked = true;

auto const st = sorted_transport{base_, et[v]};
auto const [added, inserted_it, dominated_by_it] =
state_.r_.add<SearchDir>(r, st, stop_idx, k);
if (added) {

trace_upd(
"┊ │k={} v={}->{} name={}, dbg={}, time_by_transport={}, "
"BETTER THAN current_best={} => update, {} marking station "
"{}!\n",
k, v, target_v, tt_.transport_name(et[v].t_idx_),
tt_.dbg(et[v].t_idx_), to_unix(by_transport),
to_unix(current_best[v]),
!is_better(by_transport, current_best[v]) ? "NOT" : "",
location{tt_, stp.location_idx()});

++stats_.n_earliest_arrival_updated_by_route_;
tmp_[l_idx][target_v] =
get_best(by_transport, tmp_[l_idx][target_v]);
state_.station_mark_.set(l_idx, true);
current_best[v] = by_transport;
any_marked = true;
} else {
trace(
"┊ │k={} *** NO REACH: "
" INSERT=(stop_idx={}, k={}, t={}), "
"DOMINATED_BY=(stop_idx={}, k={}, t={})!\n",
k, //
stop_idx, k, pt{tt_, et}, //
dominated_by_it->stop_idx_, dominated_by_it->k_,
pt{tt_, dominated_by_it->t_.get_transport(base_)});
}
} else {
trace(
"┊ │k={} v={}->{} *** NO UPD: at={}, name={}, dbg={}, "
Expand Down Expand Up @@ -901,6 +921,11 @@ struct raptor {
}
}
}

if (any_marked) {
state_.r_.activate(r);
}

return any_marked;
}

Expand Down
2 changes: 2 additions & 0 deletions include/nigiri/routing/raptor/raptor_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "cista/containers/flat_matrix.h"

#include "nigiri/common/delta_t.h"
#include "nigiri/routing/raptor/transport_stop.h"
#include "nigiri/common/flat_matrix_view.h"
#include "nigiri/routing/limits.h"

Expand Down Expand Up @@ -83,6 +84,7 @@ struct raptor_state {
bitvec route_mark_;
bitvec rt_transport_mark_;
bitvec end_reachable_;
reached r_;
};

} // namespace nigiri::routing
111 changes: 111 additions & 0 deletions include/nigiri/routing/raptor/transport_stop.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#pragma once

#include <cstdint>

#include "nigiri/routing/pareto_set.h"
#include "nigiri/types.h"

namespace nigiri::routing {

struct sorted_transport {
sorted_transport() noexcept = default;

sorted_transport(day_idx_t const base, transport const& t) noexcept
: day_idx_{static_cast<std::int32_t>(to_idx(t.day_)) -
static_cast<std::int32_t>(to_idx(base))},
t_idx_{static_cast<std::int32_t>(to_idx(t.t_idx_))} {}

bool operator<=(sorted_transport const& o) const noexcept {
return day_idx_ < o.day_idx_ ||
(day_idx_ == o.day_idx_ && t_idx_ <= o.t_idx_);
}

bool operator>=(sorted_transport const& o) const noexcept {
return day_idx_ > o.day_idx_ ||
(day_idx_ == o.day_idx_ && t_idx_ >= o.t_idx_);
}

transport get_transport(day_idx_t const base) const noexcept {
return {
.t_idx_ = transport_idx_t{t_idx_},
.day_ = day_idx_t{static_cast<std::int32_t>(to_idx(base)) + day_idx_}};
}

std::int32_t day_idx_ : 4;
std::int32_t t_idx_ : 28;
};

struct transport_stop {
template <direction SeachDir>
bool dominates(transport_stop const& o) const noexcept {
return active_ >= o.active_ &&
(SeachDir == direction::kForward ? t_ <= o.t_ : t_ >= o.t_) &&
(SeachDir == direction::kForward ? stop_idx_ <= o.stop_idx_
: stop_idx_ >= o.stop_idx_) &&
k_ <= o.k_;
}

sorted_transport t_;
stop_idx_t stop_idx_;
std::uint8_t k_;
bool active_{false};
};

struct reached {
template <direction SearchDir>
stop_idx_t get_stop(day_idx_t const base,
route_idx_t const r,
transport const x,
std::uint8_t const k) {
auto const t = sorted_transport{base, x};
if constexpr (SearchDir == direction::kForward) {
auto best = std::numeric_limits<stop_idx_t>::max();
for (auto const& re : route_transport_stops_[r]) {
if (k < re.k_) {
continue;
}
if (re.t_ <= t && re.stop_idx_ < best) {
best = re.stop_idx_;
}
}
return best;
} else {
auto best = std::numeric_limits<stop_idx_t>::min();
for (auto const& re : route_transport_stops_[r]) {
if (k < re.k_) {
continue;
}
if (re.t_ >= t && re.stop_idx_ > best) {
best = re.stop_idx_;
}
}
return best;
}
}

template <direction SearchDir>
auto add(route_idx_t const r,
sorted_transport const t,
stop_idx_t const stop_idx,
std::uint8_t const k) {
auto const x = route_transport_stops_[r].add(
transport_stop{
.t_ = t, .stop_idx_ = stop_idx, .k_ = k, .active_ = true},
[](auto&& a, auto&& b) { return a.template dominates<SearchDir>(b); });
auto const& [added, inserted_it, dominated_by_it] = x;
if (added) {
inserted_it->active_ = false;
}
return x;
}

void activate(route_idx_t const r) {
for (auto& x : route_transport_stops_[r]) {
x.active_ = true;
}
}

vector_map<route_idx_t, pareto_set<transport_stop>> route_transport_stops_;
};

} // namespace nigiri::routing
1 change: 1 addition & 0 deletions src/routing/raptor/raptor_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ raptor_state& raptor_state::resize(unsigned const n_locations,
prev_station_mark_.resize(n_locations);
route_mark_.resize(n_routes);
rt_transport_mark_.resize(n_rt_transports);
r_.route_transport_stops_.resize(n_routes);
end_reachable_.resize(n_locations);
return *this;
}
Expand Down
Loading