Skip to content

Commit e8c8cda

Browse files
committed
Added source documentation
1 parent dda9539 commit e8c8cda

File tree

10 files changed

+291
-1
lines changed

10 files changed

+291
-1
lines changed

analysis/markov/Linleios.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
import Linleios.Evolve
2+
3+
/-!
4+
# Linleios: a Markovian model of Linear Leios
5+
-/

analysis/markov/Linleios/Evolve.lean

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ open Lean.ToJson (toJson)
1111
open Std (HashMap)
1212

1313

14+
/--
15+
Try to forge an RB in this substep, given the state and environment.
16+
-/
1417
def forgeRb {env : Environment} (state : State) : Outcomes :=
1518
let state' :=
1619
{
@@ -23,6 +26,9 @@ def forgeRb {env : Environment} (state : State) : Outcomes :=
2326
, ({state' with hasRb := false, canCertify := false}, 1 - p)
2427
]
2528

29+
/--
30+
Try to include a certificate in the latest RB being forged in this substep, given the state and environment.
31+
-/
2632
def certify {env : Environment} (state : State) : Outcomes :=
2733
if state.hasRb && state.canCertify
2834
then let p := env.pSpacingOkay
@@ -32,6 +38,9 @@ def certify {env : Environment} (state : State) : Outcomes :=
3238
]
3339
else [(state, 1)]
3440

41+
/--
42+
Try to forge an EB in this substep, given the state and environment.
43+
-/
3544
def forgeEb {env : Environment} (state : State) : Outcomes :=
3645
if state.hasRb
3746
then let p := 1 - env.pLate
@@ -41,6 +50,9 @@ def forgeEb {env : Environment} (state : State) : Outcomes :=
4150
]
4251
else [(state, 1)]
4352

53+
/--
54+
Try to vote for an EB in this substep, given the state and environment.
55+
-/
4456
def vote {env : Environment} (state : State) : Outcomes :=
4557
if state.hasRb
4658
then let p := env.pQuorum
@@ -50,13 +62,22 @@ def vote {env : Environment} (state : State) : Outcomes :=
5062
]
5163
else [(state, 1)]
5264

65+
/--
66+
Step forward to the next potential block.
67+
-/
5368
def step {env : Environment} : List (State → Outcomes) :=
5469
[@forgeRb env, @certify env, @forgeEb env, @vote env]
5570

5671

72+
/--
73+
Discard probabilities below the specified threshold.
74+
-/
5775
def prune (ε : Float) : Probabilities → Probabilities :=
5876
HashMap.filter (fun _ p => p > ε)
5977

78+
/--
79+
Evolve state probabilities on step forward according the a transition function.
80+
-/
6081
def evolve (transition : State → Outcomes) : Probabilities → Probabilities :=
6182
HashMap.fold
6283
(
@@ -68,19 +89,32 @@ def evolve (transition : State → Outcomes) : Probabilities → Probabilities :
6889
)
6990
7091

92+
/--
93+
Chain a sequence of transitions sequentially, evolving probabilities.
94+
-/
7195
def chain (transitions : List (State → Outcomes)) : Probabilities → Probabilities :=
7296
match transitions with
7397
| [] => id
7498
| (t :: ts) => chain ts ∘ evolve t
7599

100+
/--
101+
Simulate the specified number of potential blocks, given a starting set of probabilities.
102+
-/
76103
def simulate (env : Environment) (start : Probabilities) (ε : Float) : Nat → Probabilities
77104
| 0 => start
78105
| n + 1 => let state' := prune ε $ chain (@step env) start
79106
simulate env state' ε n
80107

108+
109+
/--
110+
Compute the total probabilities of a set of states.
111+
-/
81112
def totalProbability (states : Probabilities) : Probability :=
82113
states.values.sum
83114

115+
/--
116+
Compute the distribution of EB counts.
117+
-/
84118
def ebDistribution : Probabilities → HashMap Nat Probability :=
85119
HashMap.fold
86120
(
@@ -90,13 +124,19 @@ def ebDistribution : Probabilities → HashMap Nat Probability :=
90124
)
91125
92126

127+
/--
128+
Format the distribution of EB counts as JSON.
129+
-/
93130
def ebDistributionJson : Probabilities → Json :=
94131
Json.mkObj
95132
∘ List.map (fun ⟨k, v⟩ => ⟨toString k, toJson v⟩)
96133
∘ (fun z => z.mergeSort (by exact fun x y => x.fst ≤ y.fst))
97134
∘ HashMap.toList
98135
∘ ebDistribution
99136

137+
/--
138+
Compute the RB efficiency, given a set of states.
139+
-/
100140
def rbEfficiency (states : Probabilities) : Float :=
101141
let clock := states.keys.head!.clock
102142
let rbCount :=
@@ -106,6 +146,9 @@ def rbEfficiency (states : Probabilities) : Float :=
106146
states
107147
rbCount / clock.toFloat
108148

149+
/--
150+
Compute the EB efficiency, given a set of states.
151+
-/
109152
def ebEfficiency (states : Probabilities) : Float :=
110153
let clock := states.keys.head!.clock
111154
let ebCount :=
@@ -115,6 +158,9 @@ def ebEfficiency (states : Probabilities) : Float :=
115158
states
116159
ebCount / (clock.toFloat - 1)
117160

161+
/--
162+
Compute the overall efficiency, give a set of states.
163+
-/
118164
def efficiency (states : Probabilities) : Float :=
119165
let rb := rbEfficiency states
120166
let eb := ebEfficiency states

analysis/markov/Linleios/Probability.lean

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,30 @@
22
import Linleios.Util
33

44

5+
/--
6+
Number of stake pools.
7+
-/
58
def nPools : Nat := 2500
69

10+
/--
11+
Compute a realistic stake distribution for the specified number of pools.
12+
-/
713
def stakeDistribution (nPools : Nat) : List Float :=
814
(List.range nPools).map (fun k => ((k + 1).toFloat / nPools.toFloat)^10 - (k.toFloat / nPools.toFloat)^10)
915

16+
/--
17+
Determine the distribution parameter that achieves the specified committee size.
18+
-/
1019
private def calibrateCommittee(committeeSize : Float) : Float :=
1120
let stakes : List Float := stakeDistribution nPools
1221
let f (m : Float) : Float :=
1322
let ps : List Float := stakes.map (fun s => 1 - Float.exp (- m * s))
1423
ps.sum - committeeSize
1524
bisectionSearch f committeeSize nPools.toFloat 0.5 10
1625

26+
/--
27+
Compute the mean and standard deviation of the committee size, given the probability of a successful vote and a target committee size.
28+
-/
1729
private def committeeDistribution (pSuccessfulVote committeeSize : Float) : Float × Float :=
1830
let stakes : List Float := stakeDistribution nPools
1931
let m := calibrateCommittee committeeSize
@@ -22,6 +34,9 @@ private def committeeDistribution (pSuccessfulVote committeeSize : Float) : Floa
2234
let σ := (ps.map (fun p => p * (1 - p))).sum.sqrt
2335
⟨ μ , σ ⟩
2436

37+
/--
38+
Compute the probability of a quorum, given the probability of a successful vote, the target committee size, and the quorum fraction.
39+
-/
2540
def pQuorum (pSuccessfulVote committeeSize τ : Float) : Float :=
2641
let ⟨ μ , σ ⟩ := committeeDistribution pSuccessfulVote committeeSize
2742
1 - cdfGaussian (τ * committeeSize) μ σ

analysis/markov/Linleios/Types.lean

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,44 @@ import Linleios.Probability
77
open Std (HashMap)
88

99

10+
/--
11+
Represent probabilities as floating-point numbers.
12+
-/
1013
abbrev Probability := Float
1114

12-
15+
/--
16+
The constant parameters used for computing transitions.
17+
-/
1318
structure Environment where
19+
/-- The active slot coefficient. -/
1420
activeSlotCoefficient : Probability
21+
/-- The $L_\text{hdr}$ protocol parameter. -/
1522
Lheader : Nat
23+
/-- The $L_\text{vote}$ protocol parameter. -/
1624
Lvote : Nat
25+
/-- The $L_\text{diff}$ protocol parameter. -/
1726
Ldiff : Nat
27+
/-- The probability that an RB occurs long enough after the previous RB so that an EB can be certified. -/
1828
pSpacingOkay : Probability
29+
/-- The per-step quorum probability. -/
1930
pQuorum : Probability
31+
/-- The probability that the EB and transaction data arrives too late to compute the ledger. -/
2032
pLate : Probability
33+
/-- The fraction of adversarial stake. -/
2134
fAdversary : Float
2235
deriving Repr
2336

37+
/--
38+
Create an environment.
39+
40+
- `activeSlotCoefficient`: the active slot coefficient
41+
- `committeeSize`: the mean committee size
42+
- `τ`: the quorum fraction
43+
- `pRbHeaderArrives`: the probability that an RB header arrives before $L_\text{hdr}$ slots
44+
- `pEBValidates`: the probability that an EB is validated before $3 L_\text{hdr} + L_\text{vote} + L_\text{diff}$ slots
45+
- `pEbUnvalidated`: the probability that the EB and transaction data arrives too late to compute the ledger
46+
- `fAdversary`: the fraction of adversarial stake
47+
-/
2448
def makeEnvironment (Lheader Lvote Ldiff : Nat) (activeSlotCoefficient committeeSize τ pRbHeaderArrives pEbValidates pEbUnvalidated fAdversary : Float) : Environment :=
2549
{
2650
activeSlotCoefficient := activeSlotCoefficient
@@ -34,14 +58,25 @@ def makeEnvironment (Lheader Lvote Ldiff : Nat) (activeSlotCoefficient committee
3458
}
3559

3660

61+
/--
62+
The state of the chain's evolution.
63+
-/
3764
structure State where
65+
/-- The number of potential RB oppurtunities. -/
3866
clock : Nat
67+
/-- The number of RBs actually forged. -/
3968
rbCount : Nat
69+
/-- The number of EBs certified. -/
4070
ebCount : Nat
71+
/-- Whether an RB was forged in the current step. -/
4172
hasRb : Bool
73+
/-- Whether an EB could be certified in the current step. -/
4274
canCertify : Bool
4375
deriving Repr, BEq, Hashable, Inhabited
4476

77+
/--
78+
The genesis state starts when zero counts.
79+
-/
4580
theorem genesis : (default : State).clock = 0 ∧ (default : State).rbCount = 0 ∧ (default : State).ebCount = 0 := by
4681
constructor
4782
rfl
@@ -50,11 +85,16 @@ theorem genesis : (default : State).clock = 0 ∧ (default : State).rbCount = 0
5085
rfl
5186

5287

88+
/--
89+
The active states and their probabilities.
90+
-/
5391
def Probabilities := HashMap State Probability
5492
deriving Repr, EmptyCollection
5593

5694
instance : Inhabited Probabilities where
5795
default := (∅ : Probabilities).insert Inhabited.default 1
5896

5997

98+
/--
99+
An outcome is a list of new states and their probabilities. -/
60100
abbrev Outcomes := List (State × Probability)

analysis/markov/Linleios/Util.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11

2+
/--
3+
The error function.
4+
-/
25
partial def erf (x : Float) : Float :=
36
if x < 0
47
then - erf (- x)
@@ -12,9 +15,15 @@ partial def erf (x : Float) : Float :=
1215
let t := 1 / (1 + p * x)
1316
1 - (a₁ * t + a₂ * t^2 + a₃ * t^3 + a₄ * t^4 + a₅ * t^5) * Float.exp (- x^2)
1417

18+
/--
19+
The CDF for a normal distribution.
20+
-/
1521
def cdfGaussian (x μ σ : Float) : Float :=
1622
(1 + erf ((x - μ) / σ / Float.sqrt 2)) / 2
1723

24+
/--
25+
A bisection search.
26+
-/
1827
def bisectionSearch (f : Float → Float) (low high : Float) (ε : Float) (maxIter : Nat) : Float :=
1928
match maxIter with
2029
| 0 => (low + high) / 2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.lake

analysis/markov/docbuild/ReadMe.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Building the documentation
2+
3+
See https://github.com/leanprover/doc-gen4/tree/v4.24.0 for detailed instructions.
4+
5+
1. In this folder, execute `MATHLIB_NO_CACHE_ON_UPDATE=1 lake update doc-gen4`.
6+
2. Also in this folder, execute `lake build Linleios:docs`.
7+
3. View the documentation at `./.lake/doc/index.html`.

0 commit comments

Comments
 (0)