Networksim additions + fix agents and normal_distribution types
This commit is contained in:
parent
32dbdc860b
commit
03b1f1a4ba
|
@ -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/Box–Muller_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
|
||||
|
|
|
@ -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)]]
|
||||
|
|
|
@ -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]:
|
||||
|
|
Loading…
Reference in New Issue