mirror of https://github.com/gsi-upm/soil
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.mesa
parent
2869b1e1e6
commit
73282530fd
@ -0,0 +1,47 @@
|
||||
|
||||
|
||||
What are the main changes between version 0.3 and 0.2?
|
||||
######################################################
|
||||
|
||||
Version 0.3 is a major rewrite of the Soil system, focused on simplifying the API, aligning it with Mesa, and making it easier to use.
|
||||
Unfortunately, this comes at the cost of backwards compatibility.
|
||||
|
||||
We drew several lessons from the previous version of Soil, and tried to address them in this version.
|
||||
Mainly:
|
||||
|
||||
- The split between simulation configuration and simulation code was overly complicated for most use cases. As a result, most users ended up reusing configuration.
|
||||
- Storing **all** the simulation data in a database is costly and unnecessary for most use cases. For most use cases, only a handful of variables need to be stored. This fits nicely with Mesa's data collection system.
|
||||
- The API was too complex, and it was difficult to understand how to use it.
|
||||
- Most parts of the API were not aligned with Mesa, which made it difficult to use Mesa's features or to integrate Soil modules with Mesa code, especially for newcomers.
|
||||
- Many parts of the API were tightly coupled, which made it difficult to find bugs, test the system and add new features.
|
||||
|
||||
The 0.30 rewrite should provide a middle ground between Soil's opinionated approach and Mesa's flexibility.
|
||||
The new Soil is less configuration-centric.
|
||||
It aims to provide more modular and convenient functions, most of which can be used in vanilla Mesa.
|
||||
|
||||
How are agents assigned to nodes in the network
|
||||
###############################################
|
||||
|
||||
In principle, the generation of the network topology and the assignment of agents to nodes are two separate processes.
|
||||
There is a mechanism to initialize the agents, a mechanism to initialize the topology, and a mechanism to assign agents to nodes.
|
||||
|
||||
However, there are a myriad of ways to do this, and it is not clear which is the best way to do it.
|
||||
Earlier versions of Soil approached it by providing a fairly complex method of agent and node generation.
|
||||
The result was a very complex and difficult to understand system, which is was also prone to bugs and changes between versions.
|
||||
|
||||
Starting with version 0.3, the approach is to provide a simplified yet flexible system for generating the network topology and assigning agents to nodes.
|
||||
This is based on these methods:
|
||||
|
||||
- `create_network`
|
||||
- `add_agents` (and `add_agent`)
|
||||
- `populate_network`
|
||||
|
||||
The default implementation of `soil.Environment` accepts some parameters that will automatically do these steps for the most common case.
|
||||
All other cases can be handled by overriding the `init(self)` method and explicitly using these methods.
|
||||
|
||||
|
||||
Can Soil environments include more than one network / topology?
|
||||
###############################################################
|
||||
|
||||
Yes, but each network has to be included manually.
|
||||
Somewhere between 0.20 and 0.30 we included the ability to include multiple networks, but it was deemed too complex and was removed.
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
@ -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
|
@ -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()
|
@ -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
|
@ -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
|
@ -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()
|
@ -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
|
@ -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: {}
|
@ -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: {}
|
@ -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"]
|
@ -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.
|
@ -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'
|
@ -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)
|
@ -0,0 +1,4 @@
|
||||
def report(f: property):
|
||||
print(f.fget)
|
||||
setattr(f.fget, "add_to_report", True)
|
||||
return f
|
@ -0,0 +1,32 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing_extensions import Annotated
|
||||
import annotated_types
|
||||
from typing import *
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
class Parameter:
|
||||
pass
|
||||
|
||||
|
||||
def floatrange(
|
||||
*,
|
||||
gt: Optional[float] = None,
|
||||
ge: Optional[float] = None,
|
||||
lt: Optional[float] = None,
|
||||
le: Optional[float] = None,
|
||||
multiple_of: Optional[float] = None,
|
||||
) -> type[float]:
|
||||
return Annotated[
|
||||
float,
|
||||
annotated_types.Interval(gt=gt, ge=ge, lt=lt, le=le),
|
||||
annotated_types.MultipleOf(multiple_of) if multiple_of is not None else None,
|
||||
]
|
||||
|
||||
function = Annotated[Callable, Parameter]
|
||||
Integer = Annotated[int, Parameter]
|
||||
Float = Annotated[float, Parameter]
|
||||
|
||||
|
||||
probability = floatrange(ge=0, le=1)
|
@ -1,6 +0,0 @@
|
||||
from mesa.visualization.UserParam import UserSettableParameter
|
||||
|
||||
|
||||
class UserSettableParameter(UserSettableParameter):
|
||||
def __str__(self):
|
||||
return self.value
|
Loading…
Reference in New Issue