@ -1,8 +1,9 @@
import os
import os
import time
import time
import imp
import imp ortlib
import sys
import sys
import yaml
import yaml
import traceback
import networkx as nx
import networkx as nx
from networkx . readwrite import json_graph
from networkx . readwrite import json_graph
from multiprocessing import Pool
from multiprocessing import Pool
@ -78,6 +79,7 @@ class Simulation(NetworkSimulation):
"""
"""
def __init__ ( self , name = None , topology = None , network_params = None ,
def __init__ ( self , name = None , topology = None , network_params = None ,
network_agents = None , agent_type = None , states = None ,
network_agents = None , agent_type = None , states = None ,
default_state = None , interval = 1 , dump = None , dry_run = False ,
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 . seed = str ( seed ) or str ( time . time ( ) )
self . dump = dump
self . dump = dump
self . dry_run = dry_run
self . dry_run = dry_run
sys . path + = [ self . dir_path , os . getcwd ( ) ]
self . environment_params = environment_params or { }
self . environment_params = environment_params or { }
self . environment_class = utils . deserialize ( environment_class ,
self . environment_class = utils . deserialize ( environment_class ,
known_modules = [ ' soil.environment ' , ] ) or Environment
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 [ ]
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 ,
distro = agents . calculate_distribution ( network_agents ,
agent_type )
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 . states = agents . _validate_states ( states ,
self . topology )
self . topology )
@ -136,9 +136,13 @@ class Simulation(NetworkSimulation):
p = Pool ( )
p = Pool ( )
with utils . timer ( ' simulation {} ' . format ( self . name ) ) :
with utils . timer ( ' simulation {} ' . format ( self . name ) ) :
if parallel :
if parallel :
func = partial ( self . run_trial , dry_run = dry_run or self . dry_run ,
func = partial ( self . run_trial_exceptions , dry_run = dry_run or self . dry_run ,
return_env = not parallel , * * kwargs )
return_env = True ,
* * kwargs )
for i in p . imap_unordered ( func , range ( self . num_trials ) ) :
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
yield i
else :
else :
for i in range ( self . num_trials ) :
for i in range ( self . num_trials ) :
@ -188,6 +192,17 @@ class Simulation(NetworkSimulation):
env . dump ( formats = self . dump )
env . dump ( formats = self . dump )
if return_env :
if return_env :
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 ) :
def to_dict ( self ) :
return self . __getstate__ ( )
return self . __getstate__ ( )
@ -221,22 +236,27 @@ class Simulation(NetworkSimulation):
if k [ 0 ] != ' _ ' :
if k [ 0 ] != ' _ ' :
state [ k ] = v
state [ k ] = v
state [ ' topology ' ] = json_graph . node_link_data ( self . topology )
state [ ' topology ' ] = json_graph . node_link_data ( self . topology )
state [ ' network_agents ' ] = agents . serialize_distribution ( self . network_agents )
state [ ' network_agents ' ] = agents . serialize_distribution ( self . network_agents ,
state [ ' environment_agents ' ] = agents . _convert_agent_types ( self . environment_agents ,
known_modules = [ ] )
to_string = True )
state [ ' environment_agents ' ] = agents . serialize_distribution ( self . environment_agents ,
known_modules = [ ] )
state [ ' environment_class ' ] = utils . serialize ( self . environment_class ,
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 :
if state [ ' load_module ' ] is None :
del state [ ' load_module ' ]
del state [ ' load_module ' ]
return state
return state
def __setstate__ ( self , state ) :
def __setstate__ ( self , state ) :
self . __dict__ = 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 . topology = json_graph . node_link_graph ( state [ ' topology ' ] )
self . network_agents = agents . calculate_distribution ( agents . _convert_agent_types ( self . network_agents ) )
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 ,
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
return state