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

Rounded time at start #115

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions include/nigiri/routing/raptor/reconstruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,10 @@ void optimize_footpaths(timetable const&,
query const&,
journey&);

template <direction SearchDir>
void correct_rounded_time_at_start(timetable const&,
rt_timetable const*,
query const&,
journey&);

} // namespace nigiri::routing
5 changes: 4 additions & 1 deletion include/nigiri/routing/start_times.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ struct rt_timetable;

namespace nigiri::routing {

static constexpr auto const kDefaultRoundTo = 2U;

struct start {
CISTA_FRIEND_COMPARABLE(start)
unixtime_t time_at_start_;
Expand All @@ -32,7 +34,8 @@ void get_starts(direction,
bool use_start_footpaths,
std::vector<start>&,
bool add_ontrip,
profile_idx_t);
profile_idx_t,
std::uint16_t round_to = kDefaultRoundTo);

void collect_destinations(timetable const&,
std::vector<offset> const& destinations,
Expand Down
2 changes: 2 additions & 0 deletions src/routing/raptor/reconstruct.cc
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ void reconstruct_journey(timetable const& tt,
}
}

correct_rounded_time_at_start<SearchDir>(tt, rtt, q, j);

optimize_footpaths<SearchDir>(tt, rtt, q, j);

#if defined(NIGIRI_TRACE_RECUSTRUCT)
Expand Down
66 changes: 66 additions & 0 deletions src/routing/raptor/rounded_time_at_start.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "nigiri/routing/raptor/reconstruct.h"

#include "nigiri/routing/journey.h"
#include "nigiri/routing/query.h"
#include "nigiri/rt/frun.h"
#include "nigiri/timetable.h"

namespace nigiri::routing {

template <direction SearchDir>
void correct_rounded_time_at_start(timetable const& tt,
rt_timetable const* rtt,
query const& q,
journey& j) {
if constexpr (SearchDir == direction::kForward) {
if (q.start_match_mode_ == location_match_mode::kIntermodal) {
if (j.legs_.size() >= 2 && holds_alternative<offset>(j.legs_[0].uses_) &&
holds_alternative<journey::run_enter_exit>(j.legs_[1].uses_)) {
auto const rounding_error = j.legs_[1].dep_time_ - j.legs_[0].arr_time_;
j.legs_[0].dep_time_ += rounding_error;
j.legs_[0].arr_time_ += rounding_error;
j.start_time_ += rounding_error;
}
} else { // start at station
if (!j.legs_.empty() &&
holds_alternative<journey::run_enter_exit>(j.legs_[0].uses_)) {
auto const ree = get<journey::run_enter_exit>(j.legs_[0].uses_);
auto const fr = rt::frun{tt, rtt, ree.r_};
auto const t_actual = fr[ree.stop_range_.from_].time(event_type::kDep);
j.legs_[0].dep_time_ = t_actual;
j.start_time_ = t_actual;
}
}
} else { // SearchDir == direction::kBackward
if (q.start_match_mode_ == location_match_mode::kIntermodal) {
if (j.legs_.size() >= 2 &&
holds_alternative<offset>(rbegin(j.legs_)[0].uses_) &&
holds_alternative<journey::run_enter_exit>(
rbegin(j.legs_)[1].uses_)) {
auto const rounding_error =
rbegin(j.legs_)[0].dep_time_ - rbegin(j.legs_)[1].arr_time_;
rbegin(j.legs_)[0].dep_time_ -= rounding_error;
rbegin(j.legs_)[0].arr_time_ -= rounding_error;
j.start_time_ -= rounding_error;
}
} else { // start at station
if (!j.legs_.empty() && holds_alternative<journey::run_enter_exit>(
rbegin(j.legs_)[0].uses_)) {
auto const ree = get<journey::run_enter_exit>(rbegin(j.legs_)[0].uses_);
auto const fr = rt::frun{tt, rtt, ree.r_};
auto const t_actual =
fr[ree.stop_range_.to_ - 1].time(event_type::kArr);
j.legs_.back().arr_time_ = t_actual;
j.start_time_ = t_actual;
}
}
}
}

template void correct_rounded_time_at_start<direction::kForward>(
timetable const&, rt_timetable const*, query const&, journey&);

template void correct_rounded_time_at_start<direction::kBackward>(
timetable const&, rt_timetable const*, query const&, journey&);

} // namespace nigiri::routing
52 changes: 35 additions & 17 deletions src/routing/start_times.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,34 @@ void trace_start(char const* fmt_str, Args... args) {
}
}

unixtime_t rounded_time_at_start(unixtime_t const event_time,
duration_t const offset_time,
direction const search_dir,
interval<unixtime_t> const& interval,
std::uint16_t const round_to) {
auto const time_at_start = search_dir == direction::kForward
? event_time - offset_time
: event_time + offset_time;
return interval.clamp(unixtime_t{i32_minutes{
(time_at_start.time_since_epoch().count() / round_to) * round_to +
(search_dir == direction::kBackward &&
time_at_start.time_since_epoch().count() % round_to != 0
? round_to
: 0)}});
}

void add_start_times_at_stop(direction const search_dir,
timetable const& tt,
rt_timetable const* rtt,
route_idx_t const route_idx,
stop_idx_t const stop_idx,
location_idx_t const location_idx,
interval<unixtime_t> const& interval_with_offset,
interval<unixtime_t> const& interval,
duration_t const offset,
std::vector<start>& starts) {
std::vector<start>& starts,
std::uint16_t const round_to) {
auto const interval_with_offset =
search_dir == direction::kForward ? interval + offset : interval - offset;
auto const first_day_idx = tt.day_idx_mam(interval_with_offset.from_).first;
auto const last_day_idx = tt.day_idx_mam(interval_with_offset.to_).first;
trace_start(
Expand Down Expand Up @@ -57,9 +76,8 @@ void add_start_times_at_stop(direction const search_dir,
interval_with_offset.contains(tt.to_unixtime(day, stop_time_mam))) {
auto const ev_time = tt.to_unixtime(day, stop_time_mam);
auto const& s = starts.emplace_back(
start{.time_at_start_ = search_dir == direction::kForward
? ev_time - offset
: ev_time + offset,
start{.time_at_start_ = rounded_time_at_start(
ev_time, offset, search_dir, interval, round_to),
.time_at_stop_ = ev_time,
.stop_ = location_idx});
trace_start(
Expand Down Expand Up @@ -88,7 +106,8 @@ void add_starts_in_interval(direction const search_dir,
location_idx_t const l,
duration_t const d,
std::vector<start>& starts,
bool const add_ontrip) {
bool const add_ontrip,
std::uint16_t const round_to) {
trace_start(
" add_starts_in_interval(interval={}, stop={}, duration={}): {} "
"routes\n",
Expand Down Expand Up @@ -124,9 +143,7 @@ void add_starts_in_interval(direction const search_dir,
trace_start(" -> no skip -> add_start_times_at_stop()\n");
add_start_times_at_stop(
search_dir, tt, rtt, r, static_cast<stop_idx_t>(i),
stop{s}.location_idx(),
search_dir == direction::kForward ? interval + d : interval - d, d,
starts);
stop{s}.location_idx(), interval, d, starts, round_to);
}
}

Expand All @@ -153,11 +170,11 @@ void add_starts_in_interval(direction const search_dir,
rt_t, static_cast<stop_idx_t>(i),
(search_dir == direction::kForward ? event_type::kDep
: event_type::kArr));
auto const& inserted = starts.emplace_back(start{
.time_at_start_ =
search_dir == direction::kForward ? ev_time - d : ev_time + d,
.time_at_stop_ = ev_time,
.stop_ = l});
auto const& inserted = starts.emplace_back(
start{.time_at_start_ = rounded_time_at_start(
ev_time, d, search_dir, interval, round_to),
.time_at_stop_ = ev_time,
.stop_ = l});
trace_start(
" => ADD RT START: time_at_start={}, time_at_stop={}, "
"stop={}\n",
Expand Down Expand Up @@ -193,7 +210,8 @@ void get_starts(direction const search_dir,
bool const use_start_footpaths,
std::vector<start>& starts,
bool const add_ontrip,
profile_idx_t const prf_idx) {
profile_idx_t const prf_idx,
std::uint16_t const round_to) {
hash_map<location_idx_t, duration_t> shortest_start;

auto const update = [&](location_idx_t const l, duration_t const d) {
Expand Down Expand Up @@ -221,7 +239,7 @@ void get_starts(direction const search_dir,
std::visit(utl::overloaded{[&](interval<unixtime_t> const interval) {
add_starts_in_interval(search_dir, tt, rtt,
interval, l, o, starts,
add_ontrip);
add_ontrip, round_to);
},
[&](unixtime_t const t) {
starts.emplace_back(
Expand Down Expand Up @@ -267,4 +285,4 @@ void collect_destinations(timetable const& tt,
}
}

} // namespace nigiri::routing
} // namespace nigiri::routing
2 changes: 1 addition & 1 deletion test/routing/rt_routing_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ TEST(routing, rt_raptor_forward) {
EXPECT_EQ(std::string_view{fwd_journeys}, ss.str());
}

constexpr auto const bwd_journeys = R"([2019-05-02 23:00, 2019-05-03 02:00]
constexpr auto const bwd_journeys = R"([2019-05-02 23:00, 2019-05-03 01:00]
TRANSFERS: 1
FROM: (A, A) [2019-05-02 23:00]
TO: (D, D) [2019-05-03 01:00]
Expand Down
Loading
Loading