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:
parent
5d89827ccf
commit
5420501d36
@ -1 +1 @@
|
|||||||
0.11.1
|
0.11.3
|
@ -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
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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')
|
||||||
|
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user