Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
felixguendling committed Jul 27, 2024
1 parent 8d72c11 commit 85f3f25
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 72 deletions.
8 changes: 4 additions & 4 deletions .pkg.lock
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
11431135496283738053
cista a25863155854a0a5555f7ce24b90d325780c0dd4
12357460146014801189
cista f4dbe8e20edd7a2ad08e934295154013dfc723f5
zlib fe8e13ffca867612951bc6baf114e5ac8b00f305
boost be5235eb2258d2ec19e32546ab767a62311d9b46
res 7d97784ba785ce8a2677ea77164040fde484fb04
date 646ba5e2e76636d9e65aaa3cf32e3e3a43defa2c
date d84b23ca2432e17f3f04a3e0cc96b096b99c39a2
fmt 09e6cf8fa61ff44509595005631f9da5d917ed3f
doctest 70e8f76437b76dd5e9c0a2eb9b907df190ab71a0
geo ee76668f0f0454e4acd3c769e00c6868620e3490
Expand All @@ -12,5 +12,5 @@ miniz 1edbdece9d71dc65c6ff405572ee37cbdcef7af4
abseil-cpp ba5240842d352b4b67a32092453a2fe5fe53a62e
protobuf d8136b9c6a62db6ce09900ecdeb82bb793096cbd
unordered_dense 77e91016354e6d8cba24a86c5abb807de2534c02
utl fd7425b1a57a4b887318ba8c41a3184f8c4a50c5
utl 80df7a6f1e2de4d290c48e9218d48eb9792b7289
wyhash 1e012b57fc2227a9e583a57e2eacb3da99816d99
5 changes: 3 additions & 2 deletions include/nigiri/routing/query.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "nigiri/routing/clasz_mask.h"
#include "nigiri/routing/limits.h"
#include "nigiri/routing/location_match_mode.h"
#include "nigiri/td_footpath.h"
#include "nigiri/types.h"

namespace nigiri::routing {
Expand Down Expand Up @@ -46,8 +47,8 @@ struct query {
location_match_mode dest_match_mode_{
nigiri::routing::location_match_mode::kExact};
bool use_start_footpaths_{true};
std::vector<offset> start_{};
std::vector<offset> destination_{};
std::vector<offset> start_{}, destination_{};
std::vector<td_footpath> td_start_{}, td_destination_{};
std::uint8_t max_transfers_{kMaxTransfers};
unsigned min_connection_count_{0U};
bool extend_interval_earlier_{false};
Expand Down
11 changes: 5 additions & 6 deletions include/nigiri/routing/search.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,11 @@ struct search {
void add_start_labels(start_time_t const& start_interval,
bool const add_ontrip) {
state_.starts_.reserve(500'000);
get_starts(SearchDir, tt_, rtt_, start_interval, q_.start_,
q_.start_match_mode_, q_.use_start_footpaths_, state_.starts_,
add_ontrip, q_.prf_idx_);
std::sort(
begin(state_.starts_), end(state_.starts_),
[&](start const& a, start const& b) { return kFwd ? b < a : a < b; });
get_starts(tt_, rtt_, SearchDir, q_, start_interval, add_ontrip,
state_.starts_);
utl::sort(state_.starts_, [&](start const& a, start const& b) {
return kFwd ? b < a : a < b;
});
}

void remove_ontrip_results() {
Expand Down
13 changes: 5 additions & 8 deletions include/nigiri/routing/start_times.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,13 @@ struct start {
location_idx_t stop_;
};

void get_starts(direction,
timetable const&,
void get_starts(timetable const&,
rt_timetable const*,
start_time_t const& start_time,
std::vector<offset> const& station_offsets,
location_match_mode,
bool use_start_footpaths,
std::vector<start>&,
direction,
query const&,
start_time_t const&,
bool add_ontrip,
profile_idx_t);
std::vector<start>&);

void collect_destinations(timetable const&,
std::vector<offset> const& destinations,
Expand Down
178 changes: 133 additions & 45 deletions src/routing/start_times.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "nigiri/rt/rt_timetable.h"
#include "nigiri/special_stations.h"
#include "utl/enumerate.h"
#include "utl/equal_ranges_linear.h"
#include "utl/get_or_create.h"
#include "utl/overloaded.h"

Expand All @@ -18,14 +19,61 @@ void trace_start(char const* fmt_str, Args... args) {
}
}

using offset_t = std::variant<duration_t, std::span<td_footpath const>>;

duration_t get_min(offset_t const o) {
return std::visit(utl::overloaded{[](duration_t const x) { return x; },
[&](std::span<td_footpath const> td) {
return std::min_element(
begin(td), end(td),
[](auto&& a, auto&& b) {
return a.duration_ <
b.duration_;
})
->duration_;
}},
o);
}

duration_t get_max(offset_t const o) {
return std::visit(utl::overloaded{[](duration_t const x) { return x; },
[&](std::span<td_footpath const> td) {
return std::max_element(
begin(td), end(td),
[](auto&& a, auto&& b) {
return a.duration_ <
b.duration_;
})
->duration_;
}},
o);
}

duration_t get_offset(direction const search_dir,
offset_t const o,
unixtime_t const t) {
return std::visit(utl::overloaded{[](duration_t const x) { return x; },
[&](std::span<td_footpath const> td) {
auto duration = kInfeasible;
for_each_footpath(
search_dir, td, t,
[&](footpath const fp) {
duration = fp.duration();
return utl::cflow::kBreak;
});
return duration;
}},
o);
}

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,
duration_t const offset,
offset_t const offset,
std::vector<start>& starts) {
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;
Expand Down Expand Up @@ -56,10 +104,17 @@ void add_start_times_at_stop(direction const search_dir,
if (traffic_days.test(to_idx(day - day_offset)) &&
interval_with_offset.contains(tt.to_unixtime(day, stop_time_mam))) {
auto const ev_time = tt.to_unixtime(day, stop_time_mam);
auto const duration = get_offset(search_dir, offset, ev_time);
if (duration == kInfeasible) {
trace_start(
" => ADD START: infeasible, time_at_stop={}, stop={}\n",
ev_time, location{tt, starts.back().stop_});
continue;
}
auto const& s = starts.emplace_back(
start{.time_at_start_ = search_dir == direction::kForward
? ev_time - offset
: ev_time + offset,
? ev_time - duration
: ev_time + duration,
.time_at_stop_ = ev_time,
.stop_ = location_idx});
trace_start(
Expand All @@ -84,15 +139,15 @@ void add_start_times_at_stop(direction const search_dir,
void add_starts_in_interval(direction const search_dir,
timetable const& tt,
rt_timetable const* rtt,
interval<unixtime_t> const& interval,
interval<unixtime_t> const& iv,
location_idx_t const l,
duration_t const d,
offset_t const d,
std::vector<start>& starts,
bool const add_ontrip) {
trace_start(
" add_starts_in_interval(interval={}, stop={}, duration={}): {} "
"routes\n",
interval, location{tt, l}, // NOLINT(clang-analyzer-core.CallAndMessage)
iv, location{tt, l}, // NOLINT(clang-analyzer-core.CallAndMessage)
d, tt.location_routes_.at(l).size());

// Iterate routes visiting the location.
Expand All @@ -110,8 +165,8 @@ void add_starts_in_interval(direction const search_dir,
// Ignore:
// - in-allowed=false for forward search
// - out-allowed=false for backward search
// - entering at last stp for forward search
// - exiting at first stp for backward search
// - entering at last stop for forward search
// - exiting at first stop for backward search
if ((search_dir == direction::kBackward &&
(i == 0U || !stp.out_allowed())) ||
(search_dir == direction::kForward &&
Expand All @@ -122,11 +177,15 @@ 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);
auto const min = get_min(d);
auto const max = get_max(d);
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{iv.from_ + min, iv.to_ + max}
: interval{iv.from_ - max, iv.to_ - min},
d, starts);
}
}

Expand All @@ -153,11 +212,19 @@ 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 duration = get_offset(search_dir, d, ev_time);
if (duration == kInfeasible) {
trace_start(
" => ADD START: infeasible, time_at_stop={}, stop={}\n",
ev_time, location{tt, starts.back().stop_});
continue;
}
auto const& inserted = starts.emplace_back(
start{.time_at_start_ = search_dir == direction::kForward
? ev_time - duration
: ev_time + duration,
.time_at_stop_ = ev_time,
.stop_ = l});
trace_start(
" => ADD RT START: time_at_start={}, time_at_stop={}, "
"stop={}\n",
Expand All @@ -173,27 +240,25 @@ void add_starts_in_interval(direction const search_dir,
// departs later and arrives at the same time). These journeys outside the
// interval will be filtered out before returning the result.
if (add_ontrip) {
auto const time_at_start =
search_dir == direction::kForward ? iv.to_ : iv.from_ - 1_minutes;
auto const duration = get_offset(search_dir, d, time_at_start);
starts.emplace_back(
start{.time_at_start_ = search_dir == direction::kForward
? interval.to_
: interval.from_ - 1_minutes,
start{.time_at_start_ = time_at_start,
.time_at_stop_ = search_dir == direction::kForward
? interval.to_ + d
: interval.from_ - 1_minutes - d,
? iv.to_ + duration
: iv.from_ - 1_minutes - duration,
.stop_ = l});
}
}

void get_starts(direction const search_dir,
timetable const& tt,
void get_starts(timetable const& tt,
rt_timetable const* rtt,
direction const search_dir,
query const& q,
start_time_t const& start_time,
std::vector<offset> const& station_offsets,
location_match_mode const mode,
bool const use_start_footpaths,
std::vector<start>& starts,
bool const add_ontrip,
profile_idx_t const prf_idx) {
bool add_ontrip,
std::vector<start>& starts) {
hash_map<location_idx_t, duration_t> shortest_start;

auto const update = [&](location_idx_t const l, duration_t const d) {
Expand All @@ -202,22 +267,22 @@ void get_starts(direction const search_dir,
};

auto const fwd = search_dir == direction::kForward;
for (auto const& o : station_offsets) {
for_each_meta(tt, mode, o.target(), [&](location_idx_t const l) {
update(l, o.duration());
if (use_start_footpaths) {
auto const footpaths = fwd ? tt.locations_.footpaths_out_[prf_idx][l]
: tt.locations_.footpaths_in_[prf_idx][l];
for (auto const& fp : footpaths) {
update(fp.target(), o.duration() + fp.duration());
}
}
});
for (auto const& o : q.start_) {
for_each_meta(tt, q.start_match_mode_, o.target(),
[&](location_idx_t const l) {
update(l, o.duration());
if (q.use_start_footpaths_) {
auto const footpaths =
fwd ? tt.locations_.footpaths_out_[q.prf_idx_][l]
: tt.locations_.footpaths_in_[q.prf_idx_][l];
for (auto const& fp : footpaths) {
update(fp.target(), o.duration() + fp.duration());
}
}
});
}

for (auto const& s : shortest_start) {
auto const l = s.first;
auto const o = s.second;
for (auto const& [l, o] : shortest_start) {
std::visit(utl::overloaded{[&](interval<unixtime_t> const interval) {
add_starts_in_interval(search_dir, tt, rtt,
interval, l, o, starts,
Expand All @@ -231,6 +296,29 @@ void get_starts(direction const search_dir,
}},
start_time);
}

utl::equal_ranges_linear(
q.td_start_,
[](td_footpath const& a, td_footpath const& b) {
return a.target_ < b.target_;
},
[&](auto&& from_it, auto&& to_it) {
auto const offset = offset_t{std::span{from_it, to_it}};
std::visit(
utl::overloaded{[&](interval<unixtime_t> const interval) {
add_starts_in_interval(
search_dir, tt, rtt, interval,
from_it->target_, offset, starts, add_ontrip);
},
[&](unixtime_t const t) {
auto const o = get_offset(search_dir, offset, t);
starts.emplace_back(
start{.time_at_start_ = t,
.time_at_stop_ = fwd ? t + o : t - o,
.stop_ = from_it->target_});
}},
start_time);
});
}

void collect_destinations(timetable const& tt,
Expand Down
15 changes: 8 additions & 7 deletions test/routing/start_times_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,14 @@ TEST(routing, start_times) {
auto const B = tt.locations_.location_id_to_idx_.at(
location_id{.id_ = "0000002", .src_ = src});
auto starts = std::vector<start>{};
get_starts(direction::kForward, tt, nullptr,
interval<unixtime_t>{sys_days{2020_y / March / 30},
sys_days{2020_y / March / 31}},
{{A, 15_minutes, 0}, {B, 30_minutes, 0}},
location_match_mode::kExact, false, starts, true, 0);
std::sort(begin(starts), end(starts),
[](auto&& a, auto&& b) { return a > b; });
auto const q =
query{.start_time_ = interval<unixtime_t>{sys_days{2020_y / March / 30},
sys_days{2020_y / March / 31}},
.start_match_mode_ = location_match_mode::kExact,
.use_start_footpaths_ = false,
.start_ = {{A, 15_minutes, 0}, {B, 30_minutes, 0}}};
get_starts(tt, nullptr, direction::kForward, q, q.start_time_, true, starts);
utl::sort(starts, [](auto&& a, auto&& b) { return a > b; });
starts.erase(std::unique(begin(starts), end(starts)), end(starts));

std::stringstream ss;
Expand Down

0 comments on commit 85f3f25

Please sign in to comment.