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

Define strict version of the host-pest-action design #198

Open
2 of 13 tasks
wenzeslaus opened this issue Aug 15, 2023 · 4 comments
Open
2 of 13 tasks

Define strict version of the host-pest-action design #198

wenzeslaus opened this issue Aug 15, 2023 · 4 comments
Labels
enhancement New feature or request
Milestone

Comments

@wenzeslaus
Copy link
Member

wenzeslaus commented Aug 15, 2023

The PR which introduced host pool object and action objects (#184) kept the same computational results for the price of less defined and less clean design. When we decide to allow for different results, we can improve the host and action (and pest) design so that it is consistent and enforces data consistency, e.g., remove methods which change only infected and replace it by methods which require to change also exposed, resistant, and mortality at the same time or change that automatically.

  • Host pool interface is not clearly defined and it is purely determined by what other code needs. (The behavior for most methods is "whatever such and such class needs".)
  • Functions like bulk_remove_hosts_at(row, col, susceptible, exposed, infected, resistant) may help managing all the necessary groups consistently (a "set infected" method may take care of mortality, but did caller meant to set resistant, too?).
  • Interface classes have mostly what was needed for the code to compile, but don't cover all intended functionality.
  • All new code just does whatever the old code was doing, so no additional consistency checks or actions are included.
  • Pest should not handle established dispersers through adding all and then removal.
  • Add a common base with virtual methods to the Action classes to allow more dynamic structure of the model steps.
  • Random number generator types are now part of the class template parameters. The references are passed in methods. Actions take the generator providers while host pool takes the raw generator because host methods can be used by different actions while action is what determines which seed (raw generator) to use. A new host API with functions taking care of multiple pools (S, E, I etc) may need to know about the different seeds or the generator provider because that will provide the context (e.g., mortality). A possible remedy is to keep as many processes as possible deterministic (this is how removal of infected work with mortality now, but it may not be an universal solution).
  • For multi-host, rate and time lag will likely go to constructor of host poll (they would be host properties; now they are mortality action properties). Alternatively, the action would be be aware of the multiple hosts and have a table of values for different hosts.
  • Outside dispersers are now handled by actions, but for that, the actions need to check the bounds and keep total number of rows and columns. Moving this distinction to host and pests pools would remove the need to handle that in actions and would increase robustness of host and pest pools. The incoming disperser would be simply reported to both, host pool would ignore it and pest pool would store it to outside dispersers.
  • Create functions for the many consistency checks which are performed on parameters (size of exposed parameter is the same as internal exposed vector etc.). Use __func__.
  • Pass config to actions instead of having action user figure out the translation from configuration to member variables.
  • Make treatment an action.
  • Add clear rounding procedures.
@wenzeslaus wenzeslaus added the enhancement New feature or request label Aug 15, 2023
@wenzeslaus wenzeslaus added this to the 3.0.0 milestone Aug 15, 2023
@wenzeslaus
Copy link
Member Author

Possible model implementation using actions directly

The Model class does not have to use the Simulation class, but can use the actions directly:

class Model
{
    // Only once, or in every step.
    Hosts hosts;

    // Every step if using the same steering-friendly API like now.
    // Some rasters are optional, so set them by method (now all are set in the ctor).
    hosts.set_infected(...)
    // ...

    // These calls are all the same, so this code can be more dynamic with only
    // some actions being created based on the config and going through a list of
    // action objects here.
    remove_by_temperature.action(hosts);
    survival_rate.action(hosts);
    move_overpopulated_pests.action(hosts);
    mortality.action(hosts);
    // ...

    // At the end of the step (and/or at the beginning), allow host pool do its own thing
    // (need for the SEI model).
    hosts.step_forward();
}

@wenzeslaus
Copy link
Member Author

Extended PestPool which includes SoilPool

PestPool and SoilPool could be one object because they both store pests without hosts.

template<typename IntegerRaster>
class PestPool
{
    IntegerRaster mobile_dispersers;
    IntegerRaster immobile_dispersers;  // aka in soil storage

    void immobile_dispersers_to(number, i, j)
    {
        // weather + ratios + stochasticity
        immobile_dispersers(i, j) += number;
    }
    int immobile_dispersers_from(i, j)
    {
        // weather + ratios + stochasticity
        number = 1;
        immobile_dispersers(i, j) -= number;
        return number;
    }
    int add_dispersers_at(dispersers, i, j)
    {
        // To soils
        dispersers_to_soil = to_soil_percentage * dispersers;
        this->immobile_dispersers_to(dispersers_to_soil, i, j);
        dispersers -= dispersers_to_soil;
        return dispersers;
    }
};

@wenzeslaus
Copy link
Member Author

Spread action more closely combining generate and disperse with soils

Generate and disperse (kernel part) of disperse could be in one function, then the disperser moves would be resolved right away (but still in two steps, so more complex than the pseudocode). Dispersers may need more tracking, but here go through soil before being dispersed. Code has a tracking of established dispersers based on an identifier of how it was established.

template<typename Hosts, typename Pests>
class Spread
{
    void action(Hosts hosts, Pests pests)
    {
        for (const auto& [i, j] : hosts.suitable_cells) {
            // Generate
            dispersers = hosts.dispersers_from(i, j);

            // To soils
            dispersers = pests.add_dispersers_at(dispersers, i, j);

            // Classic spread
            for (const auto& disperser : dispersers) {
                i, j, kernel_name = kernel(disperser);
                // This can be in the pest:
                // if (i, j is outside) {
                //      pests.add_free(i, j);
                // }
                pests.add_landed(i, j);
                established = hosts.disperser_to(i, j);
                if (established) {
                    pests.add_established(i, j, disperser, kernel_name);
                }
            }

            // From soils
            dispersers = pests.immobile_dispersers_from(i, j);
            for (const auto& disperser : dispersers) {
                established = hosts.disperser_to(i, j);
                if (established)
                    pests.add_established(i, j, i, j, "soil");
            }
        }
    }
};

@wenzeslaus
Copy link
Member Author

Single method for removing exposed and infected

One method which combines remove_exposed_at and remove_infected_at to ensure that both E and I are modified when needed.

    void remove_infection_at(
        RasterIndex i,
        RasterIndex j,
        double percentage,
        Generator& generator)
    {
        this->remove_infected_at(i, j, x * percentage, generator);
        this->remove_exposed_at(i, j, y * percentage, generator);
    }
    void remove_infection_at(
        RasterIndex i,
        RasterIndex j,
        int exposed,
        int infected,
        Generator& generator)
    {
        this->remove_exposed_at(i, j, exposed, generator);
        this->remove_infected_at(i, j, infected, generator);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant