1
0
mirror of https://github.com/gsi-upm/soil synced 2025-08-23 19:52:19 +00:00

Big refactor v0.30

All test pass, except for the TestConfig suite, which is not too critical as the
plan for this version onwards is to avoid configuration as much as possible.
This commit is contained in:
J. Fernando Sánchez
2023-04-09 04:19:24 +02:00
parent 2869b1e1e6
commit 73282530fd
45 changed files with 721 additions and 82265 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +0,0 @@
---
version: '2'
name: simple
group: tests
dir_path: "/tmp/"
num_trials: 3
max_steps: 100
interval: 1
seed: "CompleteSeed!"
model_class: Environment
model_params:
am_i_complete: true
topology:
params:
generator: complete_graph
n: 12
environment:
agents:
agent_class: CounterModel
topology: true
state:
times: 1
# In this group we are not specifying any topology
fixed:
- name: 'Environment Agent 1'
agent_class: BaseAgent
group: environment
topology: false
hidden: true
state:
times: 10
- agent_class: CounterModel
id: 0
group: fixed_counters
state:
times: 1
total: 0
- agent_class: CounterModel
group: fixed_counters
id: 1
distribution:
- agent_class: CounterModel
weight: 1
group: distro_counters
state:
times: 3
- agent_class: AggregatedCounter
weight: 0.2
override:
- filter:
agent_class: AggregatedCounter
n: 2
state:
times: 5

View File

@@ -1,16 +0,0 @@
---
name: custom-generator
description: Using a custom generator for the network
num_trials: 3
max_steps: 100
interval: 1
network_params:
generator: mymodule.mygenerator
# These are custom parameters
n: 10
n_edges: 5
network_agents:
- agent_class: CounterModel
weight: 1
state:
state_id: 0

View File

@@ -1,6 +1,7 @@
from networkx import Graph
import random
import networkx as nx
from soil import Simulation, Environment, CounterModel, parameters
def mygenerator(n=5, n_edges=5):
@@ -20,3 +21,19 @@ def mygenerator(n=5, n_edges=5):
n_out = random.choice(nodes)
G.add_edge(n_in, n_out)
return G
class GeneratorEnv(Environment):
"""Using a custom generator for the network"""
generator: parameters.function = mygenerator
def init(self):
self.create_network(network_generator=self.generator, n=10, n_edges=5)
self.init_agents(CounterModel)
sim = Simulation(model=GeneratorEnv, max_steps=10, interval=1)
if __name__ == '__main__':
sim.run(dry_run=True)

View File

@@ -4,8 +4,7 @@ from soil.time import Delta
class Fibonacci(FSM):
"""Agent that only executes in t_steps that are Fibonacci numbers"""
defaults = {"prev": 1}
prev = 1
@default_state
@state
@@ -25,23 +24,18 @@ class Odds(FSM):
return None, Delta(1 + self.now % 2)
from soil import Simulation
from soil import Environment, Simulation
from networkx import complete_graph
simulation = Simulation(
model_params={
'agents':[
{'agent_class': Fibonacci, 'node_id': 0},
{'agent_class': Odds, 'node_id': 1}
],
'topology': {
'params': {
'generator': 'complete_graph',
'n': 2
}
},
},
max_time=100,
)
class TimeoutsEnv(Environment):
def init(self):
self.init_network(generator=complete_graph, n=2)
self.add_agent(agent_class=Fibonacci, node_id=0)
self.add_agent(agent_class=Odds, node_id=1)
sim = Simulation(model=TimeoutsEnv, max_steps=10, interval=1)
if __name__ == "__main__":
simulation.run(dry_run=True)
sim.run(dry_run=True)

View File

@@ -232,12 +232,10 @@ class Passenger(Evented, FSM):
self.die()
simulation = Simulation(
name="RideHailing",
model_class=City,
model_params={"n_passengers": 2},
seed="carsSeed",
)
simulation = Simulation(name="RideHailing",
model=City,
seed="carsSeed",
model_params=dict(n_passengers=2))
if __name__ == "__main__":
simulation.run()

View File

@@ -1,19 +0,0 @@
---
name: mesa_sim
group: tests
dir_path: "/tmp"
num_trials: 3
max_steps: 100
interval: 1
seed: '1'
model_class: social_wealth.MoneyEnv
model_params:
generator: social_wealth.graph_generator
agents:
topology: true
distribution:
- agent_class: social_wealth.SocialMoneyAgent
weight: 1
N: 10
width: 50
height: 50

View File

@@ -0,0 +1,7 @@
from soil import Simulation
from social_wealth import MoneyEnv, graph_generator
sim = Simulation(name="mesa_sim", dry_run=True, max_steps=10, interval=2, model=MoneyEnv, model_params=dict(generator=graph_generator, N=10, width=50, height=50))
if __name__ == "__main__":
sim.run()

View File

@@ -1,5 +1,5 @@
from mesa.visualization.ModularVisualization import ModularServer
from soil.visualization import UserSettableParameter
from mesa.visualization.UserParam import Slider, Choice
from mesa.visualization.modules import ChartModule, NetworkModule, CanvasGrid
from social_wealth import MoneyEnv, graph_generator, SocialMoneyAgent
import networkx as nx
@@ -64,8 +64,7 @@ chart = ChartModule(
)
model_params = {
"N": UserSettableParameter(
"slider",
"N": Slider(
"N",
5,
1,
@@ -73,8 +72,7 @@ model_params = {
1,
description="Choose how many agents to include in the model",
),
"height": UserSettableParameter(
"slider",
"height": Slider(
"height",
5,
5,
@@ -82,8 +80,7 @@ model_params = {
1,
description="Grid height",
),
"width": UserSettableParameter(
"slider",
"width": Slider(
"width",
5,
5,
@@ -91,8 +88,7 @@ model_params = {
1,
description="Grid width",
),
"agent_class": UserSettableParameter(
"choice",
"agent_class": Choice(
"Agent class",
value="MoneyAgent",
choices=["MoneyAgent", "SocialMoneyAgent"],

View File

@@ -1,133 +0,0 @@
---
default_state: {}
environment_agents: []
environment_params:
prob_neighbor_spread: 0.0
prob_tv_spread: 0.01
interval: 1
max_steps: 300
name: Sim_all_dumb
network_agents:
- agent_class: newsspread.DumbViewer
state:
has_tv: false
weight: 1
- agent_class: newsspread.DumbViewer
state:
has_tv: true
weight: 1
network_params:
generator: barabasi_albert_graph
n: 500
m: 5
num_trials: 50
---
default_state: {}
environment_agents: []
environment_params:
prob_neighbor_spread: 0.0
prob_tv_spread: 0.01
interval: 1
max_steps: 300
name: Sim_half_herd
network_agents:
- agent_class: newsspread.DumbViewer
state:
has_tv: false
weight: 1
- agent_class: newsspread.DumbViewer
state:
has_tv: true
weight: 1
- agent_class: newsspread.HerdViewer
state:
has_tv: false
weight: 1
- agent_class: newsspread.HerdViewer
state:
has_tv: true
weight: 1
network_params:
generator: barabasi_albert_graph
n: 500
m: 5
num_trials: 50
---
default_state: {}
environment_agents: []
environment_params:
prob_neighbor_spread: 0.0
prob_tv_spread: 0.01
interval: 1
max_steps: 300
name: Sim_all_herd
network_agents:
- agent_class: newsspread.HerdViewer
state:
has_tv: true
state_id: neutral
weight: 1
- agent_class: newsspread.HerdViewer
state:
has_tv: true
state_id: neutral
weight: 1
network_params:
generator: barabasi_albert_graph
n: 500
m: 5
num_trials: 50
---
default_state: {}
environment_agents: []
environment_params:
prob_neighbor_spread: 0.0
prob_tv_spread: 0.01
prob_neighbor_cure: 0.1
interval: 1
max_steps: 300
name: Sim_wise_herd
network_agents:
- agent_class: newsspread.HerdViewer
state:
has_tv: true
state_id: neutral
weight: 1
- agent_class: newsspread.WiseViewer
state:
has_tv: true
weight: 1
network_params:
generator: barabasi_albert_graph
n: 500
m: 5
num_trials: 50
---
default_state: {}
environment_agents: []
environment_params:
prob_neighbor_spread: 0.0
prob_tv_spread: 0.01
prob_neighbor_cure: 0.1
interval: 1
max_steps: 300
name: Sim_all_wise
network_agents:
- agent_class: newsspread.WiseViewer
state:
has_tv: true
state_id: neutral
weight: 1
- agent_class: newsspread.WiseViewer
state:
has_tv: true
weight: 1
network_params:
generator: barabasi_albert_graph
n: 500
m: 5
network_params:
generator: barabasi_albert_graph
n: 500
m: 5
num_trials: 50

View File

@@ -1,87 +0,0 @@
from soil.agents import FSM, NetworkAgent, state, default_state, prob
import logging
class DumbViewer(FSM, NetworkAgent):
"""
A viewer that gets infected via TV (if it has one) and tries to infect
its neighbors once it's infected.
"""
prob_neighbor_spread = 0.5
prob_tv_spread = 0.1
has_been_infected = False
@default_state
@state
def neutral(self):
if self["has_tv"]:
if self.prob(self.model["prob_tv_spread"]):
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):
if self.prob(self.model["prob_neighbor_spread"]):
neighbor.infect()
def infect(self):
"""
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
"""
self.has_been_infected = True
class HerdViewer(DumbViewer):
"""
A viewer whose probability of infection depends on the state of its neighbors.
"""
def infect(self):
"""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()
prob_infect = self.model["prob_neighbor_spread"] * infected / total
self.debug("prob_infect", prob_infect)
if self.prob(prob_infect):
self.has_been_infected = True
class WiseViewer(HerdViewer):
"""
A viewer that can change its mind.
"""
defaults = {
"prob_neighbor_spread": 0.5,
"prob_neighbor_cure": 0.25,
"prob_tv_spread": 0.1,
}
@state
def cured(self):
prob_cure = self.model["prob_neighbor_cure"]
for neighbor in self.get_neighbors(state_id=self.infected.id):
if self.prob(prob_cure):
try:
neighbor.cure()
except AttributeError:
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)
prob_cure = self.model["prob_neighbor_cure"] * (cured / infected)
if self.prob(prob_cure):
return self.cured

View File

@@ -0,0 +1,129 @@
from soil.agents import FSM, NetworkAgent, state, default_state, prob
from soil.parameters import *
import logging
from soil.environment import Environment
class DumbViewer(FSM, NetworkAgent):
"""
A viewer that gets infected via TV (if it has one) and tries to infect
its neighbors once it's infected.
"""
has_been_infected: bool = False
has_tv: bool = False
@default_state
@state
def neutral(self):
if self.has_tv:
if self.prob(self.get("prob_tv_spread")):
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):
if self.prob(self.get("prob_neighbor_spread")):
neighbor.infect()
def infect(self):
"""
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
"""
self.has_been_infected = True
class HerdViewer(DumbViewer):
"""
A viewer whose probability of infection depends on the state of its neighbors.
"""
def infect(self):
"""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()
prob_infect = self.get("prob_neighbor_spread") * infected / total
self.debug("prob_infect", prob_infect)
if self.prob(prob_infect):
self.has_been_infected = True
class WiseViewer(HerdViewer):
"""
A viewer that can change its mind.
"""
@state
def cured(self):
prob_cure = self.get("prob_neighbor_cure")
for neighbor in self.get_neighbors(state_id=self.infected.id):
if self.prob(prob_cure):
try:
neighbor.cure()
except AttributeError:
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)
prob_cure = self.get("prob_neighbor_cure") * (cured / infected)
if self.prob(prob_cure):
return self.cured
class NewsSpread(Environment):
ratio_dumb: probability = 1,
ratio_herd: probability = 0,
ratio_wise: probability = 0,
prob_tv_spread: probability = 0.1,
prob_neighbor_spread: probability = 0.1,
prob_neighbor_cure: probability = 0.05,
def init(self):
self.populate_network([DumbViewer, HerdViewer, WiseViewer], [self.ratio_dumb, self.ratio_herd, self.ratio_wise])
from itertools import permutations
from soil import Simulation
# We want to investigate the effect of different agent distributions on the spread of news.
# To do that, we will run different simulations, with a varying ratio of DumbViewers, HerdViewers, and WiseViewers
# Because the effect of these agents might also depend on the network structure, we will run our simulations on two different networks:
# one with a small-world structure and one with a connected structure.
for [r1, r2, r3] in permutations([0, 0.5, 1.0], 3):
for (generator, netparams) in {
"barabasi_albert_graph": {"m": 5},
"erdos_renyi_graph": {"p": 0.1},
}.items():
print(r1, r2, r3, generator)
# Create new simulation
netparams["n"] = 500
sim = Simulation(
model=NewsSpread,
model_params={
"ratio_dumb": r1,
"ratio_herd": r2,
"ratio_wise": r3,
"network_generator": generator,
"network_params": netparams,
"prob_neighbor_spread": 0,
},
num_trials=50,
max_steps=300,
dry_run=True,
)
# Run all the necessary instances
sim.run()

View File

@@ -1,7 +1,7 @@
"""
Example of a fully programmatic simulation, without definition files.
"""
from soil import Simulation, agents
from soil import Simulation, Environment, agents
from networkx import Graph
import logging
@@ -25,23 +25,18 @@ class MyAgent(agents.FSM):
self.info("This runs 2/10 times on average")
class ProgrammaticEnv(Environment):
def init(self):
self.create_network(generator=mygenerator)
self.populate_network(agent_class=MyAgent)
self.add_agent_reporter('times_run')
simulation = Simulation(
name="Programmatic",
model_params={
'topology': {
'params': {
'generator': mygenerator
},
},
'agents': {
'distribution': [{
'agent_class': MyAgent,
'topology': True,
}]
}
},
model=ProgrammaticEnv,
seed='Program',
agent_reporters={'times_run': 'times_run'},
num_trials=1,
max_time=100,
dry_run=True,

View File

@@ -1,26 +0,0 @@
---
name: pubcrawl
num_trials: 3
max_steps: 10
dump: false
network_params:
# Generate 100 empty nodes. They will be assigned a network agent
generator: empty_graph
n: 30
network_agents:
- agent_class: pubcrawl.Patron
description: Extroverted patron
state:
openness: 1.0
weight: 9
- agent_class: pubcrawl.Patron
description: Introverted patron
state:
openness: 0.1
weight: 1
environment_agents:
- agent_class: pubcrawl.Police
environment_class: pubcrawl.CityPubs
environment_params:
altercations: 0
number_of_pubs: 3

View File

@@ -1,6 +1,7 @@
from soil.agents import FSM, NetworkAgent, state, default_state
from soil import Environment
from soil import Environment, Simulation, parameters
from itertools import islice
import networkx as nx
import logging
@@ -8,19 +9,23 @@ class CityPubs(Environment):
"""Environment with Pubs"""
level = logging.INFO
def __init__(self, *args, number_of_pubs=3, pub_capacity=10, **kwargs):
super(CityPubs, self).__init__(*args, **kwargs)
number_of_pubs: parameters.Integer = 3
ratio_extroverted: parameters.probability = 0.1
pub_capacity: parameters.Integer = 10
def init(self):
pubs = {}
for i in range(number_of_pubs):
for i in range(self.number_of_pubs):
newpub = {
"name": "The awesome pub #{}".format(i),
"open": True,
"capacity": pub_capacity,
"capacity": self.pub_capacity,
"occupancy": 0,
}
pubs[newpub["name"]] = newpub
self.add_agent(agent_class=Police, node_id=0)
self["pubs"] = pubs
self.populate_network([{"openness": 0.1}, {"openness": 1}], [self.ratio_extroverted, 1-self.ratio_extroverted], agent_class=Patron)
def enter(self, pub_id, *nodes):
"""Agents will try to enter. The pub checks if it is possible"""
@@ -169,7 +174,20 @@ class Police(FSM):
self.info("No trash to take out. Too bad.")
if __name__ == "__main__":
from soil import run_from_config
sim = Simulation(
name="pubcrawl",
num_trials=3,
max_steps=10,
dry_run=True,
model_params=dict(
generator=nx.empty_graph,
network_params={"n": 30},
model=CityPubs,
altercations=0,
number_of_pubs=3,
)
)
run_from_config("pubcrawl.yml", dry_run=True, dump=None, parallel=False)
if __name__ == "__main__":
sim.run(parallel=False)

View File

@@ -1,42 +0,0 @@
---
version: '2'
name: rabbits_basic
num_trials: 1
seed: MySeed
description: null
group: null
interval: 1.0
max_time: 100
model_class: rabbit_agents.RabbitEnv
model_params:
agents:
topology: true
distribution:
- agent_class: rabbit_agents.Male
weight: 1
- agent_class: rabbit_agents.Female
weight: 1
fixed:
- agent_class: rabbit_agents.RandomAccident
topology: false
hidden: true
state:
group: environment
state:
group: network
mating_prob: 0.1
prob_death: 0.001
topology:
fixed:
directed: true
links: []
nodes:
- id: 1
- id: 0
model_reporters:
num_males: 'num_males'
num_females: 'num_females'
num_rabbits: |
py:lambda env: env.num_males + env.num_females
extra:
visualization_params: {}

View File

@@ -1,42 +0,0 @@
---
version: '2'
name: rabbits_improved
num_trials: 1
seed: MySeed
description: null
group: null
interval: 1.0
max_time: 100
model_class: rabbit_agents.RabbitEnv
model_params:
agents:
topology: true
distribution:
- agent_class: rabbit_agents.Male
weight: 1
- agent_class: rabbit_agents.Female
weight: 1
fixed:
- agent_class: rabbit_agents.RandomAccident
topology: false
hidden: true
state:
group: environment
state:
group: network
mating_prob: 0.1
prob_death: 0.001
topology:
fixed:
directed: true
links: []
nodes:
- id: 1
- id: 0
model_reporters:
num_males: 'num_males'
num_females: 'num_females'
num_rabbits: |
py:lambda env: env.num_males + env.num_females
extra:
visualization_params: {}

View File

@@ -1,23 +1,20 @@
from soil import FSM, state, default_state, BaseAgent, NetworkAgent, Environment
from soil import FSM, state, default_state, BaseAgent, NetworkAgent, Environment, Simulation
from soil.time import Delta
from enum import Enum
from collections import Counter
import logging
import math
from rabbits_basic_sim import RabbitEnv
class RabbitEnv(Environment):
@property
def num_rabbits(self):
return self.count_agents(agent_class=Rabbit)
@property
def num_males(self):
return self.count_agents(agent_class=Male)
@property
def num_females(self):
return self.count_agents(agent_class=Female)
class RabbitsImprovedEnv(RabbitEnv):
def init(self):
"""Initialize the environment with the new versions of the agents"""
a1 = self.add_node(Male)
a2 = self.add_node(Female)
a1.add_edge(a2)
self.add_agent(RandomAccident)
class Rabbit(FSM, NetworkAgent):
@@ -150,8 +147,7 @@ class RandomAccident(BaseAgent):
self.debug("Rabbits alive: {}".format(rabbits_alive))
if __name__ == "__main__":
from soil import easy
sim = Simulation(model=RabbitsImprovedEnv, max_time=100, seed="MySeed", num_trials=1)
with easy("rabbits.yml") as sim:
sim.run()
if __name__ == "__main__":
sim.run()

View File

@@ -1,20 +1,29 @@
from soil import FSM, state, default_state, BaseAgent, NetworkAgent, Environment
from soil import FSM, state, default_state, BaseAgent, NetworkAgent, Environment, Simulation, report, parameters as params
from collections import Counter
import logging
import math
class RabbitEnv(Environment):
prob_death = 1e-100
prob_death: params.probability = 1e-100
def init(self):
a1 = self.add_node(Male)
a2 = self.add_node(Female)
a1.add_edge(a2)
self.add_agent(RandomAccident)
@report
@property
def num_rabbits(self):
return self.count_agents(agent_class=Rabbit)
@report
@property
def num_males(self):
return self.count_agents(agent_class=Male)
@report
@property
def num_females(self):
return self.count_agents(agent_class=Female)
@@ -145,8 +154,8 @@ class RandomAccident(BaseAgent):
self.debug("Rabbits alive: {}".format(rabbits_alive))
if __name__ == "__main__":
from soil import easy
with easy("rabbits.yml") as sim:
sim.run()
sim = Simulation(model=RabbitEnv, max_time=100, seed="MySeed", num_trials=1)
if __name__ == "__main__":
sim.run()

View File

@@ -2,7 +2,7 @@
Example of setting a
Example of a fully programmatic simulation, without definition files.
"""
from soil import Simulation, agents
from soil import Simulation, agents, Environment
from soil.time import Delta
@@ -29,11 +29,15 @@ class MyAgent(agents.FSM):
return None, Delta(self.random.expovariate(1 / 16))
class RandomEnv(Environment):
def init(self):
self.add_agent(agent_class=MyAgent)
s = Simulation(
name="Programmatic",
model_params={
'agents': [{'agent_class': MyAgent}],
},
model=RandomEnv,
num_trials=1,
max_time=100,
dry_run=True,

View File

@@ -1,30 +0,0 @@
---
sampler:
method: "SALib.sample.morris.sample"
N: 10
template:
group: simple
num_trials: 1
interval: 1
max_steps: 2
seed: "CompleteSeed!"
dump: false
model_params:
network_params:
generator: complete_graph
n: 10
network_agents:
- agent_class: CounterModel
weight: "{{ x1 }}"
state:
state_id: 0
- agent_class: AggregatedCounter
weight: "{{ 1 - x1 }}"
name: "{{ x3 }}"
skip_test: true
vars:
bounds:
x1: [0, 1]
x2: [1, 2]
fixed:
x3: ["a", "b", "c"]

View File

@@ -1,62 +0,0 @@
name: TerroristNetworkModel_sim
max_steps: 150
num_trials: 1
model_params:
network_params:
generator: random_geometric_graph
radius: 0.2
# generator: geographical_threshold_graph
# theta: 20
n: 100
network_agents:
- agent_class: TerroristNetworkModel.TerroristNetworkModel
weight: 0.8
state:
id: civilian # Civilians
- agent_class: TerroristNetworkModel.TerroristNetworkModel
weight: 0.1
state:
id: leader # Leaders
- agent_class: TerroristNetworkModel.TrainingAreaModel
weight: 0.05
state:
id: terrorist # Terrorism
- agent_class: TerroristNetworkModel.HavenModel
weight: 0.05
state:
id: civilian # Civilian
# TerroristSpreadModel
information_spread_intensity: 0.7
terrorist_additional_influence: 0.035
max_vulnerability: 0.7
prob_interaction: 0.5
# TrainingAreaModel and HavenModel
training_influence: 0.20
haven_influence: 0.20
# TerroristNetworkModel
vision_range: 0.30
sphere_influence: 2
weight_social_distance: 0.035
weight_link_distance: 0.035
visualization_params:
# Icons downloaded from https://www.iconfinder.com/
shape_property: agent
shapes:
TrainingAreaModel: target
HavenModel: home
TerroristNetworkModel: person
colors:
- attr_id: civilian
color: '#40de40'
- attr_id: terrorist
color: red
- attr_id: leader
color: '#c16a6a'
background_image: 'map_4800x2860.jpg'
background_opacity: '0.9'
background_filter_color: 'blue'
skip_test: true # This simulation takes too long for automated tests.

View File

@@ -1,6 +1,43 @@
import networkx as nx
from soil.agents import Geo, NetworkAgent, FSM, state, default_state
from soil import Environment
from soil.agents import Geo, NetworkAgent, FSM, custom, state, default_state
from soil import Environment, Simulation
from soil.parameters import *
class TerroristEnvironment(Environment):
generator: function = nx.random_geometric_graph
n: Integer = 100
radius: Float = 0.2
information_spread_intensity: probability = 0.7
terrorist_additional_influence: probability = 0.03
terrorist_additional_influence: probability = 0.035
max_vulnerability: probability = 0.7
prob_interaction: probability = 0.5
# TrainingAreaModel and HavenModel
training_influence: probability = 0.20
haven_influence: probability = 0.20
# TerroristNetworkModel
vision_range: Float = 0.30
sphere_influence: Integer = 2
weight_social_distance: Float = 0.035
weight_link_distance: Float = 0.035
ratio_civil: probability = 0.8
ratio_leader: probability = 0.1
ratio_training: probability = 0.05
ratio_haven: probability = 0.05
def init(self):
self.create_network(generator=self.generator, n=self.n, radius=self.radius)
self.populate_network([
TerroristNetworkModel.w(state_id='civilian'),
TerroristNetworkModel.w(state_id='leader'),
TrainingAreaModel,
HavenModel
], [self.ratio_civil, self.ratio_leader, self.ratio_trainig, self.ratio_heaven])
class TerroristSpreadModel(FSM, Geo):
@@ -17,36 +54,21 @@ class TerroristSpreadModel(FSM, Geo):
prob_interaction
"""
def __init__(self, model=None, unique_id=0, state=()):
super().__init__(model=model, unique_id=unique_id, state=state)
self.information_spread_intensity = model.environment_params[
"information_spread_intensity"
]
self.terrorist_additional_influence = model.environment_params[
"terrorist_additional_influence"
]
self.prob_interaction = model.environment_params["prob_interaction"]
if self["id"] == self.civilian.id: # Civilian
self.mean_belief = self.random.uniform(0.00, 0.5)
elif self["id"] == self.terrorist.id: # Terrorist
def init(self):
if self.state_id == self.civilian.id: # Civilian
self.mean_belief = self.model.random.uniform(0.00, 0.5)
elif self.state_id == self.terrorist.id: # Terrorist
self.mean_belief = self.random.uniform(0.8, 1.00)
elif self["id"] == self.leader.id: # Leader
elif self.state_id == self.leader.id: # Leader
self.mean_belief = 1.00
else:
raise Exception("Invalid state id: {}".format(self["id"]))
if "min_vulnerability" in model.environment_params:
self.vulnerability = self.random.uniform(
model.environment_params["min_vulnerability"],
model.environment_params["max_vulnerability"],
)
else:
self.vulnerability = self.random.uniform(
0, model.environment_params["max_vulnerability"]
)
self.vulnerability = self.random.uniform(
self.get("min_vulnerability", 0), self.get("max_vulnerability", 1)
)
@default_state
@state
def civilian(self):
neighbours = list(self.get_neighbors(agent_class=TerroristSpreadModel))
@@ -287,3 +309,32 @@ class TerroristNetworkModel(TerroristSpreadModel):
return nx.shortest_path_length(self.G, self.id, target)
except nx.NetworkXNoPath:
return float("inf")
sim = Simulation(
model=TerroristEnvironment,
num_trials=1,
name="TerroristNetworkModel_sim",
max_steps=150,
skip_test=True,
dry_run=True,
)
# TODO: integrate visualization
# visualization_params:
# # Icons downloaded from https://www.iconfinder.com/
# shape_property: agent
# shapes:
# TrainingAreaModel: target
# HavenModel: home
# TerroristNetworkModel: person
# colors:
# - attr_id: civilian
# color: '#40de40'
# - attr_id: terrorist
# color: red
# - attr_id: leader
# color: '#c16a6a'
# background_image: 'map_4800x2860.jpg'
# background_opacity: '0.9'
# background_filter_color: 'blue'

View File

@@ -1,15 +0,0 @@
---
name: torvalds_example
max_steps: 10
interval: 2
model_params:
agent_class: CounterModel
default_state:
skill_level: 'beginner'
network_params:
path: 'torvalds.edgelist'
states:
Torvalds:
skill_level: 'God'
balkian:
skill_level: 'developer'

16
examples/torvalds_sim.py Normal file
View File

@@ -0,0 +1,16 @@
from soil import Environment, Simulation, CounterModel
class TorvaldsEnv(Environment):
def init(self):
self.create_network(path='torvalds.edgelist')
self.populate_network(CounterModel, skill_level='beginner')
print("Agentes: ", list(self.network_agents))
self.find_one(node_id="Torvalds").skill_level = 'God'
self.find_one(node_id="balkian").skill_level = 'developer'
sim = Simulation(name='torvalds_example',
max_steps=10,
interval=2,
model=TorvaldsEnv)