mirror of
https://github.com/gsi-upm/soil
synced 2025-08-23 19:52:19 +00:00
WIP: all tests pass
This commit is contained in:
@@ -1,49 +1,50 @@
|
||||
---
|
||||
version: '2'
|
||||
general:
|
||||
id: simple
|
||||
group: tests
|
||||
dir_path: "/tmp/"
|
||||
num_trials: 3
|
||||
max_time: 100
|
||||
interval: 1
|
||||
seed: "CompleteSeed!"
|
||||
topologies:
|
||||
default:
|
||||
params:
|
||||
generator: complete_graph
|
||||
n: 10
|
||||
agents:
|
||||
default:
|
||||
name: simple
|
||||
group: tests
|
||||
dir_path: "/tmp/"
|
||||
num_trials: 3
|
||||
max_time: 100
|
||||
interval: 1
|
||||
seed: "CompleteSeed!"
|
||||
model_class: Environment
|
||||
model_params:
|
||||
topologies:
|
||||
default:
|
||||
params:
|
||||
generator: complete_graph
|
||||
n: 4
|
||||
agents:
|
||||
agent_class: CounterModel
|
||||
state:
|
||||
group: network
|
||||
times: 1
|
||||
network:
|
||||
topology: 'default'
|
||||
distribution:
|
||||
- agent_class: CounterModel
|
||||
weight: 0.4
|
||||
weight: 0.25
|
||||
state:
|
||||
state_id: 0
|
||||
times: 1
|
||||
- agent_class: AggregatedCounter
|
||||
weight: 0.6
|
||||
override:
|
||||
- filter:
|
||||
node_id: 0
|
||||
weight: 0.5
|
||||
state:
|
||||
name: 'The first node'
|
||||
times: 2
|
||||
override:
|
||||
- filter:
|
||||
node_id: 1
|
||||
state:
|
||||
name: 'The second node'
|
||||
|
||||
environment:
|
||||
fixed:
|
||||
- name: 'Environment Agent 1'
|
||||
agent_class: CounterModel
|
||||
name: 'Node 1'
|
||||
- filter:
|
||||
node_id: 2
|
||||
state:
|
||||
name: 'Node 2'
|
||||
fixed:
|
||||
- agent_class: BaseAgent
|
||||
hidden: true
|
||||
topology: null
|
||||
state:
|
||||
name: 'Environment Agent 1'
|
||||
times: 10
|
||||
environment:
|
||||
environment_class: Environment
|
||||
params:
|
||||
am_i_complete: true
|
||||
group: environment
|
||||
am_i_complete: true
|
||||
|
@@ -8,17 +8,20 @@ interval: 1
|
||||
seed: "CompleteSeed!"
|
||||
network_params:
|
||||
generator: complete_graph
|
||||
n: 10
|
||||
n: 4
|
||||
network_agents:
|
||||
- agent_class: CounterModel
|
||||
weight: 0.4
|
||||
weight: 0.25
|
||||
state:
|
||||
state_id: 0
|
||||
times: 1
|
||||
- agent_class: AggregatedCounter
|
||||
weight: 0.6
|
||||
weight: 0.5
|
||||
state:
|
||||
times: 2
|
||||
environment_agents:
|
||||
- agent_id: 'Environment Agent 1'
|
||||
agent_class: CounterModel
|
||||
agent_class: BaseAgent
|
||||
state:
|
||||
times: 10
|
||||
environment_class: Environment
|
||||
@@ -28,5 +31,7 @@ agent_class: CounterModel
|
||||
default_state:
|
||||
times: 1
|
||||
states:
|
||||
- name: 'The first node'
|
||||
- name: 'The second node'
|
||||
1:
|
||||
name: 'Node 1'
|
||||
2:
|
||||
name: 'Node 2'
|
||||
|
@@ -8,7 +8,7 @@ class Dead(agents.FSM):
|
||||
@agents.default_state
|
||||
@agents.state
|
||||
def only(self):
|
||||
self.die()
|
||||
return self.die()
|
||||
|
||||
class TestMain(TestCase):
|
||||
def test_die_raises_exception(self):
|
||||
@@ -19,4 +19,6 @@ class TestMain(TestCase):
|
||||
|
||||
def test_die_returns_infinity(self):
|
||||
d = Dead(unique_id=0, model=environment.Environment())
|
||||
assert d.step().abs(0) == stime.INFINITY
|
||||
ret = d.step().abs(0)
|
||||
print(ret, 'next')
|
||||
assert ret == stime.INFINITY
|
||||
|
@@ -1,91 +0,0 @@
|
||||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
import pandas as pd
|
||||
import yaml
|
||||
from functools import partial
|
||||
|
||||
from os.path import join
|
||||
from soil import simulation, analysis, agents
|
||||
|
||||
|
||||
ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
class Ping(agents.FSM):
|
||||
|
||||
defaults = {
|
||||
'count': 0,
|
||||
}
|
||||
|
||||
@agents.default_state
|
||||
@agents.state
|
||||
def even(self):
|
||||
self.debug(f'Even {self["count"]}')
|
||||
self['count'] += 1
|
||||
return self.odd
|
||||
|
||||
@agents.state
|
||||
def odd(self):
|
||||
self.debug(f'Odd {self["count"]}')
|
||||
self['count'] += 1
|
||||
return self.even
|
||||
|
||||
|
||||
class TestAnalysis(TestCase):
|
||||
|
||||
# Code to generate a simple sqlite history
|
||||
def setUp(self):
|
||||
"""
|
||||
The initial states should be applied to the agent and the
|
||||
agent should be able to update its state."""
|
||||
config = {
|
||||
'name': 'analysis',
|
||||
'seed': 'seed',
|
||||
'network_params': {
|
||||
'generator': 'complete_graph',
|
||||
'n': 2
|
||||
},
|
||||
'agent_class': Ping,
|
||||
'states': [{'interval': 1}, {'interval': 2}],
|
||||
'max_time': 30,
|
||||
'num_trials': 1,
|
||||
'history': True,
|
||||
'environment_params': {
|
||||
}
|
||||
}
|
||||
s = simulation.from_config(config)
|
||||
self.env = s.run_simulation(dry_run=True)[0]
|
||||
|
||||
def test_saved(self):
|
||||
env = self.env
|
||||
assert env.get_agent(0)['count', 0] == 1
|
||||
assert env.get_agent(0)['count', 29] == 30
|
||||
assert env.get_agent(1)['count', 0] == 1
|
||||
assert env.get_agent(1)['count', 29] == 15
|
||||
assert env['env', 29, None]['SEED'] == env['env', 29, 'SEED']
|
||||
|
||||
def test_count(self):
|
||||
env = self.env
|
||||
df = analysis.read_sql(env._history.db_path)
|
||||
res = analysis.get_count(df, 'SEED', 'state_id')
|
||||
assert res['SEED'][self.env['SEED']].iloc[0] == 1
|
||||
assert res['SEED'][self.env['SEED']].iloc[-1] == 1
|
||||
assert res['state_id']['odd'].iloc[0] == 2
|
||||
assert res['state_id']['even'].iloc[0] == 0
|
||||
assert res['state_id']['odd'].iloc[-1] == 1
|
||||
assert res['state_id']['even'].iloc[-1] == 1
|
||||
|
||||
def test_value(self):
|
||||
env = self.env
|
||||
df = analysis.read_sql(env._history.db_path)
|
||||
res_sum = analysis.get_value(df, 'count')
|
||||
|
||||
assert res_sum['count'].iloc[0] == 2
|
||||
|
||||
import numpy as np
|
||||
res_mean = analysis.get_value(df, 'count', aggfunc=np.mean)
|
||||
assert res_mean['count'].iloc[15] == (16+8)/2
|
||||
|
||||
res_total = analysis.get_majority(df)
|
||||
res_total['SEED'].iloc[0] == self.env['SEED']
|
@@ -29,7 +29,7 @@ class TestConfig(TestCase):
|
||||
expected = serialization.load_file(join(ROOT, "complete_converted.yml"))[0]
|
||||
old = serialization.load_file(join(ROOT, "old_complete.yml"))[0]
|
||||
converted_defaults = config.convert_old(old, strict=False)
|
||||
converted = converted_defaults.dict(skip_defaults=True)
|
||||
converted = converted_defaults.dict(exclude_unset=True)
|
||||
|
||||
isequal(converted, expected)
|
||||
|
||||
@@ -40,10 +40,10 @@ class TestConfig(TestCase):
|
||||
"""
|
||||
config = serialization.load_file(join(EXAMPLES, 'complete.yml'))[0]
|
||||
s = simulation.from_config(config)
|
||||
init_config = copy.copy(s.config)
|
||||
init_config = copy.copy(s.to_dict())
|
||||
|
||||
s.run_simulation(dry_run=True)
|
||||
nconfig = s.config
|
||||
nconfig = s.to_dict()
|
||||
# del nconfig['to
|
||||
isequal(init_config, nconfig)
|
||||
|
||||
@@ -61,7 +61,7 @@ class TestConfig(TestCase):
|
||||
Simple configuration that tests that the graph is loaded, and that
|
||||
network agents are initialized properly.
|
||||
"""
|
||||
config = {
|
||||
cfg = {
|
||||
'name': 'CounterAgent',
|
||||
'network_params': {
|
||||
'path': join(ROOT, 'test.gexf')
|
||||
@@ -74,12 +74,14 @@ class TestConfig(TestCase):
|
||||
'environment_params': {
|
||||
}
|
||||
}
|
||||
s = simulation.from_old_config(config)
|
||||
conf = config.convert_old(cfg)
|
||||
s = simulation.from_config(conf)
|
||||
|
||||
env = s.get_env()
|
||||
assert len(env.topologies['default'].nodes) == 2
|
||||
assert len(env.topologies['default'].edges) == 1
|
||||
assert len(env.agents) == 2
|
||||
assert env.agents[0].topology == env.topologies['default']
|
||||
assert env.agents[0].G == env.topologies['default']
|
||||
|
||||
def test_agents_from_config(self):
|
||||
'''We test that the known complete configuration produces
|
||||
@@ -87,12 +89,9 @@ class TestConfig(TestCase):
|
||||
cfg = serialization.load_file(join(ROOT, "complete_converted.yml"))[0]
|
||||
s = simulation.from_config(cfg)
|
||||
env = s.get_env()
|
||||
assert len(env.topologies['default'].nodes) == 10
|
||||
assert len(env.agents(group='network')) == 10
|
||||
assert len(env.topologies['default'].nodes) == 4
|
||||
assert len(env.agents(group='network')) == 4
|
||||
assert len(env.agents(group='environment')) == 1
|
||||
|
||||
assert sum(1 for a in env.agents(group='network', agent_class=agents.CounterModel)) == 4
|
||||
assert sum(1 for a in env.agents(group='network', agent_class=agents.AggregatedCounter)) == 6
|
||||
|
||||
def test_yaml(self):
|
||||
"""
|
||||
|
@@ -2,7 +2,7 @@ from unittest import TestCase
|
||||
import os
|
||||
from os.path import join
|
||||
|
||||
from soil import serialization, simulation
|
||||
from soil import serialization, simulation, config
|
||||
|
||||
ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
EXAMPLES = join(ROOT, '..', 'examples')
|
||||
@@ -14,36 +14,37 @@ class TestExamples(TestCase):
|
||||
pass
|
||||
|
||||
|
||||
def make_example_test(path, config):
|
||||
def make_example_test(path, cfg):
|
||||
def wrapped(self):
|
||||
root = os.getcwd()
|
||||
for s in simulation.all_from_config(path):
|
||||
iterations = s.config.general.max_time * s.config.general.num_trials
|
||||
if iterations > 1000:
|
||||
s.config.general.max_time = 100
|
||||
s.config.general.num_trials = 1
|
||||
if config.get('skip_test', False) and not FORCE_TESTS:
|
||||
for s in simulation.iter_from_config(cfg):
|
||||
iterations = s.max_steps * s.num_trials
|
||||
if iterations < 0 or iterations > 1000:
|
||||
s.max_steps = 100
|
||||
s.num_trials = 1
|
||||
assert isinstance(cfg, config.Config)
|
||||
if getattr(cfg, 'skip_test', False) and not FORCE_TESTS:
|
||||
self.skipTest('Example ignored.')
|
||||
envs = s.run_simulation(dry_run=True)
|
||||
assert envs
|
||||
for env in envs:
|
||||
assert env
|
||||
try:
|
||||
n = config['network_params']['n']
|
||||
n = cfg.model_params['network_params']['n']
|
||||
assert len(list(env.network_agents)) == n
|
||||
assert env.now > 0 # It has run
|
||||
assert env.now <= config['max_time'] # But not further than allowed
|
||||
except KeyError:
|
||||
pass
|
||||
assert env.schedule.steps > 0 # It has run
|
||||
assert env.schedule.steps <= s.max_steps # But not further than allowed
|
||||
return wrapped
|
||||
|
||||
|
||||
def add_example_tests():
|
||||
for config, path in serialization.load_files(
|
||||
for cfg, path in serialization.load_files(
|
||||
join(EXAMPLES, '*', '*.yml'),
|
||||
join(EXAMPLES, '*.yml'),
|
||||
):
|
||||
p = make_example_test(path=path, config=config)
|
||||
p = make_example_test(path=path, cfg=config.Config.from_raw(cfg))
|
||||
fname = os.path.basename(path)
|
||||
p.__name__ = 'test_example_file_%s' % fname
|
||||
p.__doc__ = '%s should be a valid configuration' % fname
|
||||
|
@@ -6,6 +6,8 @@ import shutil
|
||||
from unittest import TestCase
|
||||
from soil import exporters
|
||||
from soil import simulation
|
||||
from soil import agents
|
||||
|
||||
|
||||
class Dummy(exporters.Exporter):
|
||||
started = False
|
||||
@@ -33,28 +35,36 @@ class Dummy(exporters.Exporter):
|
||||
|
||||
class Exporters(TestCase):
|
||||
def test_basic(self):
|
||||
# We need to add at least one agent to make sure the scheduler
|
||||
# ticks every step
|
||||
num_trials = 5
|
||||
max_time = 2
|
||||
config = {
|
||||
'name': 'exporter_sim',
|
||||
'network_params': {},
|
||||
'agent_class': 'CounterModel',
|
||||
'max_time': 2,
|
||||
'num_trials': 5,
|
||||
'environment_params': {}
|
||||
'model_params': {
|
||||
'agents': [{
|
||||
'agent_class': agents.BaseAgent
|
||||
}]
|
||||
},
|
||||
'max_time': max_time,
|
||||
'num_trials': num_trials,
|
||||
}
|
||||
s = simulation.from_config(config)
|
||||
|
||||
for env in s.run_simulation(exporters=[Dummy], dry_run=True):
|
||||
assert env.now <= 2
|
||||
assert len(env.agents) == 1
|
||||
assert env.now == max_time
|
||||
|
||||
assert Dummy.started
|
||||
assert Dummy.ended
|
||||
assert Dummy.called_start == 1
|
||||
assert Dummy.called_end == 1
|
||||
assert Dummy.called_trial == 5
|
||||
assert Dummy.trials == 5
|
||||
assert Dummy.total_time == 2*5
|
||||
assert Dummy.called_trial == num_trials
|
||||
assert Dummy.trials == num_trials
|
||||
assert Dummy.total_time == max_time * num_trials
|
||||
|
||||
def test_writing(self):
|
||||
'''Try to write CSV, GEXF, sqlite and YAML (without dry_run)'''
|
||||
'''Try to write CSV, sqlite and YAML (without dry_run)'''
|
||||
n_trials = 5
|
||||
config = {
|
||||
'name': 'exporter_sim',
|
||||
@@ -74,7 +84,6 @@ class Exporters(TestCase):
|
||||
envs = s.run_simulation(exporters=[
|
||||
exporters.default,
|
||||
exporters.csv,
|
||||
exporters.gexf,
|
||||
],
|
||||
dry_run=False,
|
||||
outdir=tmpdir,
|
||||
@@ -88,11 +97,7 @@ class Exporters(TestCase):
|
||||
|
||||
try:
|
||||
for e in envs:
|
||||
with open(os.path.join(simdir, '{}.gexf'.format(e.name))) as f:
|
||||
result = f.read()
|
||||
assert result
|
||||
|
||||
with open(os.path.join(simdir, '{}.csv'.format(e.name))) as f:
|
||||
with open(os.path.join(simdir, '{}.env.csv'.format(e.id))) as f:
|
||||
result = f.read()
|
||||
assert result
|
||||
finally:
|
||||
|
@@ -1,128 +0,0 @@
|
||||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
import io
|
||||
import yaml
|
||||
import copy
|
||||
import pickle
|
||||
import networkx as nx
|
||||
from functools import partial
|
||||
|
||||
from os.path import join
|
||||
from soil import (simulation, Environment, agents, serialization,
|
||||
utils)
|
||||
from soil.time import Delta
|
||||
from tsih import NoHistory, History
|
||||
|
||||
|
||||
ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
EXAMPLES = join(ROOT, '..', 'examples')
|
||||
|
||||
|
||||
class CustomAgent(agents.FSM):
|
||||
@agents.default_state
|
||||
@agents.state
|
||||
def normal(self):
|
||||
self.neighbors = self.count_agents(state_id='normal',
|
||||
limit_neighbors=True)
|
||||
@agents.state
|
||||
def unreachable(self):
|
||||
return
|
||||
|
||||
class TestHistory(TestCase):
|
||||
|
||||
def test_counter_agent_history(self):
|
||||
"""
|
||||
The evolution of the state should be recorded in the logging agent
|
||||
"""
|
||||
config = {
|
||||
'name': 'CounterAgent',
|
||||
'network_params': {
|
||||
'path': join(ROOT, 'test.gexf')
|
||||
},
|
||||
'network_agents': [{
|
||||
'agent_class': 'AggregatedCounter',
|
||||
'weight': 1,
|
||||
'state': {'state_id': 0}
|
||||
|
||||
}],
|
||||
'max_time': 10,
|
||||
'environment_params': {
|
||||
}
|
||||
}
|
||||
s = simulation.from_config(config)
|
||||
env = s.run_simulation(dry_run=True)[0]
|
||||
for agent in env.network_agents:
|
||||
last = 0
|
||||
assert len(agent[None, None]) == 11
|
||||
for step, total in sorted(agent['total', None]):
|
||||
assert total == last + 2
|
||||
last = total
|
||||
|
||||
def test_row_conversion(self):
|
||||
env = Environment(history=True)
|
||||
env['test'] = 'test_value'
|
||||
|
||||
res = list(env.history_to_tuples())
|
||||
assert len(res) == len(env.environment_params)
|
||||
|
||||
env.schedule.time = 1
|
||||
env['test'] = 'second_value'
|
||||
res = list(env.history_to_tuples())
|
||||
|
||||
assert env['env', 0, 'test' ] == 'test_value'
|
||||
assert env['env', 1, 'test' ] == 'second_value'
|
||||
|
||||
def test_nohistory(self):
|
||||
'''
|
||||
Make sure that no history(/sqlite) is used by default
|
||||
'''
|
||||
env = Environment(topology=nx.Graph(), network_agents=[])
|
||||
assert isinstance(env._history, NoHistory)
|
||||
|
||||
def test_save_graph_history(self):
|
||||
'''
|
||||
The history_to_graph method should return a valid networkx graph.
|
||||
|
||||
The state of the agent should be encoded as intervals in the nx graph.
|
||||
'''
|
||||
G = nx.cycle_graph(5)
|
||||
distribution = agents.calculate_distribution(None, agents.BaseAgent)
|
||||
env = Environment(topology=G, network_agents=distribution, history=True)
|
||||
env[0, 0, 'testvalue'] = 'start'
|
||||
env[0, 10, 'testvalue'] = 'finish'
|
||||
nG = env.history_to_graph()
|
||||
values = nG.nodes[0]['attr_testvalue']
|
||||
assert ('start', 0, 10) in values
|
||||
assert ('finish', 10, None) in values
|
||||
|
||||
def test_save_graph_nohistory(self):
|
||||
'''
|
||||
The history_to_graph method should return a valid networkx graph.
|
||||
|
||||
When NoHistory is used, only the last known value is known
|
||||
'''
|
||||
G = nx.cycle_graph(5)
|
||||
distribution = agents.calculate_distribution(None, agents.BaseAgent)
|
||||
env = Environment(topology=G, network_agents=distribution, history=False)
|
||||
env.get_agent(0)['testvalue'] = 'start'
|
||||
env.schedule.time = 10
|
||||
env.get_agent(0)['testvalue'] = 'finish'
|
||||
nG = env.history_to_graph()
|
||||
values = nG.nodes[0]['attr_testvalue']
|
||||
assert ('start', 0, None) not in values
|
||||
assert ('finish', 10, None) in values
|
||||
|
||||
def test_pickle_agent_environment(self):
|
||||
env = Environment(name='Test', history=True)
|
||||
a = agents.BaseAgent(model=env, unique_id=25)
|
||||
|
||||
a['key'] = 'test'
|
||||
|
||||
pickled = pickle.dumps(a)
|
||||
recovered = pickle.loads(pickled)
|
||||
|
||||
assert recovered.env.name == 'Test'
|
||||
assert list(recovered.env._history.to_tuples())
|
||||
assert recovered['key', 0] == 'test'
|
||||
assert recovered['key'] == 'test'
|
@@ -24,6 +24,7 @@ class CustomAgent(agents.FSM, agents.NetworkAgent):
|
||||
def unreachable(self):
|
||||
return
|
||||
|
||||
|
||||
class TestMain(TestCase):
|
||||
|
||||
def test_empty_simulation(self):
|
||||
@@ -79,20 +80,16 @@ class TestMain(TestCase):
|
||||
}
|
||||
},
|
||||
'agents': {
|
||||
'default': {
|
||||
'agent_class': 'CounterModel',
|
||||
},
|
||||
'counters': {
|
||||
'topology': 'default',
|
||||
'fixed': [{'state': {'times': 10}}, {'state': {'times': 20}}],
|
||||
}
|
||||
'agent_class': 'CounterModel',
|
||||
'topology': 'default',
|
||||
'fixed': [{'state': {'times': 10}}, {'state': {'times': 20}}],
|
||||
}
|
||||
}
|
||||
}
|
||||
s = simulation.from_config(config)
|
||||
env = s.get_env()
|
||||
assert isinstance(env.agents[0], agents.CounterModel)
|
||||
assert env.agents[0].topology == env.topologies['default']
|
||||
assert env.agents[0].G == env.topologies['default']
|
||||
assert env.agents[0]['times'] == 10
|
||||
assert env.agents[0]['times'] == 10
|
||||
env.step()
|
||||
@@ -105,8 +102,8 @@ class TestMain(TestCase):
|
||||
config = {
|
||||
'max_time': 10,
|
||||
'model_params': {
|
||||
'agents': [(CustomAgent, {'weight': 1}),
|
||||
(CustomAgent, {'weight': 3}),
|
||||
'agents': [{'agent_class': CustomAgent, 'weight': 1, 'topology': 'default'},
|
||||
{'agent_class': CustomAgent, 'weight': 3, 'topology': 'default'},
|
||||
],
|
||||
'topologies': {
|
||||
'default': {
|
||||
@@ -128,7 +125,7 @@ class TestMain(TestCase):
|
||||
"""A complete example from a documentation should work."""
|
||||
config = serialization.load_file(join(EXAMPLES, 'torvalds.yml'))[0]
|
||||
config['model_params']['network_params']['path'] = join(EXAMPLES,
|
||||
config['network_params']['path'])
|
||||
config['model_params']['network_params']['path'])
|
||||
s = simulation.from_config(config)
|
||||
env = s.run_simulation(dry_run=True)[0]
|
||||
for a in env.network_agents:
|
||||
@@ -208,24 +205,6 @@ class TestMain(TestCase):
|
||||
assert converted[1]['agent_class'] == 'test_main.CustomAgent'
|
||||
pickle.dumps(converted)
|
||||
|
||||
def test_subgraph(self):
|
||||
'''An agent should be able to subgraph the global topology'''
|
||||
G = nx.Graph()
|
||||
G.add_node(3)
|
||||
G.add_edge(1, 2)
|
||||
distro = agents.calculate_distribution(agent_class=agents.NetworkAgent)
|
||||
distro[0]['topology'] = 'default'
|
||||
aconfig = config.AgentConfig(distribution=distro, topology='default')
|
||||
env = Environment(name='Test', topologies={'default': G}, agents={'network': aconfig})
|
||||
lst = list(env.network_agents)
|
||||
|
||||
a2 = env.find_one(node_id=2)
|
||||
a3 = env.find_one(node_id=3)
|
||||
assert len(a2.subgraph(limit_neighbors=True)) == 2
|
||||
assert len(a3.subgraph(limit_neighbors=True)) == 1
|
||||
assert len(a3.subgraph(limit_neighbors=True, center=False)) == 0
|
||||
assert len(a3.subgraph(agent_class=agents.NetworkAgent)) == 3
|
||||
|
||||
def test_templates(self):
|
||||
'''Loading a template should result in several configs'''
|
||||
configs = serialization.load_file(join(EXAMPLES, 'template.yml'))
|
||||
@@ -236,14 +215,18 @@ class TestMain(TestCase):
|
||||
'name': 'until_sim',
|
||||
'model_params': {
|
||||
'network_params': {},
|
||||
'agent_class': 'CounterModel',
|
||||
'agents': {
|
||||
'fixed': [{
|
||||
'agent_class': agents.BaseAgent,
|
||||
}]
|
||||
},
|
||||
},
|
||||
'max_time': 2,
|
||||
'num_trials': 50,
|
||||
}
|
||||
s = simulation.from_config(config)
|
||||
runs = list(s.run_simulation(dry_run=True))
|
||||
over = list(x.now for x in runs if x.now>2)
|
||||
over = list(x.now for x in runs if x.now > 2)
|
||||
assert len(runs) == config['num_trials']
|
||||
assert len(over) == 0
|
||||
|
||||
|
@@ -6,7 +6,8 @@ import networkx as nx
|
||||
|
||||
from os.path import join
|
||||
|
||||
from soil import network, environment
|
||||
from soil import config, network, environment, agents, simulation
|
||||
from test_main import CustomAgent
|
||||
|
||||
ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
EXAMPLES = join(ROOT, '..', 'examples')
|
||||
@@ -60,22 +61,53 @@ class TestNetwork(TestCase):
|
||||
G = nx.random_geometric_graph(20, 0.1)
|
||||
env = environment.NetworkEnvironment(topology=G)
|
||||
f = io.BytesIO()
|
||||
env.dump_gexf(f)
|
||||
assert env.topologies['default']
|
||||
network.dump_gexf(env.topologies['default'], f)
|
||||
|
||||
def test_networkenvironment_creation(self):
|
||||
"""Networkenvironment should accept netconfig as parameters"""
|
||||
model_params = {
|
||||
'topologies': {
|
||||
'default': {
|
||||
'path': join(ROOT, 'test.gexf')
|
||||
}
|
||||
},
|
||||
'agents': {
|
||||
'topology': 'default',
|
||||
'distribution': [{
|
||||
'agent_class': CustomAgent,
|
||||
}]
|
||||
}
|
||||
}
|
||||
env = environment.Environment(**model_params)
|
||||
assert env.topologies
|
||||
env.step()
|
||||
assert len(env.topologies['default']) == 2
|
||||
assert len(env.agents) == 2
|
||||
assert env.agents[1].count_agents(state_id='normal') == 2
|
||||
assert env.agents[1].count_agents(state_id='normal', limit_neighbors=True) == 1
|
||||
assert env.agents[0].neighbors == 1
|
||||
|
||||
def test_custom_agent_neighbors(self):
|
||||
"""Allow for search of neighbors with a certain state_id"""
|
||||
config = {
|
||||
'network_params': {
|
||||
'path': join(ROOT, 'test.gexf')
|
||||
'model_params': {
|
||||
'topologies': {
|
||||
'default': {
|
||||
'path': join(ROOT, 'test.gexf')
|
||||
}
|
||||
},
|
||||
'agents': {
|
||||
'topology': 'default',
|
||||
'distribution': [
|
||||
{
|
||||
'weight': 1,
|
||||
'agent_class': CustomAgent
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
'network_agents': [{
|
||||
'agent_class': CustomAgent,
|
||||
'weight': 1
|
||||
|
||||
}],
|
||||
'max_time': 10,
|
||||
'environment_params': {
|
||||
}
|
||||
}
|
||||
s = simulation.from_config(config)
|
||||
env = s.run_simulation(dry_run=True)[0]
|
||||
@@ -83,3 +115,19 @@ class TestNetwork(TestCase):
|
||||
assert env.agents[1].count_agents(state_id='normal', limit_neighbors=True) == 1
|
||||
assert env.agents[0].neighbors == 1
|
||||
|
||||
def test_subgraph(self):
|
||||
'''An agent should be able to subgraph the global topology'''
|
||||
G = nx.Graph()
|
||||
G.add_node(3)
|
||||
G.add_edge(1, 2)
|
||||
distro = agents.calculate_distribution(agent_class=agents.NetworkAgent)
|
||||
aconfig = config.AgentConfig(distribution=distro, topology='default')
|
||||
env = environment.Environment(name='Test', topologies={'default': G}, agents=aconfig)
|
||||
lst = list(env.network_agents)
|
||||
|
||||
a2 = env.find_one(node_id=2)
|
||||
a3 = env.find_one(node_id=3)
|
||||
assert len(a2.subgraph(limit_neighbors=True)) == 2
|
||||
assert len(a3.subgraph(limit_neighbors=True)) == 1
|
||||
assert len(a3.subgraph(limit_neighbors=True, center=False)) == 0
|
||||
assert len(a3.subgraph(agent_class=agents.NetworkAgent)) == 3
|
||||
|
Reference in New Issue
Block a user