-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRandom.lean
More file actions
183 lines (149 loc) · 7.57 KB
/
Copy pathRandom.lean
File metadata and controls
183 lines (149 loc) · 7.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import Weft.PMF
import Weft.Std.Arith
/-!
# Randomised functionalities
Programs request randomness through functionalities:
uniform shares, nonzero shares, public coins and preprocessing correlations.
Each request samples fresh coins in `PMF`.
`seqUniform_eq_uniform` relates sequential draws to joint uniform sampling.
Evaluation models fix the coins to chosen values.
They describe that fixed execution;
for reactive programs, other coin choices may change both outputs and costs.
-/
namespace Weft
/-! ## A fresh random share -/
namespace Rand
inductive Op where | rand
abbrev ops (F : Type) : Interface where
Op := Op
dom _ := []
cod _ := .share F
noncomputable def model (F : Type) [Fintype F] [Nonempty F] : Model (ops F) .ideal PMF :=
⟨fun _ => (uniform F).map fun x => (x, ())⟩
def eval (F : Type) [Inhabited F] : Model (ops F) .ideal Id := ⟨fun _ => pure ((default : F), ())⟩
end Rand
/-- Sample a uniform value and return it as a share. -/
abbrev Rand (F : Type) [Fintype F] [Inhabited F] : Functionality :=
⟨Rand.ops F, Rand.eval F, (· = Rand.model F), Functionality.unique_eq _⟩
@[simp, weft] theorem Rand.model_eq (F : Type) [Fintype F] [Inhabited F] :
(Rand F).model = Rand.model F := Functionality.model_eq rfl
/-! ## Nonzero random shares -/
instance {F : Type} [Zero F] [Nontrivial F] : Nonempty {x : F // x ≠ 0} :=
let ⟨x, hx⟩ := exists_ne (0 : F); ⟨⟨x, hx⟩⟩
namespace RandNZ
inductive Op where | randNZ
abbrev ops (F : Type) : Interface where
Op := Op
dom _ := []
cod _ := .share F
noncomputable def model (F : Type) [Zero F] [Nontrivial F] [Fintype F] [DecidableEq F] : Model (ops F) .ideal PMF :=
⟨fun _ => (uniform {x : F // x ≠ 0}).map fun x => (x.1, ())⟩
def eval (F : Type) [One F] : Model (ops F) .ideal Id := ⟨fun _ => pure ((1 : F), ())⟩
end RandNZ
/-- Sample uniformly from `F \ {0}` and return a share.
Over a field, this supplies an invertible mask. -/
abbrev RandNZ (F : Type) [Zero F] [One F] [Nontrivial F] [Fintype F] [DecidableEq F] : Functionality :=
⟨RandNZ.ops F, RandNZ.eval F, (· = RandNZ.model F), Functionality.unique_eq _⟩
@[simp, weft] theorem RandNZ.model_eq (F : Type) [Zero F] [One F] [Nontrivial F] [Fintype F] [DecidableEq F] :
(RandNZ F).model = RandNZ.model F := Functionality.model_eq rfl
/-! ## Public coins -/
namespace PubCoin
inductive Op where | coin
abbrev ops (F : Type) : Interface where
Op := Op
dom _ := []
cod _ := .clear F
noncomputable def model (F : Type) [Fintype F] [Nonempty F] : Model (ops F) .ideal PMF :=
⟨fun _ => (uniform F).map fun x => (x, ())⟩
def eval (F : Type) [Inhabited F] : Model (ops F) .ideal Id := ⟨fun _ => pure ((default : F), ())⟩
end PubCoin
/-- Sample a uniform clear value, recorded in the event. -/
abbrev PubCoin (F : Type) [Fintype F] [Inhabited F] : Functionality :=
⟨PubCoin.ops F, PubCoin.eval F, (· = PubCoin.model F), Functionality.unique_eq _⟩
@[simp, weft] theorem PubCoin.model_eq (F : Type) [Fintype F] [Inhabited F] :
(PubCoin F).model = PubCoin.model F := Functionality.model_eq rfl
/-! ## Correlated randomness -/
/-- A deterministic function of `k` jointly uniform coins. -/
structure Correlation (R T : Type) where
k : Nat
build : (Fin k → R) → T
/-- Apply the correlation function to a uniform draw from `Rᵏ`. -/
noncomputable def Correlation.sample {R T : Type} [Fintype R] [Nonempty R] (c : Correlation R T) : PMF T :=
(uniform (Fin c.k → R)).map c.build
/-! ### A multiplication (Beaver) triple `(a, b, a·b)` -/
namespace MulTriple
inductive Op where | get
abbrev ops (F : Type) : Interface where
Op := Op
dom _ := []
cod _ := .prod (.share F) (.prod (.share F) (.share F))
def corr (F : Type) [Mul F] : Correlation F (F × F × F) := ⟨2, fun x => (x 0, x 1, x 0 * x 1)⟩
noncomputable def model (F : Type) [Mul F] [Fintype F] [Nonempty F] : Model (ops F) .ideal PMF :=
⟨fun _ => (corr F).sample.map fun t => (t, ())⟩
def eval (F : Type) [Mul F] [Inhabited F] : Model (ops F) .ideal Id :=
⟨fun _ => pure (((default : F), (default : F), (default : F) * default), ())⟩
end MulTriple
/-- Sample `(a, b, a·b)` with independent uniform `a` and `b`. -/
abbrev MulTriple (F : Type) [Mul F] [Fintype F] [Inhabited F] : Functionality :=
⟨MulTriple.ops F, MulTriple.eval F, (· = MulTriple.model F), Functionality.unique_eq _⟩
@[simp, weft] theorem MulTriple.model_eq (F : Type) [Mul F] [Fintype F] [Inhabited F] :
(MulTriple F).model = MulTriple.model F := Functionality.model_eq rfl
/-! ### A square pair `(r, r²)` -/
namespace SquarePair
inductive Op where | get
abbrev ops (F : Type) : Interface where
Op := Op
dom _ := []
cod _ := .prod (.share F) (.share F)
def corr (F : Type) [Mul F] : Correlation F (F × F) := ⟨1, fun x => (x 0, x 0 * x 0)⟩
noncomputable def model (F : Type) [Mul F] [Fintype F] [Nonempty F] : Model (ops F) .ideal PMF :=
⟨fun _ => (corr F).sample.map fun t => (t, ())⟩
def eval (F : Type) [Mul F] [Inhabited F] : Model (ops F) .ideal Id :=
⟨fun _ => pure (((default : F), (default : F) * default), ())⟩
end SquarePair
/-- Sample `(r, r²)` with uniform `r`. -/
abbrev SquarePair (F : Type) [Mul F] [Fintype F] [Inhabited F] : Functionality :=
⟨SquarePair.ops F, SquarePair.eval F, (· = SquarePair.model F), Functionality.unique_eq _⟩
@[simp, weft] theorem SquarePair.model_eq (F : Type) [Mul F] [Fintype F] [Inhabited F] :
(SquarePair F).model = SquarePair.model F := Functionality.model_eq rfl
/-! ### Double sharings
Both components represent the same random value.
This interface does not distinguish sharing degrees. -/
namespace DoubleSharing
inductive Op where | get
abbrev ops (F : Type) : Interface where
Op := Op
dom _ := []
cod _ := .prod (.share F) (.share F)
def corr (F : Type) : Correlation F (F × F) := ⟨1, fun x => (x 0, x 0)⟩
noncomputable def model (F : Type) [Fintype F] [Nonempty F] : Model (ops F) .ideal PMF :=
⟨fun _ => (corr F).sample.map fun t => (t, ())⟩
def eval (F : Type) [Inhabited F] : Model (ops F) .ideal Id := ⟨fun _ => pure (((default : F), (default : F)), ())⟩
end DoubleSharing
/-- Return two shares of the same uniform value. -/
abbrev DoubleSharing (F : Type) [Fintype F] [Inhabited F] : Functionality :=
⟨DoubleSharing.ops F, DoubleSharing.eval F, (· = DoubleSharing.model F), Functionality.unique_eq _⟩
@[simp, weft] theorem DoubleSharing.model_eq (F : Type) [Fintype F] [Inhabited F] :
(DoubleSharing F).model = DoubleSharing.model F := Functionality.model_eq rfl
/-! ## Program operations -/
section Ops
variable {F : Type} {fs : Hybrid} {D : Domain}
/-- Request a random share of the explicitly supplied type `F`. -/
def rand (F : Type) [Fintype F] [Inhabited F] [Has (Rand F) fs] : Prog fs.ops D (D.share F) :=
Prog.op (F := Rand F) ⟨.rand, ()⟩
def randNZ (F : Type) [Zero F] [One F] [Nontrivial F] [Fintype F] [DecidableEq F] [Has (RandNZ F) fs] :
Prog fs.ops D (D.share F) :=
Prog.op (F := RandNZ F) ⟨.randNZ, ()⟩
def coin (F : Type) [Fintype F] [Inhabited F] [Has (PubCoin F) fs] : Prog fs.ops D (D.clear F) :=
Prog.op (F := PubCoin F) ⟨.coin, ()⟩
def mulTriple (F : Type) [Mul F] [Fintype F] [Inhabited F] [Has (MulTriple F) fs] :
Prog fs.ops D (D.share F × D.share F × D.share F) :=
Prog.op (F := MulTriple F) ⟨.get, ()⟩
def squarePair (F : Type) [Mul F] [Fintype F] [Inhabited F] [Has (SquarePair F) fs] :
Prog fs.ops D (D.share F × D.share F) :=
Prog.op (F := SquarePair F) ⟨.get, ()⟩
def doubleSharing (F : Type) [Fintype F] [Inhabited F] [Has (DoubleSharing F) fs] :
Prog fs.ops D (D.share F × D.share F) :=
Prog.op (F := DoubleSharing F) ⟨.get, ()⟩
end Ops
end Weft