@bramas/simulant-lean 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,150 @@
1
+ import Simulant.Round
2
+
3
+ /-!
4
+ # Executions, tasks and non-vacuity (plan, Sections 3.9, 3.10 and 5.2)
5
+
6
+ Every execution permitted by the round is considered (no fairness on the
7
+ adversary's choices), except that a semi-synchronous round only admits
8
+ scheduler-fair executions: every agent that acts forever is activated
9
+ infinitely often.
10
+ -/
11
+
12
+ namespace Simulant
13
+
14
+ inductive Verdict where
15
+ | success | failure | inProgress
16
+ deriving DecidableEq, Repr
17
+
18
+ inductive Goal where
19
+ | eventually | eventuallyAlways | safety
20
+ deriving DecidableEq, Repr
21
+
22
+ variable {σ : Sig}
23
+
24
+ structure Execution (σ : Sig) where
25
+ config : Nat → Config σ
26
+ witness : Nat → Witness
27
+ active : Nat → List (Fin σ.k)
28
+
29
+ def Satisfies (goal : Goal) (verdict : Config σ → Verdict) (e : Execution σ) : Prop :=
30
+ match goal with
31
+ | .safety => ∀ n, verdict (e.config n) ≠ .failure
32
+ | .eventually => ∃ n, verdict (e.config n) = .success ∧ ∀ j, j ≤ n → verdict (e.config j) ≠ .failure
33
+ | .eventuallyAlways =>
34
+ (∀ n, verdict (e.config n) ≠ .failure) ∧ ∃ n, ∀ j, n ≤ j → verdict (e.config j) = .success
35
+
36
+ namespace Model
37
+
38
+ variable [FlagSet σ.F] (m : Model σ) (act0 : σ.A) (init : ND (Config σ))
39
+
40
+ /-- Starts in an initial configuration and follows the round. -/
41
+ def Valid (e : Execution σ) : Prop :=
42
+ ND.Can init (e.config 0) ∧
43
+ ∀ n, (e.witness n, (e.active n, e.config (n + 1))) ∈ m.roundA act0 (e.config n)
44
+
45
+ /-- Every agent that acts forever is activated infinitely often. -/
46
+ def Fair (e : Execution σ) : Prop :=
47
+ ∀ a : Fin σ.k, (∀ n, FlagSet.acts (e.config n).agents[a].flags ≠ .never) →
48
+ ∀ n, ∃ j, n ≤ j ∧ a ∈ e.active j
49
+
50
+ def Admissible (e : Execution σ) : Prop :=
51
+ m.Valid act0 init e ∧ (m.round = .ssync → Fair e)
52
+
53
+ /-- The correctness statement: every admissible execution satisfies the goal. -/
54
+ def Correct (verdict : Config σ → Verdict) (goal : Goal) : Prop :=
55
+ ∀ e, m.Admissible act0 init e → Satisfies goal verdict e
56
+
57
+ inductive Reachable : Config σ → Prop where
58
+ | init {C} : ND.Can init C → Reachable C
59
+ | step {C C' w a} : Reachable C → (w, (a, C')) ∈ m.roundA act0 C → Reachable C'
60
+
61
+ /-! Non-vacuity: the model is not empty, so a correctness theorem is not vacuous. -/
62
+
63
+ omit [FlagSet σ.F] in
64
+ /-- (The model is an argument only so that `m.HasInitial init` reads like the other statements.) -/
65
+ def HasInitial (_m : Model σ) (init : ND (Config σ)) : Prop := ∃ C, ND.Can init C
66
+
67
+ def Total : Prop := ∀ C, Reachable m act0 init C → ∃ w a C', (w, (a, C')) ∈ m.roundA act0 C
68
+
69
+ def HasExecution : Prop := ∃ e, m.Admissible act0 init e
70
+
71
+ end Model
72
+
73
+ /-! ## Lassos
74
+
75
+ A finite lasso found by the explorer, checked by evaluation, gives an
76
+ admissible execution (for a synchronous round). -/
77
+
78
+ structure Lasso (σ : Sig) where
79
+ start : Config σ
80
+ /-- Each step: witness, activated agents, next configuration. -/
81
+ steps : List (Witness × List (Fin σ.k) × Config σ)
82
+ /-- The last configuration equals the configuration at this position (0 is `start`). -/
83
+ loop : Nat
84
+
85
+ namespace Lasso
86
+
87
+ def configs (l : Lasso σ) : List (Config σ) := l.start :: l.steps.map (·.2.2)
88
+
89
+ /-- The position in the lasso after `n` steps. -/
90
+ def pos (l : Lasso σ) : Nat → Nat
91
+ | 0 => 0
92
+ | n + 1 => if l.pos n + 1 = l.steps.length then l.loop else l.pos n + 1
93
+
94
+ theorem pos_lt (l : Lasso σ) (h : l.loop < l.steps.length) : ∀ n, l.pos n < l.steps.length := by
95
+ intro n
96
+ induction n with
97
+ | zero => simp [pos]; omega
98
+ | succ n ih => simp only [pos]; split <;> omega
99
+
100
+ theorem length_configs (l : Lasso σ) : l.configs.length = l.steps.length + 1 := by
101
+ simp [configs]
102
+
103
+ def toExecution (l : Lasso σ) (h : l.loop < l.steps.length) : Execution σ where
104
+ config n := l.configs[l.pos n]'(by have := l.pos_lt h n; rw [length_configs]; omega)
105
+ witness n := (l.steps[l.pos n]'(l.pos_lt h n)).1
106
+ active n := (l.steps[l.pos n]'(l.pos_lt h n)).2.1
107
+
108
+ variable [FlagSet σ.F]
109
+
110
+ /-- Every step of the lasso is a step of the round, and it closes on itself. -/
111
+ def Valid (m : Model σ) (act0 : σ.A) (l : Lasso σ) : Prop :=
112
+ l.loop < l.steps.length ∧
113
+ (∀ i (h : i < l.steps.length),
114
+ l.steps[i] ∈ m.roundA act0 (l.configs[i]'(by rw [length_configs]; omega))) ∧
115
+ l.configs[l.steps.length]? = l.configs[l.loop]?
116
+
117
+ omit [FlagSet σ.F] in
118
+ theorem config_succ (l : Lasso σ) (h : l.loop < l.steps.length)
119
+ (hclose : l.configs[l.steps.length]? = l.configs[l.loop]?) (n : Nat) :
120
+ (l.toExecution h).config (n + 1) =
121
+ (l.steps[l.pos n]'(l.pos_lt h n)).2.2 := by
122
+ have hp := l.pos_lt h n
123
+ simp only [toExecution, pos]
124
+ split
125
+ · rename_i heq
126
+ have h1 : l.configs[l.pos n + 1]? = some (l.steps[l.pos n]'hp).2.2 := by
127
+ simp [configs, hp]
128
+ rw [heq] at h1
129
+ rw [hclose] at h1
130
+ exact Option.some.inj ((List.getElem?_eq_getElem _).symm.trans h1)
131
+ · simp [configs]
132
+
133
+ theorem toExecution_valid (m : Model σ) (act0 : σ.A) (init : ND (Config σ)) (l : Lasso σ)
134
+ (hv : l.Valid m act0) (hinit : ND.Can init l.start) :
135
+ m.Valid act0 init (l.toExecution hv.1) := by
136
+ obtain ⟨hlt, hsteps, hclose⟩ := hv
137
+ refine ⟨by simpa [toExecution, pos, configs] using hinit, fun n => ?_⟩
138
+ have hp := l.pos_lt hlt n
139
+ rw [config_succ l hlt hclose n]
140
+ have := hsteps (l.pos n) hp
141
+ simpa [toExecution] using this
142
+
143
+ /-- For a synchronous round, a valid lasso is an admissible execution. -/
144
+ theorem hasExecution (m : Model σ) (act0 : σ.A) (init : ND (Config σ)) (l : Lasso σ)
145
+ (hround : m.round = .fsync) (hv : l.Valid m act0) (hinit : ND.Can init l.start) :
146
+ m.HasExecution act0 init :=
147
+ ⟨l.toExecution hv.1, toExecution_valid m act0 init l hv hinit, fun h => by rw [hround] at h; cases h⟩
148
+
149
+ end Lasso
150
+ end Simulant
@@ -0,0 +1,89 @@
1
+ import Simulant.NonVacuity
2
+
3
+ /-!
4
+ # Invariants of public states
5
+
6
+ The public state of an agent changes only through the algorithm's step:
7
+ components never write it, and agents that do not decide keep it. So a
8
+ property of public states that the step preserves holds of every agent in
9
+ every reachable configuration, whatever the components.
10
+ -/
11
+
12
+ namespace Simulant
13
+
14
+ variable {σ : Sig} [FlagSet σ.F]
15
+
16
+ omit [FlagSet σ.F] in
17
+ theorem Decision.idle_pub (a : Agent σ) (act : σ.A) : (Decision.idle a act).pub = a.pub := rfl
18
+
19
+ theorem Config.apply_pub (C : Config σ) (e : Effect σ) (i : Fin σ.k) : (C.apply e).agents[i].pub = C.agents[i].pub := by
20
+ rw [Config.apply_agent]
21
+
22
+ theorem moveAll_pub (ts : TState) (C : Config σ) (ds : Fin σ.k → Decision σ) (i : Fin σ.k) :
23
+ (moveAll ts C ds).agents[i].pub =
24
+ if ((ds i).decided && FlagSet.acts C.agents[i].flags != .never) = true then (ds i).pub else C.agents[i].pub := by
25
+ simp only [moveAll, Fin.getElem_fin, Vector.getElem_ofFn]
26
+ split <;> rfl
27
+
28
+ namespace Model
29
+
30
+ variable (m : Model σ) (act0 : σ.A) (P : σ.P → Prop)
31
+
32
+ theorem options_pub (ts : TState) (C : Config σ) (i : Fin σ.k)
33
+ (hstep : ∀ mem pub v, P pub → P (m.step mem pub v).pub) (hC : P C.agents[i].pub)
34
+ {d : Decision σ} (hd : ND.Can (m.options act0 ts C i) d) : P d.pub := by
35
+ unfold Model.options at hd
36
+ dsimp only at hd
37
+ split at hd
38
+ · obtain ⟨_, -, rfl⟩ := ND.can_map.1 hd
39
+ exact hC
40
+ · obtain ⟨f, -, hd⟩ := ND.can_bind.1 hd
41
+ obtain ⟨v, -, hd⟩ := ND.can_bind.1 hd
42
+ rw [ND.can_pure.1 hd]
43
+ exact hstep _ _ _ hC
44
+
45
+ theorem decideAll_pub (ts : TState) (C : Config σ)
46
+ (hstep : ∀ mem pub v, P pub → P (m.step mem pub v).pub) (hC : ∀ i : Fin σ.k, P C.agents[i].pub) :
47
+ ∀ (active : List (Fin σ.k)) (init : Fin σ.k → Decision σ), (∀ j, P (init j).pub) →
48
+ ∀ ds, ND.Can (active.foldlM (fun ds i => do
49
+ let d ← m.options act0 ts C i
50
+ pure fun j => if j = i then d else ds j) init) ds → ∀ j, P (ds j).pub
51
+ | [], init, hinit, ds, hds => by
52
+ rw [List.foldlM_nil, ND.can_pure] at hds
53
+ subst hds
54
+ exact hinit
55
+ | i :: rest, init, hinit, ds, hds => by
56
+ rw [List.foldlM_cons] at hds
57
+ obtain ⟨acc, hacc, hds⟩ := ND.can_bind.1 hds
58
+ obtain ⟨d, hd, rfl⟩ := ND.can_map.1 hacc
59
+ refine decideAll_pub ts C hstep hC rest _ ?_ ds hds
60
+ intro j
61
+ by_cases h : j = i
62
+ · simp only [h, ite_true]; exact m.options_pub act0 P ts C i hstep (hC i) hd
63
+ · simp only [h, ite_false]; exact hinit j
64
+
65
+ /-- A property of public states preserved by the step holds of every agent after a round. -/
66
+ theorem step_pub {C C' : Config σ} {w : Witness} (hstep : ∀ mem pub v, P pub → P (m.step mem pub v).pub)
67
+ (h : m.Step act0 C w C') (hC : ∀ i : Fin σ.k, P C.agents[i].pub) : ∀ i : Fin σ.k, P C'.agents[i].pub := by
68
+ obtain ⟨_, h⟩ := h
69
+ simp only [Model.roundA, ND.mem_bind, ND.mem_pure] at h
70
+ obtain ⟨_, ts, _, -, ⟨_, e1, _, -, ⟨_, act, _, -, ⟨_, ds, _, hd, ⟨_, e2, _, -, ⟨_, e3, _, -, ⟨-, heq⟩, -⟩, -⟩, -⟩, -⟩, -⟩, -⟩ := h
71
+ obtain ⟨-, rfl⟩ := Prod.mk.inj heq
72
+ have h1 : ∀ i : Fin σ.k, P (C.apply e1).agents[i].pub := by intro i; rw [Config.apply_pub]; exact hC i
73
+ have hds := m.decideAll_pub act0 P ts (C.apply e1) hstep h1 act _ (fun j => by rw [Decision.idle_pub]; exact h1 j) ds ⟨_, hd⟩
74
+ intro i
75
+ rw [Config.apply_pub, moveAll_pub, Config.apply_pub]
76
+ split
77
+ · exact hds i
78
+ · exact h1 i
79
+
80
+ /-- ... and so of every agent in every reachable configuration. -/
81
+ theorem reachable_pub (init : ND (Config σ)) (hstep : ∀ mem pub v, P pub → P (m.step mem pub v).pub)
82
+ (hinit : ∀ C, ND.Can init C → ∀ i : Fin σ.k, P C.agents[i].pub) {C : Config σ}
83
+ (h : m.Reachable act0 init C) : ∀ i : Fin σ.k, P C.agents[i].pub := by
84
+ induction h with
85
+ | init hC => exact hinit _ hC
86
+ | step _ hs ih => exact m.step_pub act0 P hstep ⟨_, hs⟩ ih
87
+
88
+ end Model
89
+ end Simulant
@@ -0,0 +1,146 @@
1
+ import Simulant.Exec
2
+
3
+ /-!
4
+ # Library lemmas about the round, for any components (plan, Section 4)
5
+ -/
6
+
7
+ namespace Simulant
8
+
9
+ variable {σ : Sig} [FlagSet σ.F]
10
+
11
+ theorem mem_chooseIfMany {site : String} {l : List α} {w : Witness} {x : α}
12
+ (h : (w, x) ∈ chooseIfMany site l) : x ∈ l := by
13
+ unfold chooseIfMany at h
14
+ split at h
15
+ · simp only [ND.mem_pure] at h; rw [h.2]; exact List.mem_singleton_self _
16
+ · exact ND.can_choose.1 ⟨w, h⟩
17
+
18
+ @[simp] theorem Config.apply_world (C : Config σ) (e : Effect σ) : (C.apply e).world = e.world C.world := rfl
19
+
20
+ @[simp] theorem Config.apply_agent (C : Config σ) (e : Effect σ) (i : Fin σ.k) :
21
+ (C.apply e).agents[i] = { C.agents[i] with flags := FlagSet.merge C.agents[i].flags (e.raise i) } := by
22
+ simp [Config.apply]
23
+
24
+ theorem moveAll_never (ts : TState) (C : Config σ) (ds : Fin σ.k → Decision σ) (i : Fin σ.k)
25
+ (h : FlagSet.acts C.agents[i].flags = .never) : (moveAll ts C ds).agents[i] = C.agents[i] := by
26
+ simp only [Fin.getElem_fin] at h
27
+ simp [moveAll, h]
28
+
29
+ @[simp] theorem moveAll_world (ts : TState) (C : Config σ) (ds : Fin σ.k → Decision σ) :
30
+ (moveAll ts C ds).world = C.world := rfl
31
+
32
+ variable [LawfulFlagSet σ.F]
33
+
34
+ theorem apply_never (C : Config σ) (e : Effect σ) (i : Fin σ.k)
35
+ (h : FlagSet.acts C.agents[i].flags = .never) : FlagSet.acts (C.apply e).agents[i].flags = .never := by
36
+ rw [Config.apply_agent]
37
+ exact LawfulFlagSet.acts_merge_never _ _ h
38
+
39
+ /-- An agent that never acts (crashed, dead) neither moves nor acts again, whatever the components. -/
40
+ theorem never_stays (m : Model σ) (act0 : σ.A) {C C' : Config σ} {w : Witness} (h : m.Step act0 C w C')
41
+ (i : Fin σ.k) (hn : FlagSet.acts C.agents[i].flags = .never) :
42
+ C'.agents[i].pos = C.agents[i].pos ∧ FlagSet.acts C'.agents[i].flags = .never := by
43
+ obtain ⟨_, h⟩ := h
44
+ simp only [Model.roundA, ND.mem_bind, ND.mem_pure] at h
45
+ obtain ⟨_, ts, _, -, ⟨_, e1, _, -, ⟨_, _, _, -, ⟨_, ds, _, -, ⟨_, e2, _, -, ⟨_, e3, _, -, ⟨-, heq⟩, -⟩, -⟩, -⟩, -⟩, -⟩, -⟩ := h
46
+ obtain ⟨-, rfl⟩ := Prod.mk.inj heq
47
+ have h1 := apply_never C e1 i hn
48
+ have h2 := apply_never _ e2 i h1
49
+ have hm := moveAll_never ts ((C.apply e1).apply e2) ds i h2
50
+ refine ⟨?_, ?_⟩
51
+ · simp only [Config.apply_agent] at hm ⊢
52
+ rw [hm]
53
+ · apply apply_never
54
+ rw [hm]
55
+ exact h2
56
+
57
+ end Simulant
58
+
59
+ /-! ## World parts that the round preserves
60
+
61
+ An observation `g` of the world (typically: a component's part) is
62
+ preserved by the round when every component preserves it. Components
63
+ built from `Hooks` preserve every part they do not own (`toComponent_preserves`). -/
64
+
65
+ namespace Simulant
66
+
67
+ variable {σ : Sig} [FlagSet σ.F] {T : Type}
68
+
69
+ /-- Every effect the component's hooks can produce preserves `g`. -/
70
+ def Component.Preserves (c : Component σ) (g : σ.W → T) : Prop :=
71
+ (∀ ts C e, ND.Can (c.beforeLook ts C) e → ∀ w, g (e.world w) = g w) ∧
72
+ (∀ ts C ds e, ND.Can (c.beforeMove ts C ds) e → ∀ w, g (e.world w) = g w) ∧
73
+ (∀ ts C e, ND.Can (c.afterMove ts C) e → ∀ w, g (e.world w) = g w)
74
+
75
+ omit [FlagSet σ.F] in
76
+ theorem Component.Preserves.comp {c : Component σ} {g : σ.W → T} (h : c.Preserves g) (f : T → U) :
77
+ c.Preserves (fun w => f (g w)) := by
78
+ obtain ⟨h1, h2, h3⟩ := h
79
+ exact ⟨fun ts C e he w => congrArg f (h1 ts C e he w), fun ts C ds e he w => congrArg f (h2 ts C ds e he w),
80
+ fun ts C e he w => congrArg f (h3 ts C e he w)⟩
81
+
82
+ theorem ND.can_map {m : ND α} {f : α → β} {b : β} :
83
+ ND.Can (do let a ← m; pure (f a)) b ↔ ∃ a, ND.Can m a ∧ b = f a := by
84
+ rw [ND.can_bind]
85
+ exact exists_congr fun _ => and_congr_right fun _ => ND.can_pure
86
+
87
+ theorem parallel_preserves {g : σ.W → T} (C : Config σ) :
88
+ ∀ (hooks : List (Config σ → ND (Effect σ))),
89
+ (∀ hk ∈ hooks, ∀ e, ND.Can (hk C) e → ∀ w, g (e.world w) = g w) →
90
+ ∀ e, ND.Can (parallel hooks C) e → ∀ w, g (e.world w) = g w
91
+ | [], _, e, he, w => by
92
+ simp only [parallel, ND.can_pure] at he
93
+ subst he
94
+ rfl
95
+ | hk :: hs, h, e, he, w => by
96
+ simp only [parallel, ND.can_bind, ND.can_pure] at he
97
+ obtain ⟨e1, h1, r, hr, rfl⟩ := he
98
+ have ih := parallel_preserves C hs (fun hk' hm => h hk' (List.mem_cons_of_mem _ hm)) r hr
99
+ show g (r.world (e1.world w)) = g w
100
+ rw [ih, h hk (List.mem_cons_self) e1 h1 w]
101
+
102
+ /-- If every component preserves `g`, so does the round. -/
103
+ theorem Model.step_preserves (m : Model σ) (act0 : σ.A) {g : σ.W → T}
104
+ (h : ∀ c ∈ m.components, c.Preserves g) {C C' : Config σ} {w : Witness}
105
+ (hs : m.Step act0 C w C') : g C'.world = g C.world := by
106
+ obtain ⟨_, hs⟩ := hs
107
+ simp only [Model.roundA, ND.mem_bind, ND.mem_pure] at hs
108
+ obtain ⟨_, ts, _, -, ⟨_, e1, _, h1, ⟨_, _, _, -, ⟨_, ds, _, -, ⟨_, e2, _, h2, ⟨_, e3, _, h3, ⟨-, heq⟩, -⟩, -⟩, -⟩, -⟩, -⟩, -⟩ := hs
109
+ obtain ⟨-, rfl⟩ := Prod.mk.inj heq
110
+ have p1 := parallel_preserves C _ (by
111
+ intro hk hm e he; simp only [List.mem_map] at hm; obtain ⟨c, hc, rfl⟩ := hm; exact (h c hc).1 ts C e he) e1 ⟨_, h1⟩
112
+ have p2 := parallel_preserves _ _ (by
113
+ intro hk hm e he; simp only [List.mem_map] at hm; obtain ⟨c, hc, rfl⟩ := hm; exact (h c hc).2.1 ts _ ds e he) e2 ⟨_, h2⟩
114
+ have p3 := parallel_preserves _ _ (by
115
+ intro hk hm e he; simp only [List.mem_map] at hm; obtain ⟨c, hc, rfl⟩ := hm; exact (h c hc).2.2 ts _ e he) e3 ⟨_, h3⟩
116
+ simp only [Config.apply_world, moveAll_world]
117
+ rw [p3, p2, p1]
118
+
119
+ omit [FlagSet σ.F] in
120
+ /-- A component preserves every part of the world that its own lens does not touch. -/
121
+ theorem Hooks.toComponent_preserves (h : Hooks σ Wc) (L : Lens σ.W Wc) (g : σ.W → T)
122
+ (hg : ∀ w x, g (L.set w x) = g w) : (h.toComponent L).Preserves g := by
123
+ refine ⟨fun ts C e he w => ?_, fun ts C ds e he w => ?_, fun ts C e he w => ?_⟩ <;>
124
+ · obtain ⟨e, -, rfl⟩ := ND.can_map.1 he
125
+ exact hg _ _
126
+
127
+ omit [FlagSet σ.F] in
128
+ /-- A component preserves an observation of its own part that each of its own effects preserves. -/
129
+ theorem Hooks.toComponent_preserves_own (h : Hooks σ Wc) (L : Lens σ.W Wc) [LawfulLens L] (g : Wc → T)
130
+ (hown : (∀ ts C e, ND.Can (h.beforeLook ts C) e → ∀ x, g (e.world x) = g x) ∧
131
+ (∀ ts C ds e, ND.Can (h.beforeMove ts C ds) e → ∀ x, g (e.world x) = g x) ∧
132
+ (∀ ts C e, ND.Can (h.afterMove ts C) e → ∀ x, g (e.world x) = g x)) :
133
+ (h.toComponent L).Preserves (fun w => g (L.get w)) := by
134
+ obtain ⟨h1, h2, h3⟩ := hown
135
+ refine ⟨fun ts C e he w => ?_, fun ts C ds e he w => ?_, fun ts C e he w => ?_⟩
136
+ · obtain ⟨e', he', rfl⟩ := ND.can_map.1 he
137
+ simp only [OwnEffect.lift, LawfulLens.get_set]
138
+ exact h1 ts C e' he' _
139
+ · obtain ⟨e', he', rfl⟩ := ND.can_map.1 he
140
+ simp only [OwnEffect.lift, LawfulLens.get_set]
141
+ exact h2 ts C ds e' he' _
142
+ · obtain ⟨e', he', rfl⟩ := ND.can_map.1 he
143
+ simp only [OwnEffect.lift, LawfulLens.get_set]
144
+ exact h3 ts C e' he' _
145
+
146
+ end Simulant
@@ -0,0 +1,54 @@
1
+ import Simulant
2
+
3
+ /-! Generated from the IR of component `BlackHole` by packages/lean-gen. Do not edit. -/
4
+
5
+ set_option linter.unusedVariables false
6
+
7
+ namespace Simulant.Library.BlackHole
8
+ open Simulant
9
+
10
+ inductive HolePolicy where
11
+ | none
12
+ | initiallyPresent
13
+ | mayEmerge
14
+ deriving DecidableEq, Repr, Inhabited
15
+
16
+ structure World (N : Nat) where
17
+ site : Fin N
18
+ active : Bool
19
+ deriving DecidableEq, Repr
20
+
21
+ /-- The flags declared by `BlackHole`, with the laws of a composition's flags. -/
22
+ class Flags (F : Type) [FlagSet F] where
23
+ dead : F → Bool
24
+ raise_dead : F
25
+ dead_raise : dead raise_dead = true
26
+ dead_merge : ∀ a b : F, dead (FlagSet.merge a b) = (dead a || dead b)
27
+ dead_none : dead (FlagSet.none : F) = false
28
+
29
+ class Actions (A : Type) where
30
+
31
+ /-- What the composition gives the component: lenses on the state it owns. -/
32
+ structure Ctx (σ : Sig) where
33
+ world : Lens σ.W (World σ.N)
34
+
35
+ def initWorld {N : Nat} [NeZero N] (policy : HolePolicy) (site : Fin N) : ND (World N) := do
36
+ let site ← (pure site)
37
+ let active ← (pure (policy == HolePolicy.initiallyPresent))
38
+ pure { site := site, active := active }
39
+
40
+ section
41
+ variable {σ : Sig} [FlagSet σ.F] [Flags σ.F] [Actions σ.A]
42
+
43
+ /-- The hooks, on the part of the world the component owns. -/
44
+ def hooks (policy : HolePolicy) (L : Ctx σ) : Hooks σ (World σ.N) where
45
+ beforeLook := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
46
+ beforeMove := fun ts C ds => pure ⟨id, fun _ => FlagSet.none⟩
47
+ afterMove := fun ts C => (do let active ← (if ((policy == HolePolicy.mayEmerge) && (!((L.world.get C.world).active))) then (ND.choose "BlackHole.active" ([false, true] : List (Bool))) else (pure ((L.world.get C.world).active))); (pure ({ world := fun x => { x with active := active }, raise := fun a => (if (fun (a : Fin σ.k) => ((FlagSet.present C.agents[a].flags) && active && ((C.agents[a].pos) == ((L.world.get C.world).site)))) a then (Flags.raise_dead : σ.F) else FlagSet.none) } : OwnEffect σ (World σ.N))))
48
+
49
+ def component (policy : HolePolicy) (L : Ctx σ) : Component σ :=
50
+ (hooks policy L).toComponent L.world
51
+
52
+ end
53
+
54
+ end Simulant.Library.BlackHole
@@ -0,0 +1,46 @@
1
+ import Simulant
2
+
3
+ /-! Generated from the IR of component `CrashAtNode` by packages/lean-gen. Do not edit. -/
4
+
5
+ set_option linter.unusedVariables false
6
+
7
+ namespace Simulant.Library.CrashAtNode
8
+ open Simulant
9
+
10
+ structure World (N : Nat) where
11
+ crashNode : Fin N
12
+ deriving DecidableEq, Repr
13
+
14
+ /-- The flags declared by `CrashAtNode`, with the laws of a composition's flags. -/
15
+ class Flags (F : Type) [FlagSet F] where
16
+ crashed : F → Bool
17
+ raise_crashed : F
18
+ crashed_raise : crashed raise_crashed = true
19
+ crashed_merge : ∀ a b : F, crashed (FlagSet.merge a b) = (crashed a || crashed b)
20
+ crashed_none : crashed (FlagSet.none : F) = false
21
+
22
+ class Actions (A : Type) where
23
+
24
+ /-- What the composition gives the component: lenses on the state it owns. -/
25
+ structure Ctx (σ : Sig) where
26
+ world : Lens σ.W (World σ.N)
27
+
28
+ def initWorld {N : Nat} [NeZero N] (crashNode : Fin N) : ND (World N) := do
29
+ let crashNode ← (pure crashNode)
30
+ pure { crashNode := crashNode }
31
+
32
+ section
33
+ variable {σ : Sig} [FlagSet σ.F] [Flags σ.F] [Actions σ.A]
34
+
35
+ /-- The hooks, on the part of the world the component owns. -/
36
+ def hooks (L : Ctx σ) : Hooks σ (World σ.N) where
37
+ beforeLook := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
38
+ beforeMove := fun ts C ds => (do let S ← (ND.choose "CrashAtNode.S" (B.subsets ((List.finRange σ.k).filter (fun (a : Fin σ.k) => ((FlagSet.correct C.agents[a].flags) && ((C.agents[a].pos) == ((L.world.get C.world).crashNode))))))); (pure ({ world := id, raise := fun a => (if (S).contains a then (Flags.raise_crashed : σ.F) else FlagSet.none) } : OwnEffect σ (World σ.N))))
39
+ afterMove := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
40
+
41
+ def component (L : Ctx σ) : Component σ :=
42
+ (hooks L).toComponent L.world
43
+
44
+ end
45
+
46
+ end Simulant.Library.CrashAtNode
@@ -0,0 +1,38 @@
1
+ import Simulant
2
+
3
+ /-! Generated from the IR of component `CrashStop` by packages/lean-gen. Do not edit. -/
4
+
5
+ set_option linter.unusedVariables false
6
+
7
+ namespace Simulant.Library.CrashStop
8
+ open Simulant
9
+
10
+ /-- The flags declared by `CrashStop`, with the laws of a composition's flags. -/
11
+ class Flags (F : Type) [FlagSet F] where
12
+ crashed : F → Bool
13
+ raise_crashed : F
14
+ crashed_raise : crashed raise_crashed = true
15
+ crashed_merge : ∀ a b : F, crashed (FlagSet.merge a b) = (crashed a || crashed b)
16
+ crashed_none : crashed (FlagSet.none : F) = false
17
+
18
+ class Actions (A : Type) where
19
+
20
+ /-- What the composition gives the component: lenses on the state it owns. -/
21
+ structure Ctx (σ : Sig) where
22
+
23
+
24
+ section
25
+ variable {σ : Sig} [FlagSet σ.F] [Flags σ.F] [Actions σ.A]
26
+
27
+ /-- The hooks, on the part of the world the component owns. -/
28
+ def hooks (f : Nat) (L : Ctx σ) : Hooks σ Unit where
29
+ beforeLook := fun ts C => (do let S ← (ND.chooseSuch "CrashStop.S" (B.subsets ((List.finRange σ.k).filter (fun (x0 : Fin σ.k) => (FlagSet.correct C.agents[x0].flags)))) (fun (S : List (Fin σ.k)) => (decide ((((List.finRange σ.k).countP (fun (x1 : Fin σ.k) => (Flags.crashed C.agents[x1].flags))) + S.length) ≤ f)))); (pure ({ world := id, raise := fun a => (if (S).contains a then (Flags.raise_crashed : σ.F) else FlagSet.none) } : OwnEffect σ Unit)))
30
+ beforeMove := fun ts C ds => pure ⟨id, fun _ => FlagSet.none⟩
31
+ afterMove := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
32
+
33
+ def component (f : Nat) (L : Ctx σ) : Component σ :=
34
+ (hooks f L).toComponent (Lens.unit σ.W)
35
+
36
+ end
37
+
38
+ end Simulant.Library.CrashStop
@@ -0,0 +1,51 @@
1
+ import Simulant
2
+
3
+ /-! Generated from the IR of component `Pebbles` by packages/lean-gen. Do not edit. -/
4
+
5
+ set_option linter.unusedVariables false
6
+
7
+ namespace Simulant.Library.Pebbles
8
+ open Simulant
9
+
10
+ inductive PebbleAction where
11
+ | none
12
+ | drop
13
+ | pick
14
+ deriving DecidableEq, Repr, Inhabited
15
+
16
+ structure World (N : Nat) where
17
+ pebbles : List (Fin N)
18
+ deriving DecidableEq, Repr
19
+
20
+ /-- The flags declared by `Pebbles`, with the laws of a composition's flags. -/
21
+ class Flags (F : Type) [FlagSet F] where
22
+
23
+ class Actions (A : Type) where
24
+ pebble : A → PebbleAction
25
+
26
+ /-- What the composition gives the component: lenses on the state it owns. -/
27
+ structure Ctx (σ : Sig) where
28
+ world : Lens σ.W (World σ.N)
29
+
30
+ def initWorld {N : Nat} [NeZero N] : ND (World N) := do
31
+ let pebbles ← (pure ([] : List (Fin N)))
32
+ pure { pebbles := pebbles }
33
+
34
+ section
35
+ variable {σ : Sig} [FlagSet σ.F] [Flags σ.F] [Actions σ.A]
36
+
37
+ def sensor_pebblesHere (L : Ctx σ) (ts : TState) (C : Config σ) (me : Fin σ.k) (frame : Bool) : ND (Nat) :=
38
+ (pure (((L.world.get C.world).pebbles).countP (fun (x0 : Fin σ.N) => (x0 == (C.agents[me].pos)))))
39
+
40
+ /-- The hooks, on the part of the world the component owns. -/
41
+ def hooks (L : Ctx σ) : Hooks σ (World σ.N) where
42
+ beforeLook := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
43
+ beforeMove := fun ts C ds => (pure (let picks := (((List.finRange σ.k).filter (fun (a : Fin σ.k) => (((ds a).decided) && ((Actions.pebble (ds a).act) == PebbleAction.pick)))).map (fun (x0 : Fin σ.k) => C.agents[x0].pos)); (let drops := (((List.finRange σ.k).filter (fun (a : Fin σ.k) => (((ds a).decided) && ((Actions.pebble (ds a).act) == PebbleAction.drop)))).map (fun (x0 : Fin σ.k) => C.agents[x0].pos)); ({ world := fun x => { x with pebbles := ((B.diff ((L.world.get C.world).pebbles) picks) ++ drops) }, raise := fun a => FlagSet.none } : OwnEffect σ (World σ.N)))))
44
+ afterMove := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
45
+
46
+ def component (L : Ctx σ) : Component σ :=
47
+ (hooks L).toComponent L.world
48
+
49
+ end
50
+
51
+ end Simulant.Library.Pebbles
@@ -0,0 +1,40 @@
1
+ import Simulant
2
+
3
+ /-! Generated from the IR of component `PersistentReflection` by packages/lean-gen. Do not edit. -/
4
+
5
+ set_option linter.unusedVariables false
6
+
7
+ namespace Simulant.Library.PersistentReflection
8
+ open Simulant
9
+
10
+ structure Fields (N : Nat) where
11
+ mirrored : Bool
12
+ deriving DecidableEq, Repr
13
+
14
+ /-- The flags declared by `PersistentReflection`, with the laws of a composition's flags. -/
15
+ class Flags (F : Type) [FlagSet F] where
16
+
17
+ class Actions (A : Type) where
18
+
19
+ /-- What the composition gives the component: lenses on the state it owns. -/
20
+ structure Ctx (σ : Sig) where
21
+ fields : Lens σ.X (Fields σ.N)
22
+
23
+ def init_mirrored {N : Nat} [NeZero N] (i : Nat) : ND (Bool) :=
24
+ (ND.choose "PersistentReflection.mirrored" ([false, true]))
25
+
26
+ section
27
+ variable {σ : Sig} [FlagSet σ.F] [Flags σ.F] [Actions σ.A]
28
+
29
+ /-- The hooks, on the part of the world the component owns. -/
30
+ def hooks (L : Ctx σ) : Hooks σ Unit where
31
+ beforeLook := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
32
+ beforeMove := fun ts C ds => pure ⟨id, fun _ => FlagSet.none⟩
33
+ afterMove := fun ts C => pure ⟨id, fun _ => FlagSet.none⟩
34
+
35
+ def component (L : Ctx σ) : Component σ :=
36
+ (hooks L).toComponent (Lens.unit σ.W)
37
+
38
+ end
39
+
40
+ end Simulant.Library.PersistentReflection
@@ -0,0 +1,41 @@
1
+ import Simulant
2
+
3
+ /-! Generated from the IR of component `Visited` by packages/lean-gen. Do not edit. -/
4
+
5
+ set_option linter.unusedVariables false
6
+
7
+ namespace Simulant.Library.Visited
8
+ open Simulant
9
+
10
+ structure World (N : Nat) where
11
+ visited : List (Fin N)
12
+ deriving DecidableEq, Repr
13
+
14
+ /-- The flags declared by `Visited`, with the laws of a composition's flags. -/
15
+ class Flags (F : Type) [FlagSet F] where
16
+
17
+ class Actions (A : Type) where
18
+
19
+ /-- What the composition gives the component: lenses on the state it owns. -/
20
+ structure Ctx (σ : Sig) where
21
+ world : Lens σ.W (World σ.N)
22
+
23
+ def initWorld {N : Nat} [NeZero N] : ND (World N) := do
24
+ let visited ← (pure ([] : List (Fin N)))
25
+ pure { visited := visited }
26
+
27
+ section
28
+ variable {σ : Sig} [FlagSet σ.F] [Flags σ.F] [Actions σ.A]
29
+
30
+ /-- The hooks, on the part of the world the component owns. -/
31
+ def hooks (L : Ctx σ) : Hooks σ (World σ.N) where
32
+ beforeLook := fun ts C => (pure ({ world := fun x => { x with visited := (((L.world.get C.world).visited) ++ (((List.finRange σ.k).filter (fun (x0 : Fin σ.k) => (FlagSet.present C.agents[x0].flags))).map (fun (x0 : Fin σ.k) => C.agents[x0].pos))).eraseDups }, raise := fun a => FlagSet.none } : OwnEffect σ (World σ.N)))
33
+ beforeMove := fun ts C ds => pure ⟨id, fun _ => FlagSet.none⟩
34
+ afterMove := fun ts C => (pure ({ world := fun x => { x with visited := (((L.world.get C.world).visited) ++ (((List.finRange σ.k).filter (fun (x0 : Fin σ.k) => (FlagSet.present C.agents[x0].flags))).map (fun (x0 : Fin σ.k) => C.agents[x0].pos))).eraseDups }, raise := fun a => FlagSet.none } : OwnEffect σ (World σ.N)))
35
+
36
+ def component (L : Ctx σ) : Component σ :=
37
+ (hooks L).toComponent L.world
38
+
39
+ end
40
+
41
+ end Simulant.Library.Visited
@@ -0,0 +1,6 @@
1
+ import Simulant.Library.BlackHole
2
+ import Simulant.Library.CrashStop
3
+ import Simulant.Library.CrashAtNode
4
+ import Simulant.Library.Pebbles
5
+ import Simulant.Library.PersistentReflection
6
+ import Simulant.Library.Visited