@ -1,8 +1,9 @@
import os
import time
import imp
import imp ortlib
import sys
import yaml
import traceback
import networkx as nx
from networkx . readwrite import json_graph
from multiprocessing import Pool
@ -78,6 +79,7 @@ class Simulation(NetworkSimulation):
"""
def __init__ ( self , name = None , topology = None , network_params = None ,
network_agents = None , agent_type = None , states = None ,
default_state = None , interval = 1 , dump = None , dry_run = False ,
@ -104,23 +106,21 @@ class Simulation(NetworkSimulation):
self . seed = str ( seed ) or str ( time . time ( ) )
self . dump = dump
self . dry_run = dry_run
sys . path + = [ self . dir_path , os . getcwd ( ) ]
self . environment_params = environment_params or { }
self . environment_class = utils . deserialize ( environment_class ,
known_modules = [ ' soil.environment ' , ] ) or Environment
self . _loaded_module = None
if load_module :
path = sys . path + [ self . dir_path , os . getcwd ( ) ]
f , fp , desc = imp . find_module ( load_module , path )
self . _loaded_module = imp . load_module ( ' soil.agents.custom ' , f , fp , desc )
environment_agents = environment_agents or [ ]
self . environment_agents = agents . _convert_agent_types ( environment_agents )
self . environment_agents = agents . _convert_agent_types ( environment_agents ,
known_modules = [ self . load_module ] )
distro = agents . calculate_distribution ( network_agents ,
agent_type )
self . network_agents = agents . _convert_agent_types ( distro )
self . network_agents = agents . _convert_agent_types ( distro ,
known_modules = [ self . load_module ] )
self . states = agents . _validate_states ( states ,
self . topology )
@ -136,9 +136,13 @@ class Simulation(NetworkSimulation):
p = Pool ( )
with utils . timer ( ' simulation {} ' . format ( self . name ) ) :
if parallel :
func = partial ( self . run_trial , dry_run = dry_run or self . dry_run ,
return_env = not parallel , * * kwargs )
func = partial ( self . run_trial_exceptions , dry_run = dry_run or self . dry_run ,
return_env = True ,
* * kwargs )
for i in p . imap_unordered ( func , range ( self . num_trials ) ) :
if isinstance ( i , Exception ) :
logger . error ( ' Trial failed: \n \t {} ' . format ( i . message ) )
continue
yield i
else :
for i in range ( self . num_trials ) :
@ -188,6 +192,17 @@ class Simulation(NetworkSimulation):
env . dump ( formats = self . dump )
if return_env :
return env
def run_trial_exceptions ( self , * args , * * kwargs ) :
'''
A wrapper for run_trial that catches exceptions and returns them .
It is meant for async simulations
'''
try :
return self . run_trial ( * args , * * kwargs )
except Exception as ex :
c = ex . __cause__
c . message = ' ' . join ( traceback . format_tb ( c . __traceback__ ) [ 3 : ] )
return c
def to_dict ( self ) :
return self . __getstate__ ( )
@ -221,22 +236,27 @@ class Simulation(NetworkSimulation):
if k [ 0 ] != ' _ ' :
state [ k ] = v
state [ ' topology ' ] = json_graph . node_link_data ( self . topology )
state [ ' network_agents ' ] = agents . serialize_distribution ( self . network_agents )
state [ ' environment_agents ' ] = agents . _convert_agent_types ( self . environment_agents ,
to_string = True )
state [ ' network_agents ' ] = agents . serialize_distribution ( self . network_agents ,
known_modules = [ ] )
state [ ' environment_agents ' ] = agents . serialize_distribution ( self . environment_agents ,
known_modules = [ ] )
state [ ' environment_class ' ] = utils . serialize ( self . environment_class ,
known_modules = [ ' soil.environment ' , ]) [ 1 ] # func, name
known_modules = [ ' soil.environment ' ]) [ 1 ] # func, name
if state [ ' load_module ' ] is None :
del state [ ' load_module ' ]
return state
def __setstate__ ( self , state ) :
self . __dict__ = state
self . load_module = getattr ( self , ' load_module ' , None )
if self . dir_path not in sys . path :
sys . path + = [ self . dir_path , os . getcwd ( ) ]
self . topology = json_graph . node_link_graph ( state [ ' topology ' ] )
self . network_agents = agents . calculate_distribution ( agents . _convert_agent_types ( self . network_agents ) )
self . environment_agents = agents . _convert_agent_types ( self . environment_agents )
self . environment_agents = agents . _convert_agent_types ( self . environment_agents ,
known_modules = [ self . load_module ] )
self . environment_class = utils . deserialize ( self . environment_class ,
known_modules = [ ' soil.environment ' , ] ) # func, name
known_modules = [ self . load_module , ' soil.environment ' , ] ) # func, name
return state