Commits

dan mackinlay committed cd9f1bb

Less code is more code

Comments (0)

Files changed (1)

 #!/usr/bin/env python
 # encoding: utf-8
 """
-traders.py
+flock.py
 
 Created by dan mackinlay on 2010-10-18.
 Copyright (c) 2010 __MyCompanyName__. All rights reserved.
+
+>>> simstate = do_flocking_sim(basic_flock_factory(DEFAULT_PARAMS))
 """
 from __future__ import division
 
-import scipy
+import scipy as sp
 import numpy as np
 from numpy import linalg as linalg
+from copy import copy
 
-class FlockState(object):
+# we expect params to contain the following keys:
+# num_agents, dt, noise, radius, steps
+DEFAULT_PARAMS = {
+    'num_agents': 100,
+    'dt': 0.01,
+    'noise': 0.2,
+    'radius': 0.05,
+}
+
+class SimState(object):
     "A thin wrapper around some simulation state."
-    vels = None
-    locs = None
-    distances = None
     params = None
-    def __init__(self, vels, locs, distances, params):
+    def __init__(self, params):
         self.params = params.copy()
-        self.vels = vels
-        self.locs = locs
-        self.distances = distances
 
-def basic_flock_factory(vels=None, locs=None, distances=None, params):
-    # we expect params to contain the following keys:
-    # num_agents, delta, noise, radius, steps and optionally seed. we also allow a re-seed.
-    if vels is None:
-        vels = np.zeros() #random_unit_vectors(params['num_agents'])
-    else:
-        vels = vels
-    if locs is None:
-        locs = scipy.random.uniform(size=(params['num_agents'], params['dimensions']))
-    else:
-        locs = vels
-    # if distances is None:
-    #         distances = scipy.random.uniform(size=(params['num_agents'], params['dimensions']))
-    #     else:
-    #         distances = distances
-    
-    return FlockState(vels = vels, locs=locs, distances=None, params=params)
+def basic_flock_factory(params):
+    sim = SimState(params=params)
+    sim.locs = np.random.uniform(size=(params['num_agents'], 2))
+    sim.vels = random_unit_vectors(params)
+    return sim    
 
-def flocking_sim():
-    pass
-    
+def do_flocking_sim(simstate, steps=100, seed=None):
+    simstate = copy(simstate)
+    params = simstate.params
+    for step in xrange(steps):
+        simstate.vels = normalise_lengths(simstate.vels + random_unit_vectors(params) * params['noise'])
+        simstate.locs = simstate.locs + params['dt'] * simstate.vels
+    return simstate        
+
+def random_unit_vectors(params):
+    """general a matrix of isotropically-distributed unit row vectors"""
+    #the normal distribution is isotropic in all dimensions
+    vectors = np.random.normal(0., 1., (params['num_agents'], 2))
+    return normalise_lengths(vectors)
+
+def normalise_lengths(row_vectors):
+    """normalise the lengths of some stacked row vectors.
+    """
+    return row_vectors / (np.sum(row_vectors * row_vectors, 1).reshape(-1,1))