mirror of
https://github.com/gsi-upm/soil
synced 2025-04-25 14:19:04 +00:00
See CHANGELOG.md for a full list of changes * Removed nxsim * Refactored `agents.NetworkAgent` and `agents.BaseAgent` * Refactored exporters * Added stats to history
107 lines
2.9 KiB
Python
107 lines
2.9 KiB
Python
import pandas as pd
|
|
|
|
from collections import Counter
|
|
|
|
class Stats:
|
|
'''
|
|
Interface for all stats. It is not necessary, but it is useful
|
|
if you don't plan to implement all the methods.
|
|
'''
|
|
|
|
def __init__(self, simulation):
|
|
self.simulation = simulation
|
|
|
|
def start(self):
|
|
'''Method to call when the simulation starts'''
|
|
pass
|
|
|
|
def end(self):
|
|
'''Method to call when the simulation ends'''
|
|
return {}
|
|
|
|
def trial(self, env):
|
|
'''Method to call when a trial ends'''
|
|
return {}
|
|
|
|
|
|
class distribution(Stats):
|
|
'''
|
|
Calculate the distribution of agent states at the end of each trial,
|
|
the mean value, and its deviation.
|
|
'''
|
|
|
|
def start(self):
|
|
self.means = []
|
|
self.counts = []
|
|
|
|
def trial(self, env):
|
|
df = env[None, None, None].df()
|
|
df = df.drop('SEED', axis=1)
|
|
ix = df.index[-1]
|
|
attrs = df.columns.get_level_values(0)
|
|
vc = {}
|
|
stats = {
|
|
'mean': {},
|
|
'count': {},
|
|
}
|
|
for a in attrs:
|
|
t = df.loc[(ix, a)]
|
|
try:
|
|
stats['mean'][a] = t.mean()
|
|
self.means.append(('mean', a, t.mean()))
|
|
except TypeError:
|
|
pass
|
|
|
|
for name, count in t.value_counts().iteritems():
|
|
if a not in stats['count']:
|
|
stats['count'][a] = {}
|
|
stats['count'][a][name] = count
|
|
self.counts.append(('count', a, name, count))
|
|
|
|
return stats
|
|
|
|
def end(self):
|
|
dfm = pd.DataFrame(self.means, columns=['metric', 'key', 'value'])
|
|
dfc = pd.DataFrame(self.counts, columns=['metric', 'key', 'value', 'count'])
|
|
|
|
count = {}
|
|
mean = {}
|
|
|
|
if self.means:
|
|
res = dfm.groupby(by=['key']).agg(['mean', 'std', 'count', 'median', 'max', 'min'])
|
|
mean = res['value'].to_dict()
|
|
if self.counts:
|
|
res = dfc.groupby(by=['key', 'value']).agg(['mean', 'std', 'count', 'median', 'max', 'min'])
|
|
for k,v in res['count'].to_dict().items():
|
|
if k not in count:
|
|
count[k] = {}
|
|
for tup, times in v.items():
|
|
subkey, subcount = tup
|
|
if subkey not in count[k]:
|
|
count[k][subkey] = {}
|
|
count[k][subkey][subcount] = times
|
|
|
|
|
|
return {'count': count, 'mean': mean}
|
|
|
|
|
|
class defaultStats(Stats):
|
|
|
|
def trial(self, env):
|
|
c = Counter()
|
|
c.update(a.__class__.__name__ for a in env.network_agents)
|
|
|
|
c2 = Counter()
|
|
c2.update(a['id'] for a in env.network_agents)
|
|
|
|
return {
|
|
'network ': {
|
|
'n_nodes': env.G.number_of_nodes(),
|
|
'n_edges': env.G.number_of_nodes(),
|
|
},
|
|
'agents': {
|
|
'model_count': dict(c),
|
|
'state_count': dict(c2),
|
|
}
|
|
}
|