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