SciCompMod / memilio

Modular spatio-temporal models for epidemic and pandemic simulations
https://scicompmod.github.io/memilio/
Apache License 2.0
51 stars 15 forks source link

Copy world doesn't work with fixed trips #961

Open DavidKerkmann opened 4 months ago

DavidKerkmann commented 4 months ago

Bug description

When copying the world of the ABM, persons are copied in order of appearance in the locations. That means that person IDs change but the order of the person vector may change. Since trips are accessed via auto& person = m_persons[trip.person_id]; this is an issue and leads to an error.

This can be either resolved by keeping the order of the persons during a copy operation on the world OR by accessing people not with array indices but only by their unique person ID.

Version

Mac

To reproduce

Go to branch abm_paper_test_bs. Use the code

// Create the sampled simulation with start time t0.
auto world = mio::abm::World(num_age_groups);
create_sampled_world(world, input_dir, t0, max_num_persons);
auto world_copy = world;
// auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED!
auto sim = mio::abm::Simulation(t0, std::move(world_copy));

in lines 897 ff.

Relevant log output

Assertion failed: (index != INVALID_LOCATION_INDEX && "unexpected error."), function find_location, file world.cpp, line 191.

Add any relevant information, e.g. used compiler, screenshots.

No response

Checklist

xsaschako commented 4 months ago

@reneSchm fixed it with the following code:

World(const World& other)
        : parameters(other.parameters)
        , m_persons()
        , m_locations()
        , m_trip_list(other.m_trip_list)
        , m_cemetery_id(add_location(LocationType::Cemetery))
    {
        for (auto& origin_loc : other.get_locations()) {
            if (origin_loc.get_type() != LocationType::Cemetery) {
                // Copy a location
                m_locations.emplace_back(
                    std::make_unique<Location>(origin_loc.copy_location_without_persons(parameters.get_num_groups())));
            }
        }
        for (auto& person : other.get_persons()) {
            // add all persons in order. copy_person also adds them to their respective location
            auto& origin_loc =
                get_individualized_location({person.get_location().get_index(), person.get_location().get_type()});
            m_persons.push_back(std::make_unique<Person>(person.copy_person(origin_loc)));
        }
        use_migration_rules(other.m_use_migration_rules);
    }
It is live on the branch abm_paper_test_bs