Skip to content

Commit b738898

Browse files
authored
1280 trip addition overhaul (#1281)
Trip simplification and overhaul, performance improvements in trip read-in.
1 parent fffdfb8 commit b738898

File tree

14 files changed

+118
-243
lines changed

14 files changed

+118
-243
lines changed

cpp/models/abm/location_type.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ enum class LocationType : std::uint32_t
4444
TransportWithoutContact, // all ways of travel with no contact to other people, e.g. biking or walking
4545
Cemetery, // Location for all the dead persons. It is created once for the Model.
4646

47-
Count //last!
47+
Count, //last!
48+
Invalid
4849
};
4950

5051
} // namespace abm

cpp/models/abm/mobility_data.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ namespace abm
3333
*/
3434
enum class TransportMode : uint32_t
3535
{
36+
Unknown = 0,
3637
Bike,
3738
CarDriver,
3839
CarPassenger,
3940
PublicTransport,
4041
Walking,
4142
Other,
42-
Unknown,
4343
Count //last!!
4444
};
4545

cpp/models/abm/model.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,12 @@ void Model::perform_mobility(TimePoint t, TimeSpan dt)
171171
}
172172

173173
// check if a person makes a trip
174-
bool weekend = t.is_weekend();
175-
size_t num_trips = m_trip_list.num_trips(weekend);
174+
size_t num_trips = m_trip_list.num_trips();
176175

177176
for (; m_trip_list.get_current_index() < num_trips &&
178-
m_trip_list.get_next_trip_time(weekend).seconds() < (t + dt).time_since_midnight().seconds();
177+
m_trip_list.get_next_trip_time().seconds() < (t + dt).time_since_midnight().seconds();
179178
m_trip_list.increase_index()) {
180-
auto& trip = m_trip_list.get_next_trip(weekend);
179+
auto& trip = m_trip_list.get_next_trip();
181180
auto& person = get_person(trip.person_id);
182181
auto personal_rng = PersonalRandomNumberGenerator(person);
183182
// skip the trip if the person is in quarantine or is dead

cpp/models/abm/trip_list.cpp

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,36 @@ namespace mio
2626
namespace abm
2727
{
2828

29-
TripList::TripList()
30-
: m_trips_weekday({})
31-
, m_trips_weekend({})
32-
, m_current_index(0)
29+
const Trip& TripList::get_next_trip() const
3330
{
31+
return m_trips[m_current_index];
3432
}
3533

36-
const Trip& TripList::get_next_trip(bool weekend) const
34+
TimePoint TripList::get_next_trip_time() const
3735
{
38-
return weekend ? m_trips_weekend[m_current_index] : m_trips_weekday[m_current_index];
36+
return m_trips[m_current_index].trip_time;
3937
}
4038

41-
TimePoint TripList::get_next_trip_time(bool weekend) const
42-
{
43-
return weekend ? m_trips_weekend[m_current_index].time : m_trips_weekday[m_current_index].time;
44-
}
45-
46-
void TripList::use_weekday_trips_on_weekend()
47-
{
48-
m_trips_weekend = m_trips_weekday;
49-
}
50-
51-
void TripList::add_trip(Trip trip, bool weekend)
39+
void TripList::add_trips(std::vector<Trip> trip)
5240
{
5341
//Trips are sorted by time.
5442
//Also include the person id in the comparison so different persons can make trips at the same time.
5543
//The same person can only make one trip at the same time.
56-
if (!weekend) {
57-
insert_sorted_replace(m_trips_weekday, trip, [](auto& trip1, auto& trip2) {
58-
return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id);
59-
});
60-
}
61-
else {
62-
insert_sorted_replace(m_trips_weekend, trip, [](auto& trip1, auto& trip2) {
63-
return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id);
44+
45+
std::sort(trip.begin(), trip.end(), [](auto& trip1, auto& trip2) {
46+
return std::tie(trip1.trip_time, trip1.person_id) < std::tie(trip2.trip_time, trip2.person_id);
47+
});
48+
// Avoid storage duplication by using in-place merge
49+
const size_t original_size = m_trips.size();
50+
51+
// Append the sorted new trips to the end
52+
m_trips.insert(m_trips.end(), std::make_move_iterator(trip.begin()), std::make_move_iterator(trip.end()));
53+
54+
// Use in-place merge to merge the two sorted ranges
55+
std::inplace_merge(
56+
m_trips.begin(), m_trips.begin() + original_size, m_trips.end(), [](const auto& trip1, const auto& trip2) {
57+
return std::tie(trip1.trip_time, trip1.person_id) < std::tie(trip2.trip_time, trip2.person_id);
6458
});
65-
}
6659
}
6760

6861
} // namespace abm

cpp/models/abm/trip_list.h

Lines changed: 25 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -40,67 +40,35 @@ namespace abm
4040
* @brief A trip describes a change of Location from one Location to another Location.
4141
*/
4242
struct Trip {
43-
//TODO: Origin is currently not used for the trips. Should we delete it then?
4443
PersonId person_id; /**< Person that makes the trip and corresponds to the index into the structure m_persons from
4544
Model, where all Person%s are saved.*/
46-
TimePoint time; ///< Daytime at which a Person changes the Location.
45+
TimePoint trip_time; ///< Daytime at which a Person changes the Location.
4746
LocationId destination; ///< Location where the Person changes to.
4847
int destination_model_id; ///< Model id of destination Location.
49-
LocationId origin; ///< Location where the Person starts the Trip.
50-
int origin_model_id; ///< Model id of origin Location.
48+
TransportMode trip_mode; ///< Mode of transportation. See TransportMode for all possible modes of transportation.
5149
std::vector<uint32_t> cells; /**< If destination consists of different Cell%s, this gives the index of the
5250
Cell%s the Person changes to.*/
53-
TransportMode
54-
trip_mode; ///< Mode of transportation. 1:Bike, 2:Car (Driver), 3:Car (Co-Driver)), 4:Public Transport, 5:Walking, 6:Other/Unknown
55-
LocationType destination_type; ///< Type of destination Location.
5651

5752
/**
5853
* @brief Construct a new Trip.
5954
* @param[in] id ID of the Person that makes the Trip.
60-
* @param[in] time_new Time at which a Person changes the Location this currently cant be set for s specific day just a timepoint in a day.
55+
* @param[in] time Time at which a Person changes the Location this currently cant be set for s specific day just a timepoint in a day.
6156
* @param[in] destination Location where the Person changes to.
6257
* @param[in] destination_model_id Model the Person changes to.
6358
* @param[in] origin Location where the person starts the Trip.
6459
* @param[in] origin_model_id Model the Person starts the Trip.
6560
* @param[in] input_cells The index of the Cell%s the Person changes to.
6661
*/
67-
Trip(PersonId id, TimePoint time_new, LocationId dest, int dest_model_id, LocationId orig, int orig_model_id,
68-
TransportMode mode_of_transport, LocationType type_of_activity, const std::vector<uint32_t>& input_cells = {})
62+
Trip(PersonId id, const TimePoint time, const LocationId dest, const int dest_model_id = 0,
63+
const TransportMode mode_of_transport = mio::abm::TransportMode::Unknown,
64+
const std::vector<uint32_t>& input_cells = {})
6965
: person_id(id)
70-
, time(mio::abm::TimePoint(time_new.time_since_midnight().seconds()))
66+
, trip_time(mio::abm::TimePoint(time.time_since_midnight().seconds()))
7167
, destination(dest)
7268
, destination_model_id(dest_model_id)
73-
, origin(orig)
74-
, origin_model_id(orig_model_id)
75-
, cells(input_cells)
7669
, trip_mode(mode_of_transport)
77-
, destination_type(type_of_activity)
78-
{
79-
}
80-
81-
Trip(PersonId id, TimePoint time_new, LocationId dest, LocationId orig, TransportMode mode_of_transport,
82-
LocationType type_of_activity, const std::vector<uint32_t>& input_cells = {})
83-
: person_id(id)
84-
, time(mio::abm::TimePoint(time_new.time_since_midnight().seconds()))
85-
, destination(dest)
86-
, destination_model_id(0)
87-
, origin(orig)
88-
, origin_model_id(0)
8970
, cells(input_cells)
90-
, trip_mode(mode_of_transport)
91-
, destination_type(type_of_activity)
92-
{
93-
}
9471

95-
Trip(PersonId id, TimePoint time_new, LocationId dest, LocationId orig, LocationType type_of_activity,
96-
const std::vector<uint32_t>& input_cells = {})
97-
: Trip(id, time_new, dest, orig, mio::abm::TransportMode::Unknown, type_of_activity, input_cells)
98-
{
99-
}
100-
101-
Trip(PersonId id, TimePoint time_new, LocationId dest, LocationType type_of_activity,
102-
const std::vector<uint32_t>& input_cells = {})
103-
: Trip(id, time_new, dest, dest, mio::abm::TransportMode::Unknown, type_of_activity, input_cells)
10472
{
10573
}
10674

@@ -109,17 +77,18 @@ struct Trip {
10977
*/
11078
bool operator==(const Trip& other) const
11179
{
112-
return (person_id == other.person_id) && (time == other.time) && (destination == other.destination) &&
113-
(origin == other.origin);
80+
return (person_id == other.person_id) && (trip_time == other.trip_time) && (destination == other.destination) &&
81+
(destination_model_id == other.destination_model_id) && (trip_mode == other.trip_mode);
11482
}
11583

11684
auto default_serialize()
11785
{
11886
return Members("Trip")
11987
.add("person_id", person_id)
120-
.add("time", time)
88+
.add("trip_time", trip_time)
12189
.add("destination", destination)
122-
.add("origin", origin);
90+
.add("model_id", destination_model_id)
91+
.add("trip_mode", trip_mode);
12392
}
12493
};
12594

@@ -132,31 +101,26 @@ class TripList
132101
/**
133102
* @brief Construct empty TripList.
134103
*/
135-
TripList();
104+
TripList() = default;
136105

137106
/**
138107
* @brief Get the next Trip.
139108
* @param weekend Whether the Trip%s during the week or on the weekend are used.
140109
*/
141-
const Trip& get_next_trip(bool weekend) const;
110+
const Trip& get_next_trip() const;
142111

143112
/**
144-
* @brief Get the time at which the next Trip will happen.
113+
* @brief Get the trip_time at which the next Trip will happen.
145114
* @param weekend Whether the Trip%s during the week or on the weekend are used.
146115
*/
147-
TimePoint get_next_trip_time(bool weekend) const;
116+
TimePoint get_next_trip_time() const;
148117

149118
/**
150-
* @brief Add a Trip to the trip list.
151-
* @param[in] trip The Trip to be added.
119+
* @brief Adds Trips to the trip list.
120+
* @param[in] trips The Trips to be added.
152121
* @param[in] weekend If the Trip is made on a weekend day.
153122
*/
154-
void add_trip(Trip trip, bool weekend = false);
155-
156-
/**
157-
* @brief Use the same TripList for weekend and weekday.
158-
*/
159-
void use_weekday_trips_on_weekend();
123+
void add_trips(std::vector<Trip> trip);
160124

161125
/**
162126
* @brief Increment the current index to select the next Trip.
@@ -178,9 +142,9 @@ class TripList
178142
* @brief Get the length of the TripList.
179143
* @param weekend Whether the Trip%s during the week or on the weekend are used.
180144
*/
181-
size_t num_trips(bool weekend = false) const
145+
size_t num_trips() const
182146
{
183-
return weekend ? m_trips_weekend.size() : m_trips_weekday.size();
147+
return m_trips.size();
184148
}
185149

186150
/**
@@ -194,16 +158,12 @@ class TripList
194158
/// This method is used by the default serialization feature.
195159
auto default_serialize()
196160
{
197-
return Members("TestingScheme")
198-
.add("trips_weekday", m_trips_weekday)
199-
.add("trips_weekend", m_trips_weekend)
200-
.add("index", m_current_index);
161+
return Members("TestingScheme").add("trips", m_trips).add("index", m_current_index);
201162
}
202163

203164
private:
204-
std::vector<Trip> m_trips_weekday; ///< The list of Trip%s a Person makes on a weekday.
205-
std::vector<Trip> m_trips_weekend; ///< The list of Trip%s a Person makes on a weekend day.
206-
uint32_t m_current_index; ///< The index of the Trip a Person makes next.
165+
std::vector<Trip> m_trips; ///< The list of Trip%s a Person makes on a weekday.
166+
uint32_t m_current_index = 0; ///< The index of the Trip a Person makes next.
207167
};
208168

209169
} // namespace abm
@@ -213,7 +173,7 @@ template <>
213173
struct DefaultFactory<abm::Trip> {
214174
static abm::Trip create()
215175
{
216-
return abm::Trip{abm::PersonId{}, abm::TimePoint{}, abm::LocationId{}, abm::LocationType{}};
176+
return abm::Trip{abm::PersonId{}, abm::TimePoint{}, abm::LocationId{}};
217177
}
218178
};
219179

cpp/models/graph_abm/graph_abm_mobility.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,12 @@ class ABMMobilityEdge
125125
for (int i = int(persons_to_change.size()) - 1; i >= 0; --i) {
126126
auto& person = model_from.get_persons()[persons_to_change[i]];
127127
auto target_type = person.get_location_type();
128+
if (target_type == abm::LocationType::Invalid) {
129+
target_type = model_to.get_location(person.get_location()).get_type();
130+
}
128131
//check if Person uses this edge
129132
if (person.get_assigned_location_model_id(target_type) == model_to.get_id()) {
133+
130134
auto target_id = person.get_assigned_location(target_type);
131135
//set correct location for person
132136
person.set_location(target_type, target_id, model_to.get_id());

cpp/models/graph_abm/graph_abmodel.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,12 @@ class GraphABModel : public abm::Model
152152
}
153153

154154
// check if a person makes a trip
155-
bool weekend = t.is_weekend();
156-
size_t num_trips = Base::m_trip_list.num_trips(weekend);
155+
size_t num_trips = Base::m_trip_list.num_trips();
157156

158157
for (; Base::m_trip_list.get_current_index() < num_trips &&
159-
Base::m_trip_list.get_next_trip_time(weekend).seconds() < (t + dt).time_since_midnight().seconds();
158+
Base::m_trip_list.get_next_trip_time().seconds() < (t + dt).time_since_midnight().seconds();
160159
Base::m_trip_list.increase_index()) {
161-
auto& trip = Base::m_trip_list.get_next_trip(weekend);
160+
auto& trip = Base::m_trip_list.get_next_trip();
162161
auto& person = get_person(trip.person_id);
163162
auto person_index = Base::get_person_index(trip.person_id);
164163
auto personal_rng = PersonalRandomNumberGenerator(person);
@@ -192,8 +191,7 @@ class GraphABModel : public abm::Model
192191
}
193192
else { //person moves to other world
194193
Base::m_activeness_statuses[person_index] = false;
195-
person.set_location(trip.destination_type, abm::LocationId::invalid_id(),
196-
std::numeric_limits<int>::max());
194+
person.set_location(abm::LocationType::Invalid, trip.destination, std::numeric_limits<int>::max());
197195
m_person_buffer.push_back(person_index);
198196
m_are_exposure_caches_valid = false;
199197
m_is_local_population_cache_valid = false;

cpp/simulations/abm_braunschweig.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ void create_model_from_data(mio::abm::Model& model, const std::string& filename,
341341
std::getline(fin, line); // Skip header row
342342

343343
// Add the persons and trips
344+
std::vector<mio::abm::Trip> trips;
344345
while (std::getline(fin, line)) {
345346
row.clear();
346347

@@ -357,8 +358,6 @@ void create_model_from_data(mio::abm::Model& model, const std::string& filename,
357358
uint32_t target_location_id = std::abs(row[index["loc_id_end"]]);
358359
uint32_t start_location_id = std::abs(row[index["loc_id_start"]]);
359360
uint32_t trip_start = row[index["start_time"]];
360-
uint32_t transport_mode = row[index["travel_mode"]];
361-
uint32_t acticity_end = row[index["activity_end"]];
362361

363362
// Add the trip to the trip list person and location must exist at this point
364363
auto target_location = locations.find(target_location_id)->second;
@@ -388,12 +387,10 @@ void create_model_from_data(mio::abm::Model& model, const std::string& filename,
388387
// For trips where the start location is not known use Home instead
389388
start_location = model.get_person(pid_itr->second).get_assigned_location(mio::abm::LocationType::Home);
390389
}
391-
model.get_trip_list().add_trip(
392-
mio::abm::Trip(static_cast<uint64_t>(pid_itr->first),
393-
mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location, start_location,
394-
mio::abm::TransportMode(transport_mode), mio::abm::LocationType(acticity_end)));
390+
trips.push_back(
391+
mio::abm::Trip(pid_itr->second, mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location));
395392
}
396-
model.get_trip_list().use_weekday_trips_on_weekend();
393+
model.get_trip_list().add_trips(trips);
397394
}
398395

399396
void set_parameters(mio::abm::Parameters params)
@@ -915,7 +912,7 @@ void write_log_to_file_trip_data(const T& history)
915912

916913
int start_index = mobility_data_index - 1;
917914
using Type = std::tuple<mio::abm::PersonId, mio::abm::LocationId, mio::abm::TimePoint,
918-
mio::abm::TransportMode, mio::abm::ActivityType, mio::abm::InfectionState>;
915+
mio::abm::TransportMode, mio::abm::ActivityType, mio::abm::InfectionState>;
919916
while (!std::binary_search(std::begin(mobility_data[start_index]), std::end(mobility_data[start_index]),
920917
mobility_data[mobility_data_index][trip_index],
921918
[](const Type& v1, const Type& v2) {

0 commit comments

Comments
 (0)