1
0
mirror of https://github.com/gsi-upm/soil synced 2024-09-21 07:41:43 +00:00
soil/examples/newsspread/newsspread.py

88 lines
2.6 KiB
Python
Raw Normal View History

2022-09-16 16:13:39 +00:00
from soil.agents import FSM, NetworkAgent, state, default_state, prob
import logging
2022-09-16 16:13:39 +00:00
class DumbViewer(FSM, NetworkAgent):
2022-10-17 18:23:57 +00:00
"""
A viewer that gets infected via TV (if it has one) and tries to infect
its neighbors once it's infected.
2022-10-17 18:23:57 +00:00
"""
prob_neighbor_spread = 0.5
prob_tv_spread = 0.1
has_been_infected = False
@default_state
@state
def neutral(self):
2022-10-17 18:23:57 +00:00
if self["has_tv"]:
if self.prob(self.model["prob_tv_spread"]):
2022-04-04 14:47:58 +00:00
return self.infected
if self.has_been_infected:
return self.infected
@state
def infected(self):
for neighbor in self.get_neighbors(state_id=self.neutral.id):
2022-10-17 18:23:57 +00:00
if self.prob(self.model["prob_neighbor_spread"]):
neighbor.infect()
def infect(self):
2022-10-17 18:23:57 +00:00
"""
2022-04-04 14:47:58 +00:00
This is not a state. It is a function that other agents can use to try to
infect this agent. DumbViewer always gets infected, but other agents like
HerdViewer might not become infected right away
2022-10-17 18:23:57 +00:00
"""
2022-04-04 14:47:58 +00:00
self.has_been_infected = True
class HerdViewer(DumbViewer):
2022-10-17 18:23:57 +00:00
"""
A viewer whose probability of infection depends on the state of its neighbors.
2022-10-17 18:23:57 +00:00
"""
def infect(self):
2022-10-17 18:23:57 +00:00
"""Notice again that this is NOT a state. See DumbViewer.infect for reference"""
infected = self.count_neighbors(state_id=self.infected.id)
total = self.count_neighbors()
2022-10-17 18:23:57 +00:00
prob_infect = self.model["prob_neighbor_spread"] * infected / total
self.debug("prob_infect", prob_infect)
2022-10-13 20:43:16 +00:00
if self.prob(prob_infect):
self.has_been_infected = True
class WiseViewer(HerdViewer):
2022-10-17 18:23:57 +00:00
"""
A viewer that can change its mind.
2022-10-17 18:23:57 +00:00
"""
defaults = {
2022-10-17 18:23:57 +00:00
"prob_neighbor_spread": 0.5,
"prob_neighbor_cure": 0.25,
"prob_tv_spread": 0.1,
}
@state
def cured(self):
2022-10-17 18:23:57 +00:00
prob_cure = self.model["prob_neighbor_cure"]
for neighbor in self.get_neighbors(state_id=self.infected.id):
2022-10-13 20:43:16 +00:00
if self.prob(prob_cure):
try:
neighbor.cure()
except AttributeError:
2022-10-17 18:23:57 +00:00
self.debug("Viewer {} cannot be cured".format(neighbor.id))
def cure(self):
self.has_been_cured = True
@state
def infected(self):
if self.has_been_cured:
return self.cured
cured = max(self.count_neighbors(self.cured.id), 1.0)
infected = max(self.count_neighbors(self.infected.id), 1.0)
2022-10-17 18:23:57 +00:00
prob_cure = self.model["prob_neighbor_cure"] * (cured / infected)
2022-10-13 20:43:16 +00:00
if self.prob(prob_cure):
2022-04-04 14:47:58 +00:00
return self.cured