1
0
mirror of https://github.com/gsi-upm/soil synced 2024-11-14 15:32:29 +00:00

Fix state and networkx dynamic attributes

This commit is contained in:
J. Fernando Sánchez 2018-05-07 18:57:41 +02:00
parent 5d89827ccf
commit 5420501d36
5 changed files with 68 additions and 34 deletions

View File

@ -1 +1 @@
0.11.1 0.11.3

View File

@ -53,7 +53,7 @@ class BaseAgent(nxsim.BaseAgent, metaclass=MetaAgent):
self.alive = True self.alive = True
real_state = deepcopy(self.defaults) real_state = deepcopy(self.defaults)
real_state.update(state or {}) real_state.update(state or {})
self._state = real_state self.state = real_state
self.interval = interval self.interval = interval
if not hasattr(self, 'level'): if not hasattr(self, 'level'):
@ -67,10 +67,17 @@ class BaseAgent(nxsim.BaseAgent, metaclass=MetaAgent):
@property @property
def state(self): def state(self):
return self._state '''
Return the agent itself, which behaves as a dictionary.
Changes made to `agent.state` will be reflected in the history.
This method shouldn't be used, but is kept here for backwards compatibility.
'''
return self
@state.setter @state.setter
def state(self, value): def state(self, value):
self._state = {}
for k, v in value.items(): for k, v in value.items():
self[k] = v self[k] = v
@ -79,21 +86,24 @@ class BaseAgent(nxsim.BaseAgent, metaclass=MetaAgent):
key, t_step = key key, t_step = key
k = history.Key(key=key, t_step=t_step, agent_id=self.id) k = history.Key(key=key, t_step=t_step, agent_id=self.id)
return self.env[k] return self.env[k]
return self.state.get(key, None) return self._state.get(key, None)
def __delitem__(self, key): def __delitem__(self, key):
self.state[key] = None self._state[key] = None
def __contains__(self, key): def __contains__(self, key):
return key in self.state return key in self._state
def __setitem__(self, key, value): def __setitem__(self, key, value):
self.state[key] = value self._state[key] = value
k = history.Key(t_step=self.now, k = history.Key(t_step=self.now,
agent_id=self.id, agent_id=self.id,
key=key) key=key)
self.env[k] = value self.env[k] = value
def items(self):
return self._state.items()
def get(self, key, default=None): def get(self, key, default=None):
return self[key] if key in self else default return self[key] if key in self else default

View File

@ -263,31 +263,30 @@ class SoilEnvironment(nxsim.NetworkEnvironment):
history = self[agent.id, None, None] history = self[agent.id, None, None]
if not history: if not history:
continue continue
for t_step, state in reversed(sorted(list(history.items()))): for t_step, attribute, value in sorted(list(history)):
for attribute, value in state.items():
if attribute == 'visible': if attribute == 'visible':
nowvisible = state[attribute] nowvisible = value
if nowvisible and not lastvisible: if nowvisible and not lastvisible:
laststep = t_step laststep = t_step
if not nowvisible and lastvisible: if not nowvisible and lastvisible:
spells.append((laststep, t_step)) spells.append((laststep, t_step))
lastvisible = nowvisible lastvisible = nowvisible
else: continue
key = 'attr_' + attribute key = 'attr_' + attribute
if key not in attributes: if key not in attributes:
attributes[key] = list() attributes[key] = list()
if key not in lastattributes: if key not in lastattributes:
lastattributes[key] = (state[attribute], t_step) lastattributes[key] = (value, t_step)
elif lastattributes[key][0] != value: elif lastattributes[key][0] != value:
last_value, laststep = lastattributes[key] last_value, laststep = lastattributes[key]
value = (last_value, t_step, laststep) commit_value = (last_value, laststep, t_step)
if key not in attributes: if key not in attributes:
attributes[key] = list() attributes[key] = list()
attributes[key].append(value) attributes[key].append(commit_value)
lastattributes[key] = (state[attribute], t_step) lastattributes[key] = (value, t_step)
for k, v in lastattributes.items(): for k, v in lastattributes.items():
attributes[k].append((v[0], 0, v[1])) attributes[k].append((v[0], v[1], None))
if lastvisible: if lastvisible:
spells.append((laststep, None)) spells.append((laststep, None))
if spells: if spells:

View File

@ -102,7 +102,9 @@ class History:
t_steps=t_steps, t_steps=t_steps,
keys=keys) keys=keys)
r = Records(df, filter=key, dtypes=self._dtypes) r = Records(df, filter=key, dtypes=self._dtypes)
if r.resolved:
return r.value() return r.value()
return r
@ -216,16 +218,23 @@ class Records():
return i.iloc[ix] return i.iloc[ix]
except KeyError: except KeyError:
return self.dtypes[f.key][2]() return self.dtypes[f.key][2]()
return self return list(self)
def __getitem__(self, k): def __getitem__(self, k):
n = copy.copy(self) n = copy.copy(self)
n.filter(k) n.filter(k)
if n.resolved:
return n.value() return n.value()
return n
def __len__(self): def __len__(self):
return len(self._df) return len(self._df)
def __str__(self):
if self.resolved:
return str(self.value())
return '<Records for [{}]>'.format(self._filter)
Key = namedtuple('Key', ['agent_id', 't_step', 'key']) Key = namedtuple('Key', ['agent_id', 't_step', 'key'])
Record = namedtuple('Record', 'agent_id t_step key value') Record = namedtuple('Record', 'agent_id t_step key value')

View File

@ -233,10 +233,26 @@ class TestMain(TestCase):
There is a bug in networkx that prevents it from creating a GEXF file There is a bug in networkx that prevents it from creating a GEXF file
from geometric models. We should work around it. from geometric models. We should work around it.
""" """
G = nx.random_geometric_graph(20,0.1) G = nx.random_geometric_graph(20, 0.1)
env = environment.SoilEnvironment(topology=G, dry_run=True) env = environment.SoilEnvironment(topology=G, dry_run=True)
env.dump_gexf('/tmp/dump-gexf') env.dump_gexf('/tmp/dump-gexf')
def test_save_graph(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.SoilEnvironment(topology=G, network_agents=distribution, dry_run=True)
env[0, 0, 'testvalue'] = 'start'
env[0, 10, 'testvalue'] = 'finish'
nG = env.history_to_graph()
values = nG.node[0]['attr_testvalue']
assert ('start', 0, 10) in values
assert ('finish', 10, None) in values
def make_example_test(path, config): def make_example_test(path, config):
def wrapped(self): def wrapped(self):