This code simulates a distributed averaging protocol. There is a network of nodes, and at the clicks of a Poisson process:
A random node wakes up
Transmits it's current average to all the nodes it is connected to
These nodes have a coroutine which waits to accept new values and compute the average.
from numpy.random import exponential, randint, uniform import time from itertools import product class Node(object): def __init__(self, number): self.friends =  self.count = 0 self.val = number self.average = number self.avg = self.averager() self.avg.next() def averager(self): while True: term = yield self.average self.val += term self.count += 1 self.average = self.val/self.count class Network(object): def __init__(self, num_nodes): self.nodes = *num_nodes for i in range(num_nodes): self.nodes[i] = Node(randint(1, 10)) self.set_connections() def set_connections(self): for f, g in product(self.nodes, self.nodes): p = uniform() if p < 0.8: f.friends.append(g) g.friends.append(f) def mainloop(self): num_nodes = len(self.nodes) while True: next_time = exponential(0.1) node = self.nodes[randint(num_nodes)] for friend in node.friends: friend.avg.send(node.average) print friend.average time.sleep(next_time)
So far I've only tested it as follows:
>>> n = Network(10) >>> n.mainloop()
and then observed that the friend.average printed out all converge to the same value.
My main concern about this code is that a lot of the logic for waking up nodes is in the Network class, whilst I'd rather it was in the node class. Also, there's no exception/error handling, or proper testing.
The main purpose of this was to try and understand coroutines, which was a bit of a mind bender.