mirror of
https://github.com/gsi-upm/soil
synced 2024-11-24 11:52:29 +00:00
Initial benchmarking
This commit is contained in:
parent
eca4cae298
commit
5e93399d58
12
benchmarks/noop-bench-async.csv
Normal file
12
benchmarks/noop-bench-async.csv
Normal file
@ -0,0 +1,12 @@
|
||||
command,mean,stddev,median,user,system,min,max,parameter_sim
|
||||
python noop/mesa_batchrunner.py,1.3258325165599998,0.05822826666377271,1.31279976286,1.2978164199999997,0.25767558,1.2780627573599999,1.46763559736,mesa_batchrunner
|
||||
python noop/mesa_simulation.py,1.3915081544599999,0.07311646048704976,1.37166811936,1.35267662,0.29222067999999995,1.32746067836,1.58495303336,mesa_simulation
|
||||
python noop/soil_step.py,1.9859962588599998,0.12143759641749913,1.93586195486,2.0000750199999997,0.54126188,1.9061700903599998,2.2532835533599997,soil_step
|
||||
python noop/soil_step_pqueue.py,2.1347049971600005,0.01336179424666973,2.13492341986,2.1368160200000004,0.56862948,2.11810132936,2.16042739636,soil_step_pqueue
|
||||
python noop/soil_gens.py,2.1284937893599998,0.03030587681163665,2.13585231586,2.14158812,0.54900038,2.0768625143599997,2.19043625236,soil_gens
|
||||
python noop/soil_gens_pqueue.py,2.3469003942599995,0.019461346004472344,2.3486906343599996,2.36505852,0.54629858,2.31766326036,2.37998102136,soil_gens_pqueue
|
||||
python noop/soil_async.py,2.85755484126,0.0314955571121844,2.84774029536,2.86388112,0.55261338,2.81428668936,2.90567961636,soil_async
|
||||
python noop/soil_async_pqueue.py,3.1999731134600005,0.04432336803797717,3.20255954186,3.2162337199999995,0.5501872800000001,3.1406816913599997,3.26137401936,soil_async_pqueue
|
||||
python noop/soilent_step.py,1.30038977816,0.017973958957989845,1.30187804986,1.3231730199999998,0.5452653799999999,1.27058263436,1.31902240836,soilent_step
|
||||
python noop/soilent_step_pqueue.py,1.4708435788599998,0.027193290392962755,1.4707784423599999,1.4900387199999998,0.54749428,1.43498127536,1.53065598436,soilent_step_pqueue
|
||||
python noop/soilent_gens.py,1.6338810973599998,0.05752539125688073,1.63513330036,1.65216122,0.51846678,1.54135944036,1.7038832853599999,soilent_gens
|
|
11
benchmarks/noop-bench.csv
Normal file
11
benchmarks/noop-bench.csv
Normal file
@ -0,0 +1,11 @@
|
||||
command,mean,stddev,median,user,system,min,max,parameter_sim
|
||||
python noop/mesa1_batchrunner.py,1.2559917394000002,0.012031173494887278,1.2572688413000002,1.2168630799999998,0.31825289999999995,1.2346063853,1.2735512493,mesa1_batchrunner
|
||||
python noop/mesa1_simulation.py,1.3024417227,0.022498874113931668,1.2994157323,1.2595484799999999,0.3087897,1.2697029703,1.3350640403,mesa1_simulation
|
||||
python noop/soil1.py,1.8789492443,0.18023367899835044,1.8186795393000001,1.86076288,0.5309521,1.7326687413000001,2.2928370642999996,soil1
|
||||
python noop/soil1_pqueue.py,1.9841675890000001,0.01735524088843906,1.9884363323,2.01830338,0.5787977999999999,1.9592171483,2.0076169282999996,soil1_pqueue
|
||||
python noop/soil2.py,2.0135188921999996,0.02869307129649681,2.0184709453,2.03951308,0.5885591,1.9680417823,2.0567112592999997,soil2
|
||||
python noop/soil2_pqueue.py,2.2367320454999997,0.024339667344486046,2.2357249777999995,2.2515216799999997,0.5978869,2.1957917303,2.2688685033,soil2_pqueue
|
||||
python noop/soilent1.py,1.1309301329,0.015133005948737871,1.1276461497999999,1.14056688,0.6027519,1.1135821423,1.1625753893,soilent1
|
||||
python noop/soilent1_pqueue.py,1.3097537665000003,0.018821977712258842,1.3073709358,1.3270259799999997,0.6000067999999998,1.2874580013,1.3381646823,soilent1_pqueue
|
||||
python noop/soilent2.py,1.5055360476,0.05166674417574119,1.4883118568,1.5121205799999997,0.5817363999999999,1.4490918363,1.6005909333000001,soilent2
|
||||
python noop/soilent2_pqueue.py,1.6622598218,0.031130739036296016,1.6588702603,1.6862567799999997,0.5854159,1.6289724583,1.7330545383,soilent2_pqueue
|
|
25
benchmarks/noop/_config.py
Normal file
25
benchmarks/noop/_config.py
Normal file
@ -0,0 +1,25 @@
|
||||
import os
|
||||
|
||||
NUM_AGENTS = int(os.environ.get('NUM_AGENTS', 100))
|
||||
NUM_ITERS = int(os.environ.get('NUM_ITERS', 10))
|
||||
MAX_STEPS = int(os.environ.get('MAX_STEPS', 1000))
|
||||
|
||||
|
||||
def run_sim(model, **kwargs):
|
||||
from soil import Simulation
|
||||
opts = dict(model=model,
|
||||
dump=False,
|
||||
num_processes=1,
|
||||
parameters={'num_agents': NUM_AGENTS},
|
||||
max_steps=MAX_STEPS,
|
||||
iterations=NUM_ITERS)
|
||||
opts.update(kwargs)
|
||||
res = Simulation(**opts).run()
|
||||
|
||||
total = sum(a.num_calls for e in res for a in e.schedule.agents)
|
||||
expected = NUM_AGENTS * NUM_ITERS * MAX_STEPS
|
||||
print(total)
|
||||
print(expected)
|
||||
|
||||
assert total == expected
|
||||
return res
|
44
benchmarks/noop/mesa_batchrunner.py
Normal file
44
benchmarks/noop/mesa_batchrunner.py
Normal file
@ -0,0 +1,44 @@
|
||||
from mesa import batch_run, DataCollector, Agent, Model
|
||||
from mesa.time import RandomActivation
|
||||
|
||||
|
||||
class NoopAgent(Agent):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.num_calls = 0
|
||||
|
||||
def step(self):
|
||||
# import pdb;pdb.set_trace()
|
||||
self.num_calls += 1
|
||||
|
||||
|
||||
class NoopModel(Model):
|
||||
def __init__(self, N):
|
||||
super().__init__()
|
||||
self.schedule = RandomActivation(self)
|
||||
for i in range(N):
|
||||
self.schedule.add(NoopAgent(self.next_id(), self))
|
||||
self.datacollector = DataCollector(model_reporters={"num_agents": lambda m: m.schedule.get_agent_count(),
|
||||
"time": lambda m: m.schedule.time},
|
||||
agent_reporters={"num_calls": "num_calls"})
|
||||
self.datacollector.collect(self)
|
||||
|
||||
def step(self):
|
||||
self.schedule.step()
|
||||
self.datacollector.collect(self)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
res = batch_run(model_cls=NoopModel,
|
||||
max_steps=MAX_STEPS,
|
||||
iterations=NUM_ITERS,
|
||||
number_processes=1,
|
||||
parameters={'N': NUM_AGENTS})
|
||||
total = sum(s["num_calls"] for s in res)
|
||||
total_agents = sum(s["num_agents"] for s in res)
|
||||
assert len(res) == NUM_AGENTS * NUM_ITERS
|
||||
assert total == NUM_AGENTS * NUM_ITERS * MAX_STEPS
|
||||
assert total_agents == NUM_AGENTS * NUM_AGENTS * NUM_ITERS
|
||||
|
38
benchmarks/noop/mesa_simulation.py
Normal file
38
benchmarks/noop/mesa_simulation.py
Normal file
@ -0,0 +1,38 @@
|
||||
from mesa import batch_run, DataCollector, Agent, Model
|
||||
from mesa.time import RandomActivation
|
||||
from soil import Simulation
|
||||
from _config import *
|
||||
|
||||
|
||||
class NoopAgent(Agent):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.num_calls = 0
|
||||
|
||||
def step(self):
|
||||
# import pdb;pdb.set_trace()
|
||||
self.num_calls += 1
|
||||
|
||||
|
||||
class NoopModel(Model):
|
||||
def __init__(self, num_agents, *args, **kwargs):
|
||||
super().__init__()
|
||||
self.schedule = RandomActivation(self)
|
||||
for i in range(num_agents):
|
||||
self.schedule.add(NoopAgent(self.next_id(), self))
|
||||
self.datacollector = DataCollector(model_reporters={"num_agents": lambda m: m.schedule.get_agent_count(),
|
||||
"time": lambda m: m.schedule.time},
|
||||
agent_reporters={"num_calls": "num_calls"})
|
||||
self.datacollector.collect(self)
|
||||
|
||||
def step(self):
|
||||
self.schedule.step()
|
||||
self.datacollector.collect(self)
|
||||
|
||||
|
||||
def run():
|
||||
run_sim(model=NoopModel)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
3
benchmarks/noop/noop-bench.csv
Normal file
3
benchmarks/noop/noop-bench.csv
Normal file
@ -0,0 +1,3 @@
|
||||
command,mean,stddev,median,user,system,min,max,parameter_sim
|
||||
python mesa1_batchrunner.py,1.2932078178200002,0.05649377020829272,1.2705532802200001,1.25902256,0.27242284,1.22210926572,1.40867459172,mesa1_batchrunner
|
||||
python mesa1_simulation.py,1.81112963812,0.015491072368938567,1.81342524572,1.8594407599999996,0.8005329399999999,1.78538603972,1.84176361172,mesa1_simulation
|
|
24
benchmarks/noop/soil_async.py
Normal file
24
benchmarks/noop/soil_async.py
Normal file
@ -0,0 +1,24 @@
|
||||
from soil import BaseAgent, Environment, Simulation
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
async def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
await self.delay()
|
||||
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
run_sim(model=NoopEnvironment)
|
25
benchmarks/noop/soil_async_pqueue.py
Normal file
25
benchmarks/noop/soil_async_pqueue.py
Normal file
@ -0,0 +1,25 @@
|
||||
from soil import BaseAgent, Environment, Simulation, PQueueActivation
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
async def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
await self.delay()
|
||||
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = PQueueActivation
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
run_sim(model=NoopEnvironment)
|
24
benchmarks/noop/soil_gens.py
Normal file
24
benchmarks/noop/soil_gens.py
Normal file
@ -0,0 +1,24 @@
|
||||
from soil import BaseAgent, Environment, Simulation
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
yield self.delay()
|
||||
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
run_sim(model=NoopEnvironment)
|
25
benchmarks/noop/soil_gens_pqueue.py
Normal file
25
benchmarks/noop/soil_gens_pqueue.py
Normal file
@ -0,0 +1,25 @@
|
||||
from soil import BaseAgent, Environment, Simulation, PQueueActivation
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
yield self.delay()
|
||||
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = PQueueActivation
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
run_sim(model=NoopEnvironment)
|
21
benchmarks/noop/soil_step.py
Normal file
21
benchmarks/noop/soil_step.py
Normal file
@ -0,0 +1,21 @@
|
||||
from soil import BaseAgent, Environment, Simulation
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
self.num_calls += 1
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
run_sim(model=NoopEnvironment)
|
22
benchmarks/noop/soil_step_pqueue.py
Normal file
22
benchmarks/noop/soil_step_pqueue.py
Normal file
@ -0,0 +1,22 @@
|
||||
from soil import BaseAgent, Environment, Simulation, PQueueActivation
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
self.num_calls += 1
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = PQueueActivation
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
run_sim(model=NoopEnvironment)
|
29
benchmarks/noop/soilent_async.py
Normal file
29
benchmarks/noop/soilent_async.py
Normal file
@ -0,0 +1,29 @@
|
||||
from soil import Agent, Environment, Simulation
|
||||
from soilent import Scheduler
|
||||
|
||||
|
||||
class NoopAgent(Agent):
|
||||
num_calls = 0
|
||||
|
||||
async def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
# yield self.delay(1)
|
||||
await self.delay()
|
||||
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = Scheduler
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
res = run_sim(model=NoopEnvironment)
|
||||
for r in res:
|
||||
assert isinstance(r.schedule, Scheduler)
|
27
benchmarks/noop/soilent_async_pqueue.py
Normal file
27
benchmarks/noop/soilent_async_pqueue.py
Normal file
@ -0,0 +1,27 @@
|
||||
from soil import Agent, Environment
|
||||
from soilent import PQueueScheduler
|
||||
|
||||
|
||||
class NoopAgent(Agent):
|
||||
num_calls = 0
|
||||
|
||||
async def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
await self.delay()
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = PQueueScheduler
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
res = run_sim(model=NoopEnvironment)
|
||||
for r in res:
|
||||
assert isinstance(r.schedule, PQueueScheduler)
|
28
benchmarks/noop/soilent_gens.py
Normal file
28
benchmarks/noop/soilent_gens.py
Normal file
@ -0,0 +1,28 @@
|
||||
from soil import Agent, Environment, Simulation
|
||||
from soilent import Scheduler
|
||||
|
||||
|
||||
class NoopAgent(Agent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
# yield self.delay(1)
|
||||
yield self.delay()
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = Scheduler
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
res = run_sim(model=NoopEnvironment)
|
||||
for r in res:
|
||||
assert isinstance(r.schedule, Scheduler)
|
28
benchmarks/noop/soilent_gens_pqueue.py
Normal file
28
benchmarks/noop/soilent_gens_pqueue.py
Normal file
@ -0,0 +1,28 @@
|
||||
from soil import Agent, Environment
|
||||
from soilent import PQueueScheduler
|
||||
|
||||
|
||||
class NoopAgent(Agent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
while True:
|
||||
self.num_calls += 1
|
||||
# yield self.delay(1)
|
||||
yield
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = PQueueScheduler
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
|
||||
res = run_sim(model=NoopEnvironment)
|
||||
for r in res:
|
||||
assert isinstance(r.schedule, PQueueScheduler)
|
24
benchmarks/noop/soilent_step.py
Normal file
24
benchmarks/noop/soilent_step.py
Normal file
@ -0,0 +1,24 @@
|
||||
from soil import BaseAgent, Environment, Simulation
|
||||
from soilent import Scheduler
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
self.num_calls += 1
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = Scheduler
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
res = run_sim(model=NoopEnvironment)
|
||||
for r in res:
|
||||
assert isinstance(r.schedule, Scheduler)
|
24
benchmarks/noop/soilent_step_pqueue.py
Normal file
24
benchmarks/noop/soilent_step_pqueue.py
Normal file
@ -0,0 +1,24 @@
|
||||
from soil import BaseAgent, Environment, Simulation
|
||||
from soilent import PQueueScheduler
|
||||
|
||||
|
||||
class NoopAgent(BaseAgent):
|
||||
num_calls = 0
|
||||
|
||||
def step(self):
|
||||
self.num_calls += 1
|
||||
|
||||
class NoopEnvironment(Environment):
|
||||
num_agents = 100
|
||||
schedule_class = PQueueScheduler
|
||||
|
||||
def init(self):
|
||||
self.add_agents(NoopAgent, k=self.num_agents)
|
||||
self.add_agent_reporter("num_calls")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import *
|
||||
res = run_sim(model=NoopEnvironment)
|
||||
for r in res:
|
||||
assert isinstance(r.schedule, PQueueScheduler)
|
19
benchmarks/run.py
Executable file
19
benchmarks/run.py
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/env python
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='Profiler for soil')
|
||||
parser.add_argument('--suffix', default=None)
|
||||
parser.add_argument('files', nargs="+")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
for fname in args.files:
|
||||
suffix = ("_" + args.suffix) if args.suffix else ""
|
||||
simname = f"{fname.replace('/', '-')}{suffix}"
|
||||
profpath = os.path.join("profs", simname + ".prof")
|
||||
|
||||
print(f"Running {fname} and saving profile to {profpath}")
|
||||
subprocess.call(["python", "-m", "cProfile", "-o", profpath, fname])
|
4
benchmarks/virusonnetwork.csv
Normal file
4
benchmarks/virusonnetwork.csv
Normal file
@ -0,0 +1,4 @@
|
||||
command,mean,stddev,median,user,system,min,max,parameter_sim
|
||||
python virusonnetwork/mesa_basic.py,3.8381473157,0.0518143371442526,3.8475315791,3.873109219999999,0.55102658,3.7523016936,3.9095182436,mesa_basic.py
|
||||
python virusonnetwork/soil_step.py,3.2167258977000004,0.02337131987357665,3.2257620261,3.28374132,0.51343958,3.1792271306,3.2511521286000002,soil_step.py
|
||||
python virusonnetwork/soil_states.py,3.4908183217,0.03726734070349347,3.4912775086,3.5684004200000006,0.50416068,3.4272087936,3.5529207346000002,soil_states.py
|
|
32
benchmarks/virusonnetwork/_config.py
Normal file
32
benchmarks/virusonnetwork/_config.py
Normal file
@ -0,0 +1,32 @@
|
||||
import os
|
||||
|
||||
NUM_AGENTS = int(os.environ.get('NUM_AGENTS', 100))
|
||||
NUM_ITERS = int(os.environ.get('NUM_ITERS', 10))
|
||||
MAX_STEPS = int(os.environ.get('MAX_STEPS', 1000))
|
||||
|
||||
|
||||
def run_sim(model, **kwargs):
|
||||
from soil import Simulation
|
||||
opts = dict(model=model,
|
||||
dump=False,
|
||||
num_processes=1,
|
||||
parameters={'num_nodes': NUM_AGENTS,
|
||||
"avg_node_degree": 3,
|
||||
"initial_outbreak_size": 5,
|
||||
"virus_spread_chance": 0.25,
|
||||
"virus_check_frequency": 0.25,
|
||||
"recovery_chance": 0.3,
|
||||
"gain_resistance_chance": 0.1,
|
||||
},
|
||||
max_steps=MAX_STEPS,
|
||||
iterations=NUM_ITERS)
|
||||
opts.update(kwargs)
|
||||
its = Simulation(**opts).run()
|
||||
|
||||
assert all(it.schedule.steps == MAX_STEPS for it in its)
|
||||
ratios = list(it.resistant_susceptible_ratio() for it in its)
|
||||
print("Max - Avg - Min ratio:", max(ratios), sum(ratios)/len(ratios), min(ratios))
|
||||
assert all(sum([it.number_susceptible,
|
||||
it.number_infected,
|
||||
it.number_resistant]) == NUM_AGENTS for it in its)
|
||||
return its
|
180
benchmarks/virusonnetwork/mesa_basic.py
Normal file
180
benchmarks/virusonnetwork/mesa_basic.py
Normal file
@ -0,0 +1,180 @@
|
||||
# Verbatim copy from mesa
|
||||
# https://github.com/projectmesa/mesa/blob/976ddfc8a1e5feaaf8007a7abaa9abc7093881a0/examples/virus_on_network/virus_on_network/model.py
|
||||
import math
|
||||
from enum import Enum
|
||||
import networkx as nx
|
||||
|
||||
import mesa
|
||||
|
||||
|
||||
class State(Enum):
|
||||
SUSCEPTIBLE = 0
|
||||
INFECTED = 1
|
||||
RESISTANT = 2
|
||||
|
||||
|
||||
def number_state(model, state):
|
||||
return sum(1 for a in model.grid.get_all_cell_contents() if a.state is state)
|
||||
|
||||
|
||||
def number_infected(model):
|
||||
return number_state(model, State.INFECTED)
|
||||
|
||||
|
||||
def number_susceptible(model):
|
||||
return number_state(model, State.SUSCEPTIBLE)
|
||||
|
||||
|
||||
def number_resistant(model):
|
||||
return number_state(model, State.RESISTANT)
|
||||
|
||||
|
||||
class VirusOnNetwork(mesa.Model):
|
||||
"""A virus model with some number of agents"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
num_nodes=10,
|
||||
avg_node_degree=3,
|
||||
initial_outbreak_size=1,
|
||||
virus_spread_chance=0.4,
|
||||
virus_check_frequency=0.4,
|
||||
recovery_chance=0.3,
|
||||
gain_resistance_chance=0.5,
|
||||
**kwargs,
|
||||
):
|
||||
|
||||
self.num_nodes = num_nodes
|
||||
prob = avg_node_degree / self.num_nodes
|
||||
self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=prob)
|
||||
self.grid = mesa.space.NetworkGrid(self.G)
|
||||
self.schedule = mesa.time.RandomActivation(self)
|
||||
self.initial_outbreak_size = (
|
||||
initial_outbreak_size if initial_outbreak_size <= num_nodes else num_nodes
|
||||
)
|
||||
self.virus_spread_chance = virus_spread_chance
|
||||
self.virus_check_frequency = virus_check_frequency
|
||||
self.recovery_chance = recovery_chance
|
||||
self.gain_resistance_chance = gain_resistance_chance
|
||||
|
||||
self.datacollector = mesa.DataCollector(
|
||||
{
|
||||
"Ratio": "resistant_susceptible_ratio",
|
||||
"Infected": number_infected,
|
||||
"Susceptible": number_susceptible,
|
||||
"Resistant": number_resistant,
|
||||
}
|
||||
)
|
||||
|
||||
# Create agents
|
||||
for i, node in enumerate(self.G.nodes()):
|
||||
a = VirusAgent(
|
||||
i,
|
||||
self,
|
||||
State.SUSCEPTIBLE,
|
||||
self.virus_spread_chance,
|
||||
self.virus_check_frequency,
|
||||
self.recovery_chance,
|
||||
self.gain_resistance_chance,
|
||||
)
|
||||
self.schedule.add(a)
|
||||
# Add the agent to the node
|
||||
self.grid.place_agent(a, node)
|
||||
|
||||
# Infect some nodes
|
||||
infected_nodes = self.random.sample(list(self.G), self.initial_outbreak_size)
|
||||
for a in self.grid.get_cell_list_contents(infected_nodes):
|
||||
a.state = State.INFECTED
|
||||
|
||||
self.running = True
|
||||
self.datacollector.collect(self)
|
||||
|
||||
@property
|
||||
def number_susceptible(self):
|
||||
return number_susceptible(self)
|
||||
@property
|
||||
def number_resistant(self):
|
||||
return number_resistant(self)
|
||||
@property
|
||||
def number_infected(self):
|
||||
return number_infected(self)
|
||||
|
||||
def resistant_susceptible_ratio(self):
|
||||
try:
|
||||
return number_state(self, State.RESISTANT) / number_state(
|
||||
self, State.SUSCEPTIBLE
|
||||
)
|
||||
except ZeroDivisionError:
|
||||
return math.inf
|
||||
|
||||
def step(self):
|
||||
self.schedule.step()
|
||||
# collect data
|
||||
self.datacollector.collect(self)
|
||||
|
||||
def run_model(self, n):
|
||||
for i in range(n):
|
||||
self.step()
|
||||
|
||||
|
||||
class VirusAgent(mesa.Agent):
|
||||
def __init__(
|
||||
self,
|
||||
unique_id,
|
||||
model,
|
||||
initial_state,
|
||||
virus_spread_chance,
|
||||
virus_check_frequency,
|
||||
recovery_chance,
|
||||
gain_resistance_chance,
|
||||
):
|
||||
super().__init__(unique_id, model)
|
||||
|
||||
self.state = initial_state
|
||||
|
||||
self.virus_spread_chance = virus_spread_chance
|
||||
self.virus_check_frequency = virus_check_frequency
|
||||
self.recovery_chance = recovery_chance
|
||||
self.gain_resistance_chance = gain_resistance_chance
|
||||
|
||||
def try_to_infect_neighbors(self):
|
||||
neighbors_nodes = self.model.grid.get_neighbors(self.pos, include_center=False)
|
||||
susceptible_neighbors = [
|
||||
agent
|
||||
for agent in self.model.grid.get_cell_list_contents(neighbors_nodes)
|
||||
if agent.state is State.SUSCEPTIBLE
|
||||
]
|
||||
for a in susceptible_neighbors:
|
||||
if self.random.random() < self.virus_spread_chance:
|
||||
a.state = State.INFECTED
|
||||
|
||||
def try_gain_resistance(self):
|
||||
if self.random.random() < self.gain_resistance_chance:
|
||||
self.state = State.RESISTANT
|
||||
|
||||
def try_remove_infection(self):
|
||||
# Try to remove
|
||||
if self.random.random() < self.recovery_chance:
|
||||
# Success
|
||||
self.state = State.SUSCEPTIBLE
|
||||
self.try_gain_resistance()
|
||||
else:
|
||||
# Failed
|
||||
self.state = State.INFECTED
|
||||
|
||||
def try_check_situation(self):
|
||||
if self.random.random() < self.virus_check_frequency:
|
||||
# Checking...
|
||||
if self.state is State.INFECTED:
|
||||
self.try_remove_infection()
|
||||
|
||||
def step(self):
|
||||
if self.state is State.INFECTED:
|
||||
self.try_to_infect_neighbors()
|
||||
self.try_check_situation()
|
||||
|
||||
|
||||
from _config import run_sim
|
||||
|
||||
run_sim(model=VirusOnNetwork)
|
92
benchmarks/virusonnetwork/soil_states.py
Normal file
92
benchmarks/virusonnetwork/soil_states.py
Normal file
@ -0,0 +1,92 @@
|
||||
# Verbatim copy from mesa
|
||||
# https://github.com/projectmesa/mesa/blob/976ddfc8a1e5feaaf8007a7abaa9abc7093881a0/examples/virus_on_network/virus_on_network/model.py
|
||||
import math
|
||||
from enum import Enum
|
||||
import networkx as nx
|
||||
|
||||
from soil import *
|
||||
|
||||
|
||||
class VirusOnNetwork(Environment):
|
||||
"""A virus model with some number of agents"""
|
||||
num_nodes = 10
|
||||
avg_node_degree = 3
|
||||
initial_outbreak_size = 1
|
||||
virus_spread_chance = 0.4
|
||||
virus_check_frequency = 0.4
|
||||
recovery_chance = 0
|
||||
gain_resistance_chance = 0
|
||||
|
||||
def init(self):
|
||||
prob = self.avg_node_degree / self.num_nodes
|
||||
# Use internal seed with the networkx generator
|
||||
self.create_network(generator=nx.erdos_renyi_graph, n=self.num_nodes, p=prob)
|
||||
|
||||
self.initial_outbreak_size = min(self.initial_outbreak_size, self.num_nodes)
|
||||
self.populate_network(VirusAgent)
|
||||
|
||||
# Infect some nodes
|
||||
infected_nodes = self.random.sample(list(self.G), self.initial_outbreak_size)
|
||||
for a in self.agents(node_id=infected_nodes):
|
||||
a.set_state(VirusAgent.infected)
|
||||
assert self.number_infected == self.initial_outbreak_size
|
||||
|
||||
@report
|
||||
def resistant_susceptible_ratio(self):
|
||||
try:
|
||||
return self.number_resistant / self.number_susceptible
|
||||
except ZeroDivisionError:
|
||||
return math.inf
|
||||
|
||||
@report
|
||||
@property
|
||||
def number_infected(self):
|
||||
return self.count_agents(state_id=VirusAgent.infected.id)
|
||||
|
||||
@report
|
||||
@property
|
||||
def number_susceptible(self):
|
||||
return self.count_agents(state_id=VirusAgent.susceptible.id)
|
||||
|
||||
@report
|
||||
@property
|
||||
def number_resistant(self):
|
||||
return self.count_agents(state_id=VirusAgent.resistant.id)
|
||||
|
||||
|
||||
class VirusAgent(Agent):
|
||||
virus_spread_chance = None # Inherit from model
|
||||
virus_check_frequency = None # Inherit from model
|
||||
recovery_chance = None # Inherit from model
|
||||
gain_resistance_chance = None # Inherit from model
|
||||
just_been_infected = False
|
||||
|
||||
@state(default=True)
|
||||
def susceptible(self):
|
||||
if self.just_been_infected:
|
||||
self.just_been_infected = False
|
||||
return self.infected
|
||||
|
||||
@state
|
||||
def infected(self):
|
||||
susceptible_neighbors = self.get_neighbors(state_id=self.susceptible.id)
|
||||
for a in susceptible_neighbors:
|
||||
if self.prob(self.virus_spread_chance):
|
||||
a.just_been_infected = True
|
||||
if self.prob(self.virus_check_frequency):
|
||||
if self.prob(self.recovery_chance):
|
||||
if self.prob(self.gain_resistance_chance):
|
||||
return self.resistant
|
||||
else:
|
||||
return self.susceptible
|
||||
else:
|
||||
return self.infected
|
||||
|
||||
@state
|
||||
def resistant(self):
|
||||
return self.at(INFINITY)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import run_sim
|
||||
run_sim(model=VirusOnNetwork)
|
104
benchmarks/virusonnetwork/soil_step.py
Normal file
104
benchmarks/virusonnetwork/soil_step.py
Normal file
@ -0,0 +1,104 @@
|
||||
# Verbatim copy from mesa
|
||||
# https://github.com/projectmesa/mesa/blob/976ddfc8a1e5feaaf8007a7abaa9abc7093881a0/examples/virus_on_network/virus_on_network/model.py
|
||||
import math
|
||||
from enum import Enum
|
||||
import networkx as nx
|
||||
|
||||
from soil import *
|
||||
|
||||
|
||||
class State(Enum):
|
||||
SUSCEPTIBLE = 0
|
||||
INFECTED = 1
|
||||
RESISTANT = 2
|
||||
|
||||
|
||||
class VirusOnNetwork(Environment):
|
||||
"""A virus model with some number of agents"""
|
||||
num_nodes = 10
|
||||
avg_node_degree = 3
|
||||
initial_outbreak_size = 1
|
||||
virus_spread_chance = 0.4
|
||||
virus_check_frequency = 0.4
|
||||
recovery_chance = 0
|
||||
gain_resistance_chance = 0
|
||||
|
||||
def init(self):
|
||||
prob = self.avg_node_degree / self.num_nodes
|
||||
# Use internal seed with the networkx generator
|
||||
self.create_network(generator=nx.erdos_renyi_graph, n=self.num_nodes, p=prob)
|
||||
|
||||
self.initial_outbreak_size = min(self.initial_outbreak_size, self.num_nodes)
|
||||
self.populate_network(VirusAgent)
|
||||
|
||||
# Infect some nodes
|
||||
infected_nodes = self.random.sample(list(self.G), self.initial_outbreak_size)
|
||||
for a in self.agents(node_id=infected_nodes):
|
||||
a.status = State.INFECTED
|
||||
assert self.number_infected == self.initial_outbreak_size
|
||||
|
||||
@report
|
||||
def resistant_susceptible_ratio(self):
|
||||
try:
|
||||
return self.number_resistant / self.number_susceptible
|
||||
except ZeroDivisionError:
|
||||
return math.inf
|
||||
|
||||
@report
|
||||
@property
|
||||
def number_infected(self):
|
||||
return self.count_agents(status=State.INFECTED)
|
||||
|
||||
@report
|
||||
@property
|
||||
def number_susceptible(self):
|
||||
return self.count_agents(status=State.SUSCEPTIBLE)
|
||||
|
||||
@report
|
||||
@property
|
||||
def number_resistant(self):
|
||||
return self.count_agents(status=State.RESISTANT)
|
||||
|
||||
|
||||
|
||||
class VirusAgent(Agent):
|
||||
status = State.SUSCEPTIBLE
|
||||
virus_spread_chance = None # Inherit from model
|
||||
virus_check_frequency = None # Inherit from model
|
||||
recovery_chance = None # Inherit from model
|
||||
gain_resistance_chance = None # Inherit from model
|
||||
|
||||
def try_to_infect_neighbors(self):
|
||||
susceptible_neighbors = self.get_neighbors(status=State.SUSCEPTIBLE)
|
||||
for a in susceptible_neighbors:
|
||||
if self.prob(self.virus_spread_chance):
|
||||
a.status = State.INFECTED
|
||||
|
||||
def try_gain_resistance(self):
|
||||
if self.prob(self.gain_resistance_chance):
|
||||
self.status = State.RESISTANT
|
||||
return self.at(INFINITY)
|
||||
|
||||
def try_remove_infection(self):
|
||||
# Try to remove
|
||||
if self.prob(self.recovery_chance):
|
||||
# Success
|
||||
self.status = State.SUSCEPTIBLE
|
||||
return self.try_gain_resistance()
|
||||
|
||||
def try_check_situation(self):
|
||||
if self.prob(self.virus_check_frequency):
|
||||
# Checking...
|
||||
if self.status is State.INFECTED:
|
||||
return self.try_remove_infection()
|
||||
|
||||
def step(self):
|
||||
if self.status is State.INFECTED:
|
||||
self.try_to_infect_neighbors()
|
||||
return self.try_check_situation()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from _config import run_sim
|
||||
run_sim(model=VirusOnNetwork)
|
Loading…
Reference in New Issue
Block a user