2015-07-19 19:01:20 +00:00
|
|
|
from distributions import transform, normal_distribution
|
|
|
|
import random
|
|
|
|
|
|
|
|
|
|
|
|
class NetworkSimulator():
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.agents = []
|
|
|
|
self.latency_distribution_sample = transform(normal_distribution(50, 20), lambda x: max(x, 0))
|
|
|
|
self.time = 0
|
|
|
|
self.objqueue = {}
|
|
|
|
self.peers = {}
|
|
|
|
self.reliability = 0.9
|
|
|
|
|
|
|
|
def generate_peers(self, num_peers=5):
|
|
|
|
self.peers = {}
|
|
|
|
for a in self.agents:
|
|
|
|
p = []
|
2015-08-27 13:38:48 +00:00
|
|
|
while len(p) <= num_peers // 2:
|
2015-07-19 19:01:20 +00:00
|
|
|
p.append(random.choice(self.agents))
|
|
|
|
if p[-1] == a:
|
|
|
|
p.pop()
|
2015-08-27 13:38:48 +00:00
|
|
|
self.peers[a.id] = self.peers.get(a.id, []) + p
|
|
|
|
for peer in p:
|
|
|
|
self.peers[peer.id] = self.peers.get(peer.id, []) + [a]
|
2015-07-19 19:01:20 +00:00
|
|
|
|
|
|
|
def tick(self):
|
|
|
|
if self.time in self.objqueue:
|
|
|
|
for recipient, obj in self.objqueue[self.time]:
|
|
|
|
if random.random() < self.reliability:
|
|
|
|
recipient.on_receive(obj)
|
|
|
|
del self.objqueue[self.time]
|
|
|
|
for a in self.agents:
|
|
|
|
a.tick()
|
|
|
|
self.time += 1
|
|
|
|
|
|
|
|
def run(self, steps):
|
|
|
|
for i in range(steps):
|
|
|
|
self.tick()
|
|
|
|
|
|
|
|
def broadcast(self, sender, obj):
|
|
|
|
for p in self.peers[sender.id]:
|
|
|
|
recv_time = self.time + self.latency_distribution_sample()
|
|
|
|
if recv_time not in self.objqueue:
|
|
|
|
self.objqueue[recv_time] = []
|
|
|
|
self.objqueue[recv_time].append((p, obj))
|
|
|
|
|
|
|
|
def direct_send(self, to_id, obj):
|
|
|
|
for a in self.agents:
|
|
|
|
if a.id == to_id:
|
|
|
|
recv_time = self.time + self.latency_distribution_sample()
|
|
|
|
if recv_time not in self.objqueue:
|
|
|
|
self.objqueue[recv_time] = []
|
|
|
|
self.objqueue[recv_time].append((a, obj))
|
|
|
|
|
|
|
|
def knock_offline_random(self, n):
|
|
|
|
ko = {}
|
|
|
|
while len(ko) < n:
|
|
|
|
c = random.choice(self.agents)
|
|
|
|
ko[c.id] = c
|
|
|
|
for c in ko.values():
|
|
|
|
self.peers[c.id] = []
|
|
|
|
for a in self.agents:
|
|
|
|
self.peers[a.id] = [x for x in self.peers[a.id] if x.id not in ko]
|
|
|
|
|
|
|
|
def partition(self):
|
|
|
|
a = {}
|
|
|
|
while len(a) < len(self.agents) / 2:
|
|
|
|
c = random.choice(self.agents)
|
|
|
|
a[c.id] = c
|
|
|
|
for c in self.agents:
|
|
|
|
if c.id in a:
|
|
|
|
self.peers[c.id] = [x for x in self.peers[c.id] if x.id in a]
|
|
|
|
else:
|
|
|
|
self.peers[c.id] = [x for x in self.peers[c.id] if x.id not in a]
|