Skip to content

1280 trip addition overhaul #1281

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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cpp/models/abm/mobility_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ namespace abm
*/
enum class TransportMode : uint32_t
{
Unknown = 0,
Bike,
CarDriver,
CarPassenger,
PublicTransport,
Walking,
Other,
Unknown,
Count //last!!
};

Expand Down
7 changes: 3 additions & 4 deletions cpp/models/abm/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,12 @@ void Model::perform_mobility(TimePoint t, TimeSpan dt)
}

// check if a person makes a trip
bool weekend = t.is_weekend();
size_t num_trips = m_trip_list.num_trips(weekend);
size_t num_trips = m_trip_list.num_trips();

for (; m_trip_list.get_current_index() < num_trips &&
m_trip_list.get_next_trip_time(weekend).seconds() < (t + dt).time_since_midnight().seconds();
m_trip_list.get_next_trip_time().seconds() < (t + dt).time_since_midnight().seconds();
m_trip_list.increase_index()) {
auto& trip = m_trip_list.get_next_trip(weekend);
auto& trip = m_trip_list.get_next_trip();
auto& person = get_person(trip.person_id);
auto personal_rng = PersonalRandomNumberGenerator(person);
// skip the trip if the person is in quarantine or is dead
Expand Down
45 changes: 18 additions & 27 deletions cpp/models/abm/trip_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,34 @@ namespace mio
namespace abm
{

TripList::TripList()
: m_trips_weekday({})
, m_trips_weekend({})
, m_current_index(0)
const Trip& TripList::get_next_trip() const
{
return m_trips[m_current_index];
}

const Trip& TripList::get_next_trip(bool weekend) const
TimePoint TripList::get_next_trip_time() const
{
return weekend ? m_trips_weekend[m_current_index] : m_trips_weekday[m_current_index];
return m_trips[m_current_index].trip_time;
}

TimePoint TripList::get_next_trip_time(bool weekend) const
{
return weekend ? m_trips_weekend[m_current_index].time : m_trips_weekday[m_current_index].time;
}

void TripList::use_weekday_trips_on_weekend()
{
m_trips_weekend = m_trips_weekday;
}

void TripList::add_trip(Trip trip, bool weekend)
void TripList::add_trips(std::vector<Trip> trip)
{
//Trips are sorted by time.
//Also include the person id in the comparison so different persons can make trips at the same time.
//The same person can only make one trip at the same time.
if (!weekend) {
insert_sorted_replace(m_trips_weekday, trip, [](auto& trip1, auto& trip2) {
return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id);
});
}
else {
insert_sorted_replace(m_trips_weekend, trip, [](auto& trip1, auto& trip2) {
return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id);
});
}

// Sort the incoming trips first
std::sort(trip.begin(), trip.end(), [](auto& trip1, auto& trip2) {
return std::tie(trip1.trip_time, trip1.person_id) < std::tie(trip2.trip_time, trip2.person_id);
});

std::vector<Trip> merged_trips;
merged_trips.reserve(m_trips.size() + trip.size());
std::merge(m_trips.begin(), m_trips.end(), trip.begin(), trip.end(), std::back_inserter(merged_trips),
[](auto& trip1, auto& trip2) {
return std::tie(trip1.trip_time, trip1.person_id) < std::tie(trip2.trip_time, trip2.person_id);
});
m_trips = std::move(merged_trips);
}

} // namespace abm
Expand Down
90 changes: 25 additions & 65 deletions cpp/models/abm/trip_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,67 +40,35 @@ namespace abm
* @brief A trip describes a change of Location from one Location to another Location.
*/
struct Trip {
//TODO: Origin is currently not used for the trips. Should we delete it then?
PersonId person_id; /**< Person that makes the trip and corresponds to the index into the structure m_persons from
Model, where all Person%s are saved.*/
TimePoint time; ///< Daytime at which a Person changes the Location.
TimePoint trip_time; ///< Daytime at which a Person changes the Location.
LocationId destination; ///< Location where the Person changes to.
int destination_model_id; ///< Model id of destination Location.
LocationId origin; ///< Location where the Person starts the Trip.
int origin_model_id; ///< Model id of origin Location.
TransportMode trip_mode; ///< Mode of transportation. See TransportMode for all possible modes of transportation.
std::vector<uint32_t> cells; /**< If destination consists of different Cell%s, this gives the index of the
Cell%s the Person changes to.*/
TransportMode
trip_mode; ///< Mode of transportation. 1:Bike, 2:Car (Driver), 3:Car (Co-Driver)), 4:Public Transport, 5:Walking, 6:Other/Unknown
LocationType destination_type; ///< Type of destination Location.

/**
* @brief Construct a new Trip.
* @param[in] id ID of the Person that makes the Trip.
* @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.
* @param[in] trip_time Time at which a Person changes the Location this currently cant be set for s specific day just a timepoint in a day.
* @param[in] destination Location where the Person changes to.
* @param[in] destination_model_id Model the Person changes to.
* @param[in] origin Location where the person starts the Trip.
* @param[in] origin_model_id Model the Person starts the Trip.
* @param[in] input_cells The index of the Cell%s the Person changes to.
*/
Trip(PersonId id, TimePoint time_new, LocationId dest, int dest_model_id, LocationId orig, int orig_model_id,
TransportMode mode_of_transport, LocationType type_of_activity, const std::vector<uint32_t>& input_cells = {})
Trip(PersonId id, const TimePoint time, const LocationId dest, const int dest_model_id = 0,
const TransportMode mode_of_transport = mio::abm::TransportMode::Unknown,
const std::vector<uint32_t>& input_cells = {})
: person_id(id)
, time(mio::abm::TimePoint(time_new.time_since_midnight().seconds()))
, trip_time(mio::abm::TimePoint(time.time_since_midnight().seconds()))
, destination(dest)
, destination_model_id(dest_model_id)
, origin(orig)
, origin_model_id(orig_model_id)
, cells(input_cells)
, trip_mode(mode_of_transport)
, destination_type(type_of_activity)
{
}

Trip(PersonId id, TimePoint time_new, LocationId dest, LocationId orig, TransportMode mode_of_transport,
LocationType type_of_activity, const std::vector<uint32_t>& input_cells = {})
: person_id(id)
, time(mio::abm::TimePoint(time_new.time_since_midnight().seconds()))
, destination(dest)
, destination_model_id(0)
, origin(orig)
, origin_model_id(0)
, cells(input_cells)
, trip_mode(mode_of_transport)
, destination_type(type_of_activity)
{
}

Trip(PersonId id, TimePoint time_new, LocationId dest, LocationId orig, LocationType type_of_activity,
const std::vector<uint32_t>& input_cells = {})
: Trip(id, time_new, dest, orig, mio::abm::TransportMode::Unknown, type_of_activity, input_cells)
{
}

Trip(PersonId id, TimePoint time_new, LocationId dest, LocationType type_of_activity,
const std::vector<uint32_t>& input_cells = {})
: Trip(id, time_new, dest, dest, mio::abm::TransportMode::Unknown, type_of_activity, input_cells)
{
}

Expand All @@ -109,17 +77,18 @@ struct Trip {
*/
bool operator==(const Trip& other) const
{
return (person_id == other.person_id) && (time == other.time) && (destination == other.destination) &&
(origin == other.origin);
return (person_id == other.person_id) && (trip_time == other.trip_time) && (destination == other.destination) &&
(destination_model_id == other.destination_model_id) && (trip_mode == other.trip_mode);
}

auto default_serialize()
{
return Members("Trip")
.add("person_id", person_id)
.add("time", time)
.add("trip_time", trip_time)
.add("destination", destination)
.add("origin", origin);
.add("model_id", destination_model_id)
.add("trip_mode", trip_mode);
}
};

Expand All @@ -132,31 +101,26 @@ class TripList
/**
* @brief Construct empty TripList.
*/
TripList();
TripList() = default;

/**
* @brief Get the next Trip.
* @param weekend Whether the Trip%s during the week or on the weekend are used.
*/
const Trip& get_next_trip(bool weekend) const;
const Trip& get_next_trip() const;

/**
* @brief Get the time at which the next Trip will happen.
* @brief Get the trip_time at which the next Trip will happen.
* @param weekend Whether the Trip%s during the week or on the weekend are used.
*/
TimePoint get_next_trip_time(bool weekend) const;
TimePoint get_next_trip_time() const;

/**
* @brief Add a Trip to the trip list.
* @param[in] trip The Trip to be added.
* @brief Adds Trips to the trip list.
* @param[in] trips The Trips to be added.
* @param[in] weekend If the Trip is made on a weekend day.
*/
void add_trip(Trip trip, bool weekend = false);

/**
* @brief Use the same TripList for weekend and weekday.
*/
void use_weekday_trips_on_weekend();
void add_trips(std::vector<Trip> trip);

/**
* @brief Increment the current index to select the next Trip.
Expand All @@ -178,9 +142,9 @@ class TripList
* @brief Get the length of the TripList.
* @param weekend Whether the Trip%s during the week or on the weekend are used.
*/
size_t num_trips(bool weekend = false) const
size_t num_trips() const
{
return weekend ? m_trips_weekend.size() : m_trips_weekday.size();
return m_trips.size();
}

/**
Expand All @@ -194,16 +158,12 @@ class TripList
/// This method is used by the default serialization feature.
auto default_serialize()
{
return Members("TestingScheme")
.add("trips_weekday", m_trips_weekday)
.add("trips_weekend", m_trips_weekend)
.add("index", m_current_index);
return Members("TestingScheme").add("trips", m_trips).add("index", m_current_index);
}

private:
std::vector<Trip> m_trips_weekday; ///< The list of Trip%s a Person makes on a weekday.
std::vector<Trip> m_trips_weekend; ///< The list of Trip%s a Person makes on a weekend day.
uint32_t m_current_index; ///< The index of the Trip a Person makes next.
std::vector<Trip> m_trips; ///< The list of Trip%s a Person makes on a weekday.
uint32_t m_current_index = 0; ///< The index of the Trip a Person makes next.
};

} // namespace abm
Expand All @@ -213,7 +173,7 @@ template <>
struct DefaultFactory<abm::Trip> {
static abm::Trip create()
{
return abm::Trip{abm::PersonId{}, abm::TimePoint{}, abm::LocationId{}, abm::LocationType{}};
return abm::Trip{abm::PersonId{}, abm::TimePoint{}, abm::LocationId{}};
}
};

Expand Down
4 changes: 4 additions & 0 deletions cpp/models/graph_abm/graph_abm_mobility.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,12 @@ class ABMMobilityEdge
for (int i = int(persons_to_change.size()) - 1; i >= 0; --i) {
auto& person = model_from.get_persons()[persons_to_change[i]];
auto target_type = person.get_location_type();
if (target_type == abm::LocationType::Count) {
target_type = model_to.get_location(person.get_location()).get_type();
}
//check if Person uses this edge
if (person.get_assigned_location_model_id(target_type) == model_to.get_id()) {

auto target_id = person.get_assigned_location(target_type);
//set correct location for person
person.set_location(target_type, target_id, model_to.get_id());
Expand Down
10 changes: 4 additions & 6 deletions cpp/models/graph_abm/graph_abmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,12 @@ class GraphABModel : public abm::Model
}

// check if a person makes a trip
bool weekend = t.is_weekend();
size_t num_trips = Base::m_trip_list.num_trips(weekend);
size_t num_trips = Base::m_trip_list.num_trips();

for (; Base::m_trip_list.get_current_index() < num_trips &&
Base::m_trip_list.get_next_trip_time(weekend).seconds() < (t + dt).time_since_midnight().seconds();
Base::m_trip_list.get_next_trip_time().seconds() < (t + dt).time_since_midnight().seconds();
Base::m_trip_list.increase_index()) {
auto& trip = Base::m_trip_list.get_next_trip(weekend);
auto& trip = Base::m_trip_list.get_next_trip();
auto& person = get_person(trip.person_id);
auto person_index = Base::get_person_index(trip.person_id);
auto personal_rng = PersonalRandomNumberGenerator(person);
Expand Down Expand Up @@ -192,8 +191,7 @@ class GraphABModel : public abm::Model
}
else { //person moves to other world
Base::m_activeness_statuses[person_index] = false;
person.set_location(trip.destination_type, abm::LocationId::invalid_id(),
std::numeric_limits<int>::max());
person.set_location(abm::LocationType::Count, trip.destination, std::numeric_limits<int>::max());
m_person_buffer.push_back(person_index);
m_are_exposure_caches_valid = false;
m_is_local_population_cache_valid = false;
Expand Down
13 changes: 5 additions & 8 deletions cpp/simulations/abm_braunschweig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ void create_model_from_data(mio::abm::Model& model, const std::string& filename,
std::getline(fin, line); // Skip header row

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

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

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

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

int start_index = mobility_data_index - 1;
using Type = std::tuple<mio::abm::PersonId, mio::abm::LocationId, mio::abm::TimePoint,
mio::abm::TransportMode, mio::abm::ActivityType, mio::abm::InfectionState>;
mio::abm::TransportMode, mio::abm::ActivityType, mio::abm::InfectionState>;
while (!std::binary_search(std::begin(mobility_data[start_index]), std::end(mobility_data[start_index]),
mobility_data[mobility_data_index][trip_index],
[](const Type& v1, const Type& v2) {
Expand Down
Loading