Commits

dan mackinlay committed 6c45f3e

handle seeds in branched experiments

  • Participants
  • Parent commits ce9b2b2

Comments (0)

Files changed (1)

 TODO:
 * Consider calculating MI between *relative* axial positions or velocities of pairs of particles over time,
   rather than branching histories, which also might work in the infinite-time limit.
-* Parallelise in something natural, such as redis or 0MQ, or ruffus.
+* Parallelise in something natural, such as redis or 0MQ, or ruffus. Probably ruffus + sqlite is easiest.
 
 """
 from __future__ import division
 from scipy.spatial import distance
 import pyentropy
 from random import sample
+import itertools
 
 # we expect params to contain the following keys:
 # n_agents, dt, noise, radius, steps
-DEFAULT_PARAMS = {
+DEFAULT_TRIAL_PARAMS = {
     'n_agents': 100,
     'dt': 0.01,
     'noise': 0.2,
     'n_branches': 100,
 }
 
+def sweep_branched_experiment(sweepables=None, base_params=DEFAULT_TRIAL_PARAMS, oversample=1, start_seed=10000):
+    sweepables = sweepables or {} #cast to empty dict
+    swept_names = sweepables.keys()
+    swept_iterables = [sweepables[name] for name in swept_names]
+    trials = []
+    seed = start_seed
+    for swept_values in itertools.product(*swept_iterables):
+        these_params = base_params.copy()
+        these_params.update(zip(swept_names, swept_values))
+        for sample_i in xrange(oversample):
+            trials.append(branched_flocking_experiment(these_params, seed=seed))
+            seed = abs(hash(str(5))) #start seed in very different places next time
+    return trials
+
+def branched_flocking_experiment(base_params=DEFAULT_TRIAL_PARAMS, seed=1):
+    """
+    Run a sim, stop it after a number of iterations.
+    Then run alternate versions with a given seed, keeping the results.
+    """
+    base_simstate = do_flocking_sim(basic_flock_factory(base_params), steps=base_params['discard_steps'], seed=seed)
+    #the sim might decorate the params dict with additional stuff. mostly the seed, i suppose.
+    base_params = base_simstate.params
+    #since we are branching, we store the original seed in 'base_seed' and keep 'seed' for most recent seed
+    # should seeds have a separate data structure for clarity?
+    base_params['base_seed'] = seed
+    return [
+        do_flocking_sim(base_simstate, steps=base_params['branch_steps'], seed=seed+i+1)
+        for i in xrange(base_params['n_branches'])
+    ]
+
 def do_flocking_sim(simstate, steps=100, seed=1):
     """
-    Starting from the state in *simstate*, iterate the simulation *steps* times.
+    Starting from the state in *simstate*, iterate the simulation *steps* times with different seeds.
     """
     simstate = simstate.clone()
     params = simstate.params
     simstate.vels = vels
     return simstate        
 
-def branched_flocking_experiment(params=DEFAULT_PARAMS, seed=1):
-    """
-    Run a sim, stop it after a number of iterations.
-    Then run alternate versions with a given seed, keeping the results.
-    """
-    base_simstate = do_flocking_sim(basic_flock_factory(params), steps=params['discard_steps'], seed=seed)
-    base_simstate.params['base_seed'] = seed
-    return [
-        do_flocking_sim(base_simstate, steps=params['branch_steps'], seed=seed+i)
-        for i in xrange(params['n_branches'])
-    ]
-
 def analyse_branched_experiment(branches, n_pairs=10):
     """Take a list of stacked trials and analyse them."""
     #I'm punting I can ignore most of the state vector. Anyway, they'll be fiddly.