Networksim additions + fix agents and normal_distribution types

This commit is contained in:
mratsim 2018-09-10 12:35:11 +02:00
parent 32dbdc860b
commit 03b1f1a4ba
3 changed files with 39 additions and 12 deletions

View File

@ -12,11 +12,14 @@
import math, random
proc normal_distribution*(mean = 0.0, std = 1.0): int =
proc normal_distribution*(mean = 0, std = 1): int =
## Return an integer sampled from a normal distribution (gaussian)
## ⚠ This is not thread-safe
# Implementation via the Box-Muller method
# See https://en.wikipedia.org/wiki/BoxMuller_transform
let
mean = mean.float
std = std.float
var
z1 {.global.}: float
@ -46,8 +49,8 @@ when isMainModule:
abs(y_true - y)/abs(y_true)
let
mu = 1000f
sigma = 12f
mu = 1000
sigma = 12
a = newSeqWith(10000000, normal_distribution(mean = mu, std = sigma))
var statistics: RunningStat
@ -61,13 +64,13 @@ when isMainModule:
echo &"{stat:<20} {value:>9.4f} | Expected: {expected:>9.4f}"
echo &"Statistics on {a.len} samples"
report "Mean: ", statistics.mean, mu
report "Standard deviation: ", statistics.standardDeviationS, sigma
report "Mean: ", statistics.mean, mu.float
report "Standard deviation: ", statistics.standardDeviationS, sigma.float
# Absolute error
doAssert absolute_error(mu, statistics.mean) < 0.6
doAssert absolute_error(sigma, statistics.standardDeviationS) < 0.01
doAssert absolute_error(mu.float, statistics.mean) < 0.6
doAssert absolute_error(sigma.float, statistics.standardDeviationS) < 0.01
# Relative error
doAssert relative_error(mu, statistics.mean) < 0.01
doAssert relative_error(sigma, statistics.standardDeviationS) < 0.01
doAssert relative_error(mu.float, statistics.mean) < 0.01
doAssert relative_error(sigma.float, statistics.standardDeviationS) < 0.01

View File

@ -104,7 +104,7 @@ func hash*(x: Duration): Hash =
type
NetworkSimulator* = ref object
agents*: seq[int]
agents*: seq[Node]
latency_distribution_sample*: proc (): Duration
time*: Duration
objqueue*: TableRef[Duration, seq[(Node, BlockOrSig)]]

View File

@ -10,8 +10,32 @@
# Part of Casper+Sharding chain v2.1: https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ#
import
tables, times,
./fork_choice_types
tables, times, sugar, random,
./fork_choice_types, ./distributions
proc initNetworkSimulator*(latency: int): NetworkSimulator =
result.latency_distribution_sample = () => initDuration(
seconds = max(
0,
normal_distribution(latency, latency * 2 div 5)
)
)
result.reliability = 0.9
result.objqueue = newTable[Duration, seq[(Node, BlockOrSig)]]()
result.peers = newTable[int, seq[Node]]()
proc generate_peers*(self: NetworkSimulator, num_peers = 5) =
self.peers.clear()
var p: seq[Node]
for a in self.agents:
p.setLen(0) # reset without involving GC/realloc
while p.len <= num_peers div 2:
p.add self.agents.rand()
if p[^1] == a:
discard p.pop()
self.peers[a.id].add p
for peer in p:
self.peers[peer.id].add a
func broadcast*(self: NetworkSimulator, sender: Node, obj: BlockOrSig) =
for p in self.peers[sender.id]: