bubble-economy /

#!/usr/bin/env python
# encoding: utf-8

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 as sp
import numpy as np
from numpy import linalg as linalg
from copy import copy

# we expect params to contain the following keys:
# num_agents, dt, noise, radius, steps
    'num_agents': 100,
    'dt': 0.01,
    'noise': 0.2,
    'radius': 0.05,

class SimState(object):
    "A thin wrapper around some simulation state."
    params = None
    def __init__(self, params):
        self.params = params.copy()

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 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.sqrt(np.sum(np.square(row_vectors), 1)).reshape(-1,1)