mirror of
https://github.com/gsi-upm/soil
synced 2024-11-22 03:02:28 +00:00
Fix gephi representation. Add sqlite
This commit is contained in:
parent
af76f54a28
commit
78364d89d5
@ -4,6 +4,8 @@ dir_path: "/tmp/"
|
|||||||
num_trials: 3
|
num_trials: 3
|
||||||
max_time: 100
|
max_time: 100
|
||||||
interval: 1
|
interval: 1
|
||||||
|
seed: "CompleteSeed!"
|
||||||
|
dump: false
|
||||||
network_params:
|
network_params:
|
||||||
generator: complete_graph
|
generator: complete_graph
|
||||||
n: 10
|
n: 10
|
||||||
@ -21,4 +23,4 @@ default_state:
|
|||||||
incidents: 0
|
incidents: 0
|
||||||
states:
|
states:
|
||||||
- name: 'The first node'
|
- name: 'The first node'
|
||||||
- name: 'The second node'
|
- name: 'The second node'
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import logging
|
|
||||||
from soil.agents import NetworkAgent, FSM, state, default_state, BaseAgent
|
from soil.agents import NetworkAgent, FSM, state, default_state, BaseAgent
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from random import random, choice
|
from random import random, choice
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
|
import logging
|
||||||
|
import math
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class Genders(Enum):
|
class Genders(Enum):
|
||||||
male = 'male'
|
male = 'male'
|
||||||
@ -13,6 +13,8 @@ class Genders(Enum):
|
|||||||
|
|
||||||
class RabbitModel(NetworkAgent, FSM):
|
class RabbitModel(NetworkAgent, FSM):
|
||||||
|
|
||||||
|
level = logging.INFO
|
||||||
|
|
||||||
defaults = {
|
defaults = {
|
||||||
'age': 0,
|
'age': 0,
|
||||||
'gender': Genders.male.value,
|
'gender': Genders.male.value,
|
||||||
@ -24,7 +26,7 @@ class RabbitModel(NetworkAgent, FSM):
|
|||||||
life_expectancy = 365 * 3
|
life_expectancy = 365 * 3
|
||||||
gestation = 33
|
gestation = 33
|
||||||
pregnancy = -1
|
pregnancy = -1
|
||||||
max_females = 10
|
max_females = 2
|
||||||
|
|
||||||
@default_state
|
@default_state
|
||||||
@state
|
@state
|
||||||
@ -57,7 +59,7 @@ class RabbitModel(NetworkAgent, FSM):
|
|||||||
whom['pregnancy'] = 0
|
whom['pregnancy'] = 0
|
||||||
whom['mate'] = self.id
|
whom['mate'] = self.id
|
||||||
whom.set_state(whom.pregnant)
|
whom.set_state(whom.pregnant)
|
||||||
logger.debug('{} impregnating: {}. {}'.format(self.id, whom.id, whom.state))
|
self.debug('{} impregnating: {}. {}'.format(self.id, whom.id, whom.state))
|
||||||
|
|
||||||
@state
|
@state
|
||||||
def pregnant(self):
|
def pregnant(self):
|
||||||
@ -66,38 +68,52 @@ class RabbitModel(NetworkAgent, FSM):
|
|||||||
return self.dead
|
return self.dead
|
||||||
|
|
||||||
self['pregnancy'] += 1
|
self['pregnancy'] += 1
|
||||||
logger.debug('Pregnancy: {}'.format(self['pregnancy']))
|
self.debug('Pregnancy: {}'.format(self['pregnancy']))
|
||||||
if self['pregnancy'] >= self.gestation:
|
if self['pregnancy'] >= self.gestation:
|
||||||
|
number_of_babies = int(8+4*random())
|
||||||
state = {}
|
for i in range(number_of_babies):
|
||||||
state['gender'] = choice(list(Genders)).value
|
state = {}
|
||||||
child = self.env.add_node(self.__class__, state)
|
state['gender'] = choice(list(Genders)).value
|
||||||
self.env.add_edge(self.id, child.id)
|
child = self.env.add_node(self.__class__, state)
|
||||||
self.env.add_edge(self['mate'], child.id)
|
self.env.add_edge(self.id, child.id)
|
||||||
# self.add_edge()
|
self.env.add_edge(self['mate'], child.id)
|
||||||
logger.info("A rabbit has been born: {}. Total: {}".format(child.id, len(self.global_topology.nodes)))
|
# self.add_edge()
|
||||||
self['offspring'] += 1
|
self.debug('A BABY IS COMING TO LIFE')
|
||||||
self.env.get_agent(self['mate'])['offspring'] += 1
|
self.env['rabbits_alive'] = self.env.get('rabbits_alive', 0)+1
|
||||||
del self['mate']
|
self.debug('Rabbits alive: {}'.format(self.env['rabbits_alive']))
|
||||||
self['pregnancy'] = -1
|
self['offspring'] += 1
|
||||||
return self.fertile
|
self.env.get_agent(self['mate'])['offspring'] += 1
|
||||||
|
del self['mate']
|
||||||
|
self['pregnancy'] = -1
|
||||||
|
return self.fertile
|
||||||
|
|
||||||
@state
|
@state
|
||||||
def dead(self):
|
def dead(self):
|
||||||
logger.info('Agent {} is dying'.format(self.id))
|
self.info('Agent {} is dying'.format(self.id))
|
||||||
if 'pregnancy' in self and self['pregnancy'] > -1:
|
if 'pregnancy' in self and self['pregnancy'] > -1:
|
||||||
logger.info('A mother has died carrying a baby!: {}!'.format(self.state))
|
self.info('A mother has died carrying a baby!!')
|
||||||
self.die()
|
self.die()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class RandomAccident(BaseAgent):
|
class RandomAccident(BaseAgent):
|
||||||
|
|
||||||
|
level = logging.INFO
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
logger.debug('Killing some rabbits!')
|
rabbits_total = self.global_topology.number_of_nodes()
|
||||||
prob_death = self.env.get('prob_death', -1)
|
rabbits_alive = self.env.get('rabbits_alive', rabbits_total)
|
||||||
|
prob_death = self.env.get('prob_death', 1e-100)*math.log(max(1, rabbits_alive))
|
||||||
|
self.debug('Killing some rabbits with prob={}!'.format(prob_death))
|
||||||
for i in self.env.network_agents:
|
for i in self.env.network_agents:
|
||||||
|
if i.state['id'] == i.dead.id:
|
||||||
|
continue
|
||||||
r = random()
|
r = random()
|
||||||
if r < prob_death:
|
if r < prob_death:
|
||||||
logger.info('I killed a rabbit: {}'.format(i.id))
|
self.debug('I killed a rabbit: {}'.format(i.id))
|
||||||
|
rabbits_alive = self.env['rabbits_alive'] = rabbits_alive -1
|
||||||
|
self.log('Rabbits alive: {}'.format(self.env['rabbits_alive']))
|
||||||
i.set_state(i.dead)
|
i.set_state(i.dead)
|
||||||
|
self.log('Rabbits alive: {}/{}'.format(rabbits_alive, rabbits_total))
|
||||||
|
if self.count_agents(state_id=RabbitModel.dead.id) == self.global_topology.number_of_nodes():
|
||||||
|
self.die()
|
@ -1,14 +1,16 @@
|
|||||||
---
|
---
|
||||||
load_module: custom_agents
|
load_module: rabbit_agents
|
||||||
name: custom_agent_example
|
name: rabbits_example
|
||||||
max_time: 2500
|
max_time: 1500
|
||||||
interval: 1
|
interval: 1
|
||||||
seed: MySimulationSeed
|
seed: MySeed
|
||||||
agent_type: RabbitModel
|
agent_type: RabbitModel
|
||||||
environment_agents:
|
environment_agents:
|
||||||
- agent_type: RandomAccident
|
- agent_type: RandomAccident
|
||||||
|
environment_params:
|
||||||
|
prob_death: 0.0001
|
||||||
default_state:
|
default_state:
|
||||||
mating_prob: 1
|
mating_prob: 0.01
|
||||||
topology:
|
topology:
|
||||||
nodes:
|
nodes:
|
||||||
- id: 1
|
- id: 1
|
@ -11,11 +11,8 @@ try:
|
|||||||
except NameError:
|
except NameError:
|
||||||
basestring = str
|
basestring = str
|
||||||
|
|
||||||
from . import agents
|
logging.basicConfig()#format=FORMAT)
|
||||||
from . import simulation
|
|
||||||
from . import environment
|
|
||||||
from . import utils
|
from . import utils
|
||||||
from . import settings
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -42,9 +39,8 @@ def main():
|
|||||||
sys.path.append(os.getcwd())
|
sys.path.append(os.getcwd())
|
||||||
importlib.import_module(args.module)
|
importlib.import_module(args.module)
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.info('Loading config file: {}'.format(args.file, args.output))
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
logger.info('Loading config file: {}'.format(args.file, args.output))
|
|
||||||
try:
|
try:
|
||||||
simulation.run_from_config(args.file, dump=(not args.dry_run), results_dir=args.output)
|
simulation.run_from_config(args.file, dump=(not args.dry_run), results_dir=args.output)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
@ -9,8 +9,8 @@ class CounterModel(NetworkAgent):
|
|||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
# Outside effects
|
# Outside effects
|
||||||
total = len(self.get_all_agents())
|
total = len(list(self.get_all_agents()))
|
||||||
neighbors = len(self.get_neighboring_agents())
|
neighbors = len(list(self.get_neighboring_agents()))
|
||||||
self.state['times'] = self.state.get('times', 0) + 1
|
self.state['times'] = self.state.get('times', 0) + 1
|
||||||
self.state['neighbors'] = neighbors
|
self.state['neighbors'] = neighbors
|
||||||
self.state['total'] = total
|
self.state['total'] = total
|
||||||
@ -24,8 +24,8 @@ class AggregatedCounter(NetworkAgent):
|
|||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
# Outside effects
|
# Outside effects
|
||||||
total = len(self.get_all_agents())
|
total = len(list(self.get_all_agents()))
|
||||||
neighbors = len(self.get_neighboring_agents())
|
neighbors = len(list(self.get_neighboring_agents()))
|
||||||
self.state['times'] = self.state.get('times', 0) + 1
|
self.state['times'] = self.state.get('times', 0) + 1
|
||||||
self.state['neighbors'] = self.state.get('neighbors', 0) + neighbors
|
self.state['neighbors'] = self.state.get('neighbors', 0) + neighbors
|
||||||
self.state['total'] = self.state.get('total', 0) + total
|
self.state['total'] = self.state.get('total', 0) + total
|
||||||
|
@ -6,11 +6,13 @@
|
|||||||
|
|
||||||
|
|
||||||
import nxsim
|
import nxsim
|
||||||
|
import logging
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
@ -37,11 +39,16 @@ class BaseAgent(nxsim.BaseAgent, metaclass=MetaAgent):
|
|||||||
state.update(kwargs.pop('state', {}))
|
state.update(kwargs.pop('state', {}))
|
||||||
kwargs['state'] = state
|
kwargs['state'] = state
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
if not hasattr(self, 'level'):
|
||||||
|
self.level = logging.DEBUG
|
||||||
|
self.logger = logging.getLogger('Agent-{}'.format(self.id))
|
||||||
|
self.logger.setLevel(self.level)
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if isinstance(key, tuple):
|
if isinstance(key, tuple):
|
||||||
k, t_step = key
|
k, t_step = key
|
||||||
return self.env[t_step, self.id, k]
|
return self.env[self.id, t_step, k]
|
||||||
return self.state.get(key, None)
|
return self.state.get(key, None)
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
@ -78,7 +85,7 @@ class BaseAgent(nxsim.BaseAgent, metaclass=MetaAgent):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
return json.dumps(self._history)
|
return json.dumps(self.state)
|
||||||
|
|
||||||
def count_agents(self, state_id=None, limit_neighbors=False):
|
def count_agents(self, state_id=None, limit_neighbors=False):
|
||||||
if limit_neighbors:
|
if limit_neighbors:
|
||||||
@ -108,6 +115,20 @@ class BaseAgent(nxsim.BaseAgent, metaclass=MetaAgent):
|
|||||||
|
|
||||||
return filter(matches_all, agents)
|
return filter(matches_all, agents)
|
||||||
|
|
||||||
|
def log(self, message, level=logging.INFO, **kwargs):
|
||||||
|
message = "\t@{:>5}:\t{}".format(self.now, message)
|
||||||
|
for k, v in kwargs:
|
||||||
|
message += " {k}={v} ".format(k, v)
|
||||||
|
extra = {}
|
||||||
|
extra['now'] = self.now
|
||||||
|
extra['id'] = self.id
|
||||||
|
return self.logger.log(level, message, extra=extra)
|
||||||
|
|
||||||
|
def debug(self, *args, **kwargs):
|
||||||
|
return self.log(*args, level=logging.DEBUG, **kwargs)
|
||||||
|
|
||||||
|
def info(self, *args, **kwargs):
|
||||||
|
return self.log(*args, level=logging.INFO, **kwargs)
|
||||||
|
|
||||||
class NetworkAgent(BaseAgent, nxsim.BaseNetworkAgent):
|
class NetworkAgent(BaseAgent, nxsim.BaseNetworkAgent):
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import os
|
import os
|
||||||
|
import sqlite3
|
||||||
import time
|
import time
|
||||||
import csv
|
|
||||||
import weakref
|
import weakref
|
||||||
|
import csv
|
||||||
import random
|
import random
|
||||||
|
import simpy
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
import nxsim
|
import nxsim
|
||||||
@ -22,15 +23,19 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
|
|||||||
interval=1,
|
interval=1,
|
||||||
seed=None,
|
seed=None,
|
||||||
dump=False,
|
dump=False,
|
||||||
|
simulation=None,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
self.name = name or 'UnnamedEnvironment'
|
self.name = name or 'UnnamedEnvironment'
|
||||||
self.states = deepcopy(states) or {}
|
if isinstance(states, list):
|
||||||
|
states = dict(enumerate(states))
|
||||||
|
self.states = deepcopy(states) if states else {}
|
||||||
self.default_state = deepcopy(default_state) or {}
|
self.default_state = deepcopy(default_state) or {}
|
||||||
|
self.sim = weakref.ref(simulation)
|
||||||
|
if 'topology' not in kwargs and simulation:
|
||||||
|
kwargs['topology'] = self.sim().topology.copy()
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._env_agents = {}
|
self._env_agents = {}
|
||||||
self._history = {}
|
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
self.logger = None
|
|
||||||
self.dump = dump
|
self.dump = dump
|
||||||
# Add environment agents first, so their events get
|
# Add environment agents first, so their events get
|
||||||
# executed before network agents
|
# executed before network agents
|
||||||
@ -39,6 +44,17 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
|
|||||||
self.environment_agents = environment_agents or []
|
self.environment_agents = environment_agents or []
|
||||||
self.network_agents = network_agents or []
|
self.network_agents = network_agents or []
|
||||||
self.process(self.save_state())
|
self.process(self.save_state())
|
||||||
|
if self.dump:
|
||||||
|
self._db_path = os.path.join(self.get_path(), 'db.sqlite')
|
||||||
|
else:
|
||||||
|
self._db_path = ":memory:"
|
||||||
|
self.create_db(self._db_path)
|
||||||
|
|
||||||
|
def create_db(self, db_path=None):
|
||||||
|
db_path = db_path or self._db_path
|
||||||
|
self._db = sqlite3.connect(db_path)
|
||||||
|
with self._db:
|
||||||
|
self._db.execute('''CREATE TABLE IF NOT EXISTS history (agent_id text, t_step int, key text, value text, value_type text)''')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def agents(self):
|
def agents(self):
|
||||||
@ -48,7 +64,7 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
|
|||||||
@property
|
@property
|
||||||
def environment_agents(self):
|
def environment_agents(self):
|
||||||
for ref in self._env_agents.values():
|
for ref in self._env_agents.values():
|
||||||
yield ref()
|
yield ref
|
||||||
|
|
||||||
@environment_agents.setter
|
@environment_agents.setter
|
||||||
def environment_agents(self, environment_agents):
|
def environment_agents(self, environment_agents):
|
||||||
@ -60,7 +76,7 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
|
|||||||
kwargs['agent_id'] = kwargs.get('agent_id', atype.__name__)
|
kwargs['agent_id'] = kwargs.get('agent_id', atype.__name__)
|
||||||
kwargs['state'] = kwargs.get('state', {})
|
kwargs['state'] = kwargs.get('state', {})
|
||||||
a = atype(environment=self, **kwargs)
|
a = atype(environment=self, **kwargs)
|
||||||
self._env_agents[a.id] = weakref.ref(a)
|
self._env_agents[a.id] = a
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def network_agents(self):
|
def network_agents(self):
|
||||||
@ -106,42 +122,72 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
|
|||||||
super().run(*args, **kwargs)
|
super().run(*args, **kwargs)
|
||||||
self._save_state()
|
self._save_state()
|
||||||
|
|
||||||
def _save_state(self):
|
def _save_state(self, now=None):
|
||||||
# for agent in self.agents:
|
# for agent in self.agents:
|
||||||
# agent.save_state()
|
# agent.save_state()
|
||||||
nowd = self._history[self.now] = {}
|
with self._db:
|
||||||
nowd['env'] = deepcopy(self.environment_params)
|
self._db.executemany("insert into history(agent_id, t_step, key, value, value_type) values (?, ?, ?, ?, ?)", self.state_to_tuples(now=now))
|
||||||
for agent in self.agents:
|
|
||||||
nowd[agent.id] = deepcopy(agent.state)
|
|
||||||
|
|
||||||
def save_state(self):
|
def save_state(self):
|
||||||
while True:
|
while self.peek() != simpy.core.Infinity:
|
||||||
|
utils.logger.info('Step: {}'.format(self.now))
|
||||||
ev = self.event()
|
ev = self.event()
|
||||||
ev._ok = True
|
ev._ok = True
|
||||||
# Schedule the event with minimum priority so
|
# Schedule the event with minimum priority so
|
||||||
# that it executes after all agents are done
|
# that it executes after all agents are done
|
||||||
self.schedule(ev, -1, self.interval)
|
self.schedule(ev, -1, self.peek())
|
||||||
yield ev
|
yield ev
|
||||||
self._save_state()
|
self._save_state()
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if isinstance(key, tuple):
|
if isinstance(key, tuple):
|
||||||
t_step, agent_id, k = key
|
values = {"agent_id": key[0],
|
||||||
|
"t_step": key[1],
|
||||||
|
"key": key[2],
|
||||||
|
"value": None,
|
||||||
|
"value_type": None
|
||||||
|
}
|
||||||
|
|
||||||
def key_or_dict(d, k, nfunc):
|
fields = list(k for k, v in values.items() if v is None)
|
||||||
if k is None:
|
conditions = " and ".join("{}='{}'".format(k, v) for k, v in values.items() if v is not None)
|
||||||
if d is None:
|
|
||||||
return {}
|
query = """SELECT {fields} from history""".format(fields=",".join(fields))
|
||||||
return {k: nfunc(v) for k, v in d.items()}
|
if conditions:
|
||||||
if k in d:
|
query = """{query} where {conditions}""".format(query=query,
|
||||||
return nfunc(d[k])
|
conditions=conditions)
|
||||||
return {}
|
with self._db:
|
||||||
|
rows = self._db.execute(query).fetchall()
|
||||||
|
|
||||||
|
utils.logger.debug(rows)
|
||||||
|
results = self.rows_to_dict(rows)
|
||||||
|
return results
|
||||||
|
|
||||||
f1 = partial(key_or_dict, k=k, nfunc=lambda x: x)
|
|
||||||
f2 = partial(key_or_dict, k=agent_id, nfunc=f1)
|
|
||||||
return key_or_dict(self._history, t_step, f2)
|
|
||||||
return self.environment_params[key]
|
return self.environment_params[key]
|
||||||
|
|
||||||
|
def rows_to_dict(self, rows):
|
||||||
|
if len(rows) < 1:
|
||||||
|
return None
|
||||||
|
|
||||||
|
level = len(rows[0])-2
|
||||||
|
|
||||||
|
if level == 0:
|
||||||
|
if len(rows) != 1:
|
||||||
|
raise ValueError('Cannot convert {} to dictionaries'.format(rows))
|
||||||
|
value, value_type = rows[0]
|
||||||
|
return utils.convert(value, value_type)
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
for row in rows:
|
||||||
|
item = results
|
||||||
|
for i in range(level-1):
|
||||||
|
key = row[i]
|
||||||
|
if key not in item:
|
||||||
|
item[key] = {}
|
||||||
|
item = item[key]
|
||||||
|
key, value, value_type = row[level-1:]
|
||||||
|
item[key] = utils.convert(value, value_type)
|
||||||
|
return results
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.environment_params[key] = value
|
self.environment_params[key] = value
|
||||||
|
|
||||||
@ -179,23 +225,34 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
|
|||||||
self.name+".gexf")
|
self.name+".gexf")
|
||||||
nx.write_gexf(G, graph_path, version="1.2draft")
|
nx.write_gexf(G, graph_path, version="1.2draft")
|
||||||
|
|
||||||
|
def state_to_tuples(self, now=None):
|
||||||
|
if now is None:
|
||||||
|
now = self.now
|
||||||
|
for k, v in self.environment_params.items():
|
||||||
|
yield 'env', now, k, v, type(v).__name__
|
||||||
|
for agent in self.agents:
|
||||||
|
for k, v in agent.state.items():
|
||||||
|
yield agent.id, now, k, v, type(v).__name__
|
||||||
|
|
||||||
def history_to_tuples(self):
|
def history_to_tuples(self):
|
||||||
for tstep, states in self._history.items():
|
with self._db:
|
||||||
for a_id, state in states.items():
|
res = self._db.execute("select agent_id, t_step, key, value from history ").fetchall()
|
||||||
for attribute, value in state.items():
|
yield from res
|
||||||
yield (a_id, tstep, attribute, value)
|
|
||||||
|
|
||||||
def history_to_graph(self):
|
def history_to_graph(self):
|
||||||
G = nx.Graph(self.G)
|
G = nx.Graph(self.G)
|
||||||
|
|
||||||
for agent in self.agents:
|
for agent in self.network_agents:
|
||||||
|
|
||||||
attributes = {'agent': str(agent.__class__)}
|
attributes = {'agent': str(agent.__class__)}
|
||||||
lastattributes = {}
|
lastattributes = {}
|
||||||
spells = []
|
spells = []
|
||||||
lastvisible = False
|
lastvisible = False
|
||||||
laststep = None
|
laststep = None
|
||||||
for t_step, state in reversed(list(self[None, agent.id, None].items())):
|
history = self[agent.id, None, None]
|
||||||
|
if not history:
|
||||||
|
continue
|
||||||
|
for t_step, state in reversed(sorted(list(history.items()))):
|
||||||
for attribute, value in state.items():
|
for attribute, value in state.items():
|
||||||
if attribute == 'visible':
|
if attribute == 'visible':
|
||||||
nowvisible = state[attribute]
|
nowvisible = state[attribute]
|
||||||
@ -206,15 +263,20 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
|
|||||||
|
|
||||||
lastvisible = nowvisible
|
lastvisible = nowvisible
|
||||||
else:
|
else:
|
||||||
if attribute not in lastattributes or lastattributes[attribute][0] != value:
|
key = 'attr_' + attribute
|
||||||
laststep = lastattributes.get(attribute,
|
if key not in attributes:
|
||||||
(None, None))[1]
|
attributes[key] = list()
|
||||||
value = (state[attribute], t_step, laststep)
|
if key not in lastattributes:
|
||||||
key = 'attr_' + attribute
|
lastattributes[key] = (state[attribute], t_step)
|
||||||
|
elif lastattributes[key][0] != value:
|
||||||
|
last_value, laststep = lastattributes[key]
|
||||||
|
value = (last_value, t_step, laststep)
|
||||||
if key not in attributes:
|
if key not in attributes:
|
||||||
attributes[key] = list()
|
attributes[key] = list()
|
||||||
attributes[key].append(value)
|
attributes[key].append(value)
|
||||||
lastattributes[attribute] = (state[attribute], t_step)
|
lastattributes[key] = (state[attribute], t_step)
|
||||||
|
for k, v in lastattributes.items():
|
||||||
|
attributes[k].append((v[0], 0, v[1]))
|
||||||
if lastvisible:
|
if lastvisible:
|
||||||
spells.append((laststep, None))
|
spells.append((laststep, None))
|
||||||
if spells:
|
if spells:
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import weakref
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import imp
|
import imp
|
||||||
import sys
|
import sys
|
||||||
import yaml
|
import yaml
|
||||||
import logging
|
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
from networkx.readwrite import json_graph
|
from networkx.readwrite import json_graph
|
||||||
|
|
||||||
@ -15,8 +13,8 @@ import pickle
|
|||||||
from nxsim import NetworkSimulation
|
from nxsim import NetworkSimulation
|
||||||
|
|
||||||
from . import agents, utils, environment, basestring
|
from . import agents, utils, environment, basestring
|
||||||
|
from .utils import logger
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class SoilSimulation(NetworkSimulation):
|
class SoilSimulation(NetworkSimulation):
|
||||||
"""
|
"""
|
||||||
@ -86,7 +84,7 @@ class SoilSimulation(NetworkSimulation):
|
|||||||
self.network_agents = self._convert_agent_types(distro)
|
self.network_agents = self._convert_agent_types(distro)
|
||||||
|
|
||||||
self.states = self.validate_states(states,
|
self.states = self.validate_states(states,
|
||||||
topology)
|
self.topology)
|
||||||
|
|
||||||
def calculate_distribution(self,
|
def calculate_distribution(self,
|
||||||
network_agents=None,
|
network_agents=None,
|
||||||
@ -178,9 +176,8 @@ class SoilSimulation(NetworkSimulation):
|
|||||||
states=self.states,
|
states=self.states,
|
||||||
default_state=self.default_state,
|
default_state=self.default_state,
|
||||||
environment_agents=self.environment_agents,
|
environment_agents=self.environment_agents,
|
||||||
|
simulation=self,
|
||||||
**self.environment_params)
|
**self.environment_params)
|
||||||
|
|
||||||
env.sim = weakref.ref(self)
|
|
||||||
# Set up agents on nodes
|
# Set up agents on nodes
|
||||||
logger.info('\tRunning')
|
logger.info('\tRunning')
|
||||||
with utils.timer('trial'):
|
with utils.timer('trial'):
|
||||||
|
@ -10,10 +10,15 @@ import networkx as nx
|
|||||||
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
logger.addHandler(logging.StreamHandler())
|
||||||
|
|
||||||
|
|
||||||
def load_network(network_params, dir_path=None):
|
def load_network(network_params, dir_path=None):
|
||||||
|
if network_params is None:
|
||||||
|
return nx.Graph()
|
||||||
path = network_params.get('path', None)
|
path = network_params.get('path', None)
|
||||||
if path:
|
if path:
|
||||||
if dir_path and not os.path.isabs(path):
|
if dir_path and not os.path.isabs(path):
|
||||||
@ -73,9 +78,23 @@ def agent_from_distribution(distribution, value=-1):
|
|||||||
for d in distribution:
|
for d in distribution:
|
||||||
threshold = d['threshold']
|
threshold = d['threshold']
|
||||||
if value >= threshold[0] and value < threshold[1]:
|
if value >= threshold[0] and value < threshold[1]:
|
||||||
state = None
|
state = {}
|
||||||
if 'state' in d:
|
if 'state' in d:
|
||||||
state = deepcopy(d['state'])
|
state = deepcopy(d['state'])
|
||||||
return d['agent_type'], state
|
return d['agent_type'], state
|
||||||
|
|
||||||
raise Exception('Distribution for value {} not found in: {}'.format(value, distribution))
|
raise Exception('Distribution for value {} not found in: {}'.format(value, distribution))
|
||||||
|
|
||||||
|
|
||||||
|
def convert(value, type_):
|
||||||
|
import importlib
|
||||||
|
try:
|
||||||
|
# Check if it's a builtin type
|
||||||
|
module = importlib.import_module('builtins')
|
||||||
|
cls = getattr(module, type_)
|
||||||
|
except AttributeError:
|
||||||
|
# if not, separate module and class
|
||||||
|
module, type_ = type_.rsplit(".", 1)
|
||||||
|
module = importlib.import_module(module)
|
||||||
|
cls = getattr(module, type_)
|
||||||
|
return cls(value)
|
||||||
|
@ -5,7 +5,7 @@ import yaml
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from os.path import join
|
from os.path import join
|
||||||
from soil import simulation, agents, utils
|
from soil import simulation, environment, agents, utils
|
||||||
|
|
||||||
|
|
||||||
ROOT = os.path.abspath(os.path.dirname(__file__))
|
ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||||
@ -198,6 +198,26 @@ class TestMain(TestCase):
|
|||||||
"""
|
"""
|
||||||
Make sure all examples in the examples folder are correct
|
Make sure all examples in the examples folder are correct
|
||||||
"""
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_row_conversion(self):
|
||||||
|
sim = simulation.SoilSimulation()
|
||||||
|
env = environment.SoilEnvironment(simulation=sim)
|
||||||
|
env['test'] = 'test_value'
|
||||||
|
env._save_state(now=0)
|
||||||
|
|
||||||
|
res = list(env.history_to_tuples())
|
||||||
|
assert len(res) == len(env.environment_params)
|
||||||
|
assert ('env', 0, 'test', 'test_value') in res
|
||||||
|
|
||||||
|
env['test'] = 'second_value'
|
||||||
|
env._save_state(now=1)
|
||||||
|
res = list(env.history_to_tuples())
|
||||||
|
|
||||||
|
assert env['env', 0, 'test' ] == 'test_value'
|
||||||
|
assert env['env', 1, 'test' ] == 'second_value'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_example_test(path, config):
|
def make_example_test(path, config):
|
||||||
|
Loading…
Reference in New Issue
Block a user