Package: covid19-supermarket-abm
Agent-based model for COVID-19 transmission in supermarkets.This code accompanies the paper"Modelling COVID-19 transmission in supermarkets using an agent-based model".InstallationOur package relies mainly onSimPy, which requires Python >= 3.6.>pipinstallcovid19-supermarket-abmExampleIn the example below, we use the example data included in the package to simulate a day in the fictitious store
given the parameters below.fromcovid19_supermarket_abm.utils.load_example_dataimportload_example_store_graph,load_example_pathsfromcovid19_supermarket_abm.path_generatorsimportget_path_generatorfromcovid19_supermarket_abm.simulatorimportsimulate_one_day# Set parametersconfig={'arrival_rate':2.55,# Poisson rate at which customers arrival'traversal_time':0.2,# mean wait time per node'num_hours_open':14,# store opening hours'infection_proportion':0.0011,# proportion of customers that are infectious}# load synthetic datazone_paths=load_example_paths()G=load_example_store_graph()# Create a path generator which feeds our model with customer pathspath_generator_function,path_generator_args=get_path_generator(zone_paths=zone_paths,G=G)# Simulate a day and store results in resultsresults_dict=simulate_one_day(config,G,path_generator_function,path_generator_args)The results from our simulations are stored inresults_dict.print(list(results_dict.keys()))Output:['num_cust','num_S','num_I','total_time_with_infected','num_contacts_per_cust','num_cust_w_contact','mean_num_cust_in_store','max_num_cust_in_store','num_contacts','shopping_times','mean_shopping_time','num_waiting_people','mean_waiting_time','store_open_length','df_num_encounters','df_time_with_infected','total_time_crowded','exposure_times']See below for their description.KeyDescriptionnum_custTotal number of customersnum_SNumber of susceptible customersnum_INumber of infected customerstotal_exposure_timeTotal exposure timenum_contacts_per_custNumber of contacts with infectious customers per susceptible customernum_cust_w_contactNumber of susceptible customers which have at least one contact with an infectious customermean_num_cust_in_storeMean number of customers in the store during the simulationmax_num_cust_in_storeMaximum number of customers in the store during the simulationnum_contactsTotal number of contacts between infectious customers and susceptible customersdf_num_encounters_per_nodeDataframe which contains the the number of encounters with infectious customers for each nodeshopping_timesArray that contains the length of all customer shopping tripsmean_shopping_timeMean of the shopping timesnum_waiting_peopleNumber of people who are queueing outside at every minute of the simulation (when the number of customers in the store is restricted)mean_waiting_timeMean time that customers wait before being allowed to enter (when the number of customers in the store is restricted)store_open_lengthLength of the store's opening hoursdf_exposure_time_per_nodeDataframe containing the exposure time per nodetotal_time_crowdedTotal time that nodes were crowded (when there are more thanthresnumber of customers in a node. Default value ofthresis 3)exposure_timesList of exposure times of customers (only recording positive exposure times)Getting startedAs we can see from the above example, our model requires four inputs.results_dict=simulate_one_day(config,G,path_generator_function,path_generator_args)These inputs are:(1) Simulation configurations:config(2) A store network:G(3) A path generator:path_generator_function(4) Arguments for the path generator:path_generator_argsWe discuss each of these inputs in the following subsections.Simulation configurationsWe input the configuration using a dictionary.
The following keys are accepted:Mandatory config keysConfig keyDescriptionarrival_rateRate at which customers arrive to the store (in customers per minute)traversal_timeMean wait time at each node (in minutes)num_hours_openNumber of hours that the store is openinfection_proportionProportion of customers that are infectedOptional config keysConfig keyDescriptionmax_customers_in_storeMaximum number of customers allowed in store (Default:None, i.e., disabled)with_node_capacitySet toTrueto limit the number of customers in each node. (Default:False). WARNING: This may cause simulations not to terminate due to gridlocks.node_capacityThe number of customers allowed in each node, ifwith_node_capacityis set toTrue. (Default:2)logging_enabledSet toTrueto start logging simulations. (Default:False). The logs can be accessed inresults_dict['logs']. Also if sanity checks fail, logs will be saved to file.Store networkWe use theNetworkXpackage to create our store network.First, we need to specify the (x,y) coordinates of each node.
So in a very simple example, we have four nodes, arranged in a square at with coordinates (0,0), (0,1), (1,0), and (1,1).pos={0:(0,0),1:(0,1),2:(1,0),3:(1,1)}Next, we need to specify the edges in the network; in other words, which nodes are connected to each other.edges=[(0,1),(1,3),(0,2),(2,3)]We create the graph as follows.fromcovid19_supermarket_abm.utils.create_store_networkimportcreate_store_networkG=create_store_network(pos,edges)To visualize your network, you can usenx.draw_networkx:importnetworkxasnxnx.draw_networkx(G,pos=pos,node_color='y')Path generator and argumentsThe path generator is what its name suggests:
It is ageneratorthat yields full customer paths.There are two* path generators implemented in this package.(1) Empirical path generator(2) Synthetic path generatorYou can also implement your own path generator and pass it.To use one of the implemented path generators,
it is often easiest to use theget_path_generatorfunction from thecovid19_supermarket_abm.path_generatorsmodule.fromcovid19_supermarket_abm.path_generatorsimportget_path_generatorpath_generator_function,path_generator_args=get_path_generator(path_generation,**args)*There is athird generatorimplemented, but for most purposes, the first two are likely preferable.Empirical path generatorThe empirical path generator takes as input a list of full paths
(which can be empirical paths or synthetically created paths) and yields random paths from that list.
Note that all paths must be valid paths in the store network or the simulation will fail at runtime.To use it, simplyfromcovid19_supermarket_abm.path_generatorsimportget_path_generatorfull_paths=[[0,1,3],[0,2,3]]# paths in the store networkpath_generator_function,path_generator_args=get_path_generator(path_generation='empirical',full_paths=full_paths)Alternatively, you can input a list of what we callzone pathsand the store networkG.
A zone path is a sequence of nodes that a customer visits, but where consecutive nodes in the sequence need not be adjacent.
In the paper, this sequence represents the item locations of where a customer bought items along with the
entrance, till and exit node that they visited.
Theget_path_generatorfunction automatically converts these zone paths to full paths by choosing shortest paths between
consecutive nodes in the zone path.fromcovid19_supermarket_abm.path_generatorsimportget_path_generatorzone_paths=[[0,3],[0,2,1],[0,3,2]]# note that consecutive nodes need not be adjacent!path_generator_function,path_generator_args=get_path_generator(path_generation='empirical',G=G,zone_paths=zone_paths)Synthetic path generatorThe synthetic path generator yields random paths as follows.(1) First, it samples the size K of the shopping basket using alog-normalrandom variable with parametermuandsigma(the mean and standard deviation of the underlying normal distribution).
(SeeSorensen et al, 2017)(2) Second, it chooses a random entrance node as the first node $v_1$ in the path.(3) Third, it samples K random item nodes, chosen uniformly at random with replacement from item_nodes, which we denote by
$v_2, ... v_{K+1}$.(4) Fourth, it samples a random till node and exit node, which we denote by $v_{K+2}$ and $v_{K+3}$.
The sequence $v_1, ..., v_{K+3}$ is a node sequence where the customer bought items, along the the entrance, till and exit
nodes that they visited.(5) Finally, we convert this sequence to a full path on the network using the shortest paths between consecutive nodes
in the sequence.For more information, see the Data section in ourpaper.fromcovid19_supermarket_abm.path_generatorsimportget_path_generatorfromcovid19_supermarket_abm.utils.create_synthetic_basketsimportget_all_shortest_path_dictsimportnetworkxasnxentrance_nodes=[0]till_nodes=[2]exit_nodes=[3]item_nodes=[1]mu=0.07sigma=0.76shortest_path_dict=get_all_shortest_path_dicts(G)synthetic_path_generator_args=[mu,sigma,entrance_nodes,till_nodes,exit_nodes,item_nodes,shortest_path_dict]path_generator_function,path_generator_args=get_path_generator(path_generation='synthetic',synthetic_path_generator_args=synthetic_path_generator_args)Note that this path generator may be quite slow. In the paper, we first pre-generated paths 100,000 paths
and then used the Empirical path generator with the pre-generated paths.Questions?This is work in progress, but feel free to ask any questions by raising an issue or contacting me directly underfabian.m.ying@gmail.com.