@@ -8,35 +8,48 @@ Number of stake pools.
88def nPools : Nat := 2500
99
1010/--
11- Compute a realistic stake distribution for the specified number of pools .
11+ Sortition results .
1212-/
13- def stakeDistribution (nPools : Nat) : List Float :=
14- (List.range nPools).map (fun k => ((k + 1 ).toFloat / nPools.toFloat)^10 - (k.toFloat / nPools.toFloat)^10 )
13+ structure Sortition where
14+ stake : Float
15+ probability : Float
16+ deriving Repr
1517
1618/--
17- Determine the distribution parameter that achieves the specified committee size .
19+ Fait Accompli sortition .
1820-/
19- private def calibrateCommittee (committeeSize : Float) : Float :=
20- let stakes : List Float := stakeDistribution nPools
21- let f (m : Float) : Float :=
22- let ps : List Float := stakes.map (fun s => 1 - Float.exp (- m * s))
23- ps.sum - committeeSize
24- bisectionSearch f committeeSize nPools.toFloat 0 .5 10
21+ def faSortition (nPools n : Nat) : List Sortition :=
22+ let S (i : Nat) := ((nPools - i + 1 ).toFloat / nPools.toFloat)^10 - ((nPools - i).toFloat / nPools.toFloat)^10
23+ let ρ (i : Nat) := 1 - ((nPools - i).toFloat / nPools.toFloat)^10
24+ let test (n i : Nat) : Bool := (1 - S i / ρ i)^2 < (n - i).toFloat / (n - i + 1 ).toFloat
25+ let i := (List.range nPools).map $ Add.add 1
26+ let ⟨ persistent , nonpersistent ⟩ := i.partition $ test n
27+ let ρStar := ρ $ persistent.length + 1
28+ let persistent' := persistent.map $ fun i ↦ {stake := S i, probability := 1 }
29+ let nonpersistent' :=
30+ nonpersistent.map $ fun i ↦
31+ let Si := S i
32+ {stake := Si, probability := Si / ρStar}
33+ persistent' ++ nonpersistent'
2534
2635/--
2736Compute the mean and standard deviation of the committee size, given the probability of a successful vote and a target committee size.
2837-/
29- private def committeeDistribution (pSuccessfulVote committeeSize : Float) : Float × Float :=
30- let stakes : List Float := stakeDistribution nPools
31- let m := calibrateCommittee committeeSize
32- let ps : List Float := stakes.map (fun s => pSuccessfulVote * (1 - Float.exp (- m * s)))
33- let μ := ps.sum
34- let σ := (ps.map (fun p => p * (1 - p))).sum.sqrt
38+ def voteDistribution (pSuccessfulVote : Float) (committeeSize : Nat) : Float × Float :=
39+ let sortition := faSortition nPools committeeSize
40+ let μ := (sortition.map $ fun s ↦ let p := s.probability * pSuccessfulVote; s.stake * p).sum
41+ let σ := (sortition.map $ fun s ↦ let p := s.probability * pSuccessfulVote; (s.stake * s.stake * p * (1 - p))).sum.sqrt
3542 ⟨ μ , σ ⟩
3643
3744/--
3845Compute the probability of a quorum, given the probability of a successful vote, the target committee size, and the quorum fraction.
3946-/
4047def pQuorum (pSuccessfulVote committeeSize τ : Float) : Float :=
41- let ⟨ μ , σ ⟩ := committeeDistribution pSuccessfulVote committeeSize
42- 1 - cdfGaussian (τ * committeeSize) μ σ
48+ let ⟨ μ , σ ⟩ := voteDistribution pSuccessfulVote committeeSize.toUInt64.toNat
49+ 1 - cdfGaussian τ μ σ
50+
51+ /--
52+ Compute a realistic stake distribution for the specified number of pools.
53+ -/
54+ def stakeDistribution (nPools : Nat) : List Float :=
55+ (faSortition nPools 700 ).map Sortition.stake
0 commit comments