slim.simulation.organisation module
This module provides an implementation for Organisation
and farm pooling. For simulation
purposes Organisation
is the only class you may need.
An organisation here oversees farmers and serves coordination purposes, better described in its class documentation. It also provides (limited) chances for collaboration and manages the external pressure. However, much of the lice dispersion logic is indeed handled by farm pools.
A farm pool is a collection of farms or farm actors (if using multithreading). In a farm pool dispersion is applied at every step, and serves as an abstraction tool for the Organisation so that to decouple from the multiprocessing/synchronisation logic.
- class slim.simulation.organisation.FarmPool
Bases:
abc.ABC
While farms do not move lice back and forth with other farms themselves, they delegate movements to farm pools.
Farm pools are, as the name says, collection of farms that can transmit new lice eggs or freshly hatched lice between them.
In practice, this means all the caller has to do is set up a farm pool, perform an update and collect the daily payoffs/new lice. Note that farm pools do not own policies and require the organisation to instruct them on the actions to perform.
This is an abstract class with two main implementers. See their definition for details. You usually do not need to instantiate either directly as the Organisation class will automatically pick the correct one depending on your configuration.
- handle_aggregation_rate(spaces: SimulatorSpace, threshold: float, limit: float, weeks: int) Tuple[bool, List[str]]
Handle the aggregation rate of the specific cages. This has two functions: - suggest all farmers to apply a treatment - force a fallowing to non-compliant farms
This implements a simplified approach to the Scottish’s CoGP Plan. The algorithm is the following:
- if (lice count of a farm f >= org_aggregation_threshold):
recommend treatment to everyone
- if (lice count of a farm f) >= cogp_aggregation_threshold
count as a strike
- if S strikes have been reached for a farm f:
enforce culling on farm f
- Returns
a pair (should broadcast a message?, should cull the ith farm?)
- abstract start()
Start the pool. This function should be called before stepping.
- abstract step(cur_date: dt.datetime, actions: SAMPLED_ACTIONS, ext_influx: int, ext_pressure: GenoRates) Tuple[Dict[int, GenoDistrib], Dict[int, float], Dict[int, Any]]
Step through the pool. This will update the internal farms and coalesce results into dictionaries of farm outputs.
- Parameters
cur_date – the current date.
actions – the list of sampled actions
ext_influx – the number of incoming lice
- Returns
a tuple (total offspring per farm, payoff per farm, extra logs per farm)
- abstract stop()
Stop the pool. This function should be called before deallocation
- class slim.simulation.organisation.MultiProcFarmPool(cfg: Config, *args, **kwargs)
Bases:
slim.simulation.organisation.FarmPool
A multi-processing farm pool.
Internally a multi-processing pool will spawn a number of FarmActor and deal with lice dispersion without introducing locksteps or barriers. In this mode farms are not accessible to the main thread, meaning there is no subscript operator to access underlying farms.
- property get_gym_space: SimulatorSpace
Get a gym space for all the agents.
- property is_running
- reset()
- start()
Start the pool. This function should be called before stepping.
- step(cur_date, actions: SAMPLED_ACTIONS, ext_influx, ext_ratios) Tuple[Dict[int, GenoDistrib], Dict[int, float], Dict[int, Any]]
Perform an update across all farms. After that, some offspring will be distributed into the farms while others will be dispersed into the reservoir, thus changing the global external pressure.
- Parameters
cur_date – the current date
actions – if given pass the action to the policy.
- Returns
the cumulated reward from all the farm updates.
- stop()
Stop the pool. This function should be called before deallocation
- class slim.simulation.organisation.Organisation(cfg: Config, *args, **kwargs)
Bases:
object
An organisation is a cooperative of
farm.Farm
s. At every time step farms handle the population update logic and produce a number of offspring, which the Organisation is supposed to handle.Furthermore, farms regularly send messages to their farms about their statuses. An organisation can recommend farms to apply treatment if one of those has surpassed critical levels (see
handle_farm_messages()
).Furthermore, the organisation handles the external pressure. Depending on the number of produced eggs and their genotype the external pressure will dynamically evolve. The mechanism is discussed in External Pressure.
The organisation will also spawn the right farm pool depending on whether the configuration has enabled multiprocessing (i.e. if cfg.farms_per_process is neither -1 nor equal to the farm number).
Ultimately, farm updates are used to recompute the external pressure.
- Parameters
cfg – a Configuration
*args – other constructing parameters passed to the underlying
farm.Farm
s.ray_address – if using multiprocessing, pass the address to ray
ray_redis_password – if using multiprocessing, pass the redis password to ray.
- get_external_pressure() Tuple[int, GenoRates]
Get the external pressure. Callers of this function should then invoke some distribution to sample the obtained number of lice that respects the probabilities.
For example:
>>> org = Organisation(...) >>> n, p = org.get_external_pressure() >>> new_lice = lice_population.from_ratios(p, n)
- Returns
a pair (number of new lice from reservoir, the ratios to sample from)
- property get_gym_space
Get the gym space.
- reset()
Reset a simulation. This implies stopping the current farms and bringing them back to the original state before the first stepping has occurred.
- step(cur_date: dt.datetime, actions: SAMPLED_ACTIONS) Tuple[Dict[int, float], Dict[str, Any]]
Perform an update across all farms. After that, some offspring will be distributed into the farms while others will be dispersed into the reservoir, thus changing the global external pressure.
- Parameters
cur_date – the current date
actions – if given pass the action to the policy.
- Returns
the cumulated reward from all the farm updates, and logs generated by all the farms
- stop()
Stop the simulation. This will kill any standing farm actor (if any). It is not allowed to resume a simulation after a stop() has occurred.
- to_json_dict()
- update_genetic_ratios(offspring: GenoDistrib)
Update the genetic ratios after an offspring update.
- Parameters
offspring – the offspring update
- update_offspring_average(offspring_per_farm: Dict[int, GenoDistrib])
DO NOT CALL THIS DIRECTLY! It is only exposed for testing purposes.
Alter the external pressure by updating the rolling average of offsprings in the last \(\tau\) days (controlled by
Config.reservoir_offspring_average
)Internally, we use a simple weighted average to store the average offpsring.
- class slim.simulation.organisation.SingleProcFarmPool(cfg: Config, *args)
Bases:
slim.simulation.organisation.FarmPool
A single process foarm pool.
- property get_gym_space
- reset()
- start()
Start the pool. This function should be called before stepping.
- step(cur_date: dt.datetime, actions: SAMPLED_ACTIONS, ext_influx: int, ext_pressure: GenoRates) Tuple[Dict[int, GenoDistrib], Dict[int, float], Dict[int, Any]]
Step through the pool. This will update the internal farms and coalesce results into dictionaries of farm outputs.
- Parameters
cur_date – the current date.
actions – the list of sampled actions
ext_influx – the number of incoming lice
- Returns
a tuple (total offspring per farm, payoff per farm, extra logs per farm)
- stop()
Stop the pool. This function should be called before deallocation