Networksim additions + fix agents and normal_distribution types
This commit is contained in:
parent
32dbdc860b
commit
03b1f1a4ba
|
@ -12,11 +12,14 @@
|
||||||
|
|
||||||
import math, random
|
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)
|
## Return an integer sampled from a normal distribution (gaussian)
|
||||||
## ⚠ This is not thread-safe
|
## ⚠ This is not thread-safe
|
||||||
# Implementation via the Box-Muller method
|
# Implementation via the Box-Muller method
|
||||||
# See https://en.wikipedia.org/wiki/Box–Muller_transform
|
# See https://en.wikipedia.org/wiki/Box–Muller_transform
|
||||||
|
let
|
||||||
|
mean = mean.float
|
||||||
|
std = std.float
|
||||||
|
|
||||||
var
|
var
|
||||||
z1 {.global.}: float
|
z1 {.global.}: float
|
||||||
|
@ -46,8 +49,8 @@ when isMainModule:
|
||||||
abs(y_true - y)/abs(y_true)
|
abs(y_true - y)/abs(y_true)
|
||||||
|
|
||||||
let
|
let
|
||||||
mu = 1000f
|
mu = 1000
|
||||||
sigma = 12f
|
sigma = 12
|
||||||
a = newSeqWith(10000000, normal_distribution(mean = mu, std = sigma))
|
a = newSeqWith(10000000, normal_distribution(mean = mu, std = sigma))
|
||||||
|
|
||||||
var statistics: RunningStat
|
var statistics: RunningStat
|
||||||
|
@ -61,13 +64,13 @@ when isMainModule:
|
||||||
echo &"{stat:<20} {value:>9.4f} | Expected: {expected:>9.4f}"
|
echo &"{stat:<20} {value:>9.4f} | Expected: {expected:>9.4f}"
|
||||||
|
|
||||||
echo &"Statistics on {a.len} samples"
|
echo &"Statistics on {a.len} samples"
|
||||||
report "Mean: ", statistics.mean, mu
|
report "Mean: ", statistics.mean, mu.float
|
||||||
report "Standard deviation: ", statistics.standardDeviationS, sigma
|
report "Standard deviation: ", statistics.standardDeviationS, sigma.float
|
||||||
|
|
||||||
# Absolute error
|
# Absolute error
|
||||||
doAssert absolute_error(mu, statistics.mean) < 0.6
|
doAssert absolute_error(mu.float, statistics.mean) < 0.6
|
||||||
doAssert absolute_error(sigma, statistics.standardDeviationS) < 0.01
|
doAssert absolute_error(sigma.float, statistics.standardDeviationS) < 0.01
|
||||||
|
|
||||||
# Relative error
|
# Relative error
|
||||||
doAssert relative_error(mu, statistics.mean) < 0.01
|
doAssert relative_error(mu.float, statistics.mean) < 0.01
|
||||||
doAssert relative_error(sigma, statistics.standardDeviationS) < 0.01
|
doAssert relative_error(sigma.float, statistics.standardDeviationS) < 0.01
|
||||||
|
|
|
@ -104,7 +104,7 @@ func hash*(x: Duration): Hash =
|
||||||
|
|
||||||
type
|
type
|
||||||
NetworkSimulator* = ref object
|
NetworkSimulator* = ref object
|
||||||
agents*: seq[int]
|
agents*: seq[Node]
|
||||||
latency_distribution_sample*: proc (): Duration
|
latency_distribution_sample*: proc (): Duration
|
||||||
time*: Duration
|
time*: Duration
|
||||||
objqueue*: TableRef[Duration, seq[(Node, BlockOrSig)]]
|
objqueue*: TableRef[Duration, seq[(Node, BlockOrSig)]]
|
||||||
|
|
|
@ -10,8 +10,32 @@
|
||||||
# Part of Casper+Sharding chain v2.1: https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ#
|
# Part of Casper+Sharding chain v2.1: https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ#
|
||||||
|
|
||||||
import
|
import
|
||||||
tables, times,
|
tables, times, sugar, random,
|
||||||
./fork_choice_types
|
./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) =
|
func broadcast*(self: NetworkSimulator, sender: Node, obj: BlockOrSig) =
|
||||||
for p in self.peers[sender.id]:
|
for p in self.peers[sender.id]:
|
||||||
|
|
Loading…
Reference in New Issue