1
+ /-
2
+ Copyright (c) 2018 Mario Carneiro. All rights reserved.
3
+ Released under Apache 2.0 license as described in the file LICENSE.
4
+ Author: Mario Carneiro
5
+
6
+ A computable model of hereditarily finite sets with atoms
7
+ (ZFA without infinity). This is useful for calculations in naive
8
+ set theory.
9
+ -/
10
+ import tactic.interactive data.list.basic
11
+
12
+ variables {α : Type *}
13
+
14
+ @[derive decidable_eq]
15
+ inductive {u } lists' (α : Type u) : bool → Type u
16
+ | atom : α → lists' ff
17
+ | nil {} : lists' tt
18
+ | cons' {b} : lists' b → lists' tt → lists' tt
19
+
20
+ def lists (α : Type *) := Σ b, lists' α b
21
+
22
+ namespace lists'
23
+
24
+ def cons : lists α → lists' α tt → lists' α tt
25
+ | ⟨b, a⟩ l := cons' a l
26
+
27
+ @[simp] def to_list : ∀ {b}, lists' α b → list (lists α)
28
+ | _ (atom a) := []
29
+ | _ nil := []
30
+ | _ (cons' a l) := ⟨_, a⟩ :: l.to_list
31
+
32
+ @[simp] theorem to_list_cons (a : lists α) (l) :
33
+ to_list (cons a l) = a :: l.to_list :=
34
+ by cases a; simp [cons]
35
+
36
+ @[simp] def of_list : list (lists α) → lists' α tt
37
+ | [] := nil
38
+ | (a :: l) := cons a (of_list l)
39
+
40
+ @[simp] theorem to_of_list (l : list (lists α)) : to_list (of_list l) = l :=
41
+ by induction l; simp *
42
+
43
+ @[simp] theorem of_to_list : ∀ (l : lists' α tt), of_list (to_list l) = l :=
44
+ suffices ∀ b (h : tt = b) (l : lists' α b),
45
+ let l' : lists' α tt := by rw h; exact l in
46
+ of_list (to_list l') = l', from this _ rfl,
47
+ λ b h l, begin
48
+ induction l, {cases h}, {exact rfl},
49
+ case lists'.cons' : b a l IH₁ IH₂ {
50
+ intro, change l' with cons' a l,
51
+ simpa [cons] using IH₂ rfl }
52
+ end
53
+
54
+ end lists'
55
+
56
+ mutual inductive lists.equiv , lists'.subset
57
+ with lists.equiv : lists α → lists α → Prop
58
+ | refl (l) : lists.equiv l l
59
+ | antisymm {l₁ l₂ : lists' α tt} :
60
+ lists'.subset l₁ l₂ → lists'.subset l₂ l₁ → lists.equiv ⟨_, l₁⟩ ⟨_, l₂⟩
61
+ with lists'.subset : lists' α tt → lists' α tt → Prop
62
+ | nil {l} : lists'.subset lists'.nil l
63
+ | cons {a a' l l'} : lists.equiv a a' → a' ∈ lists'.to_list l' →
64
+ lists'.subset l l' → lists'.subset (lists'.cons a l) l'
65
+ local infix ~ := equiv
66
+
67
+ namespace lists'
68
+
69
+ instance : has_subset (lists' α tt) := ⟨lists'.subset⟩
70
+
71
+ instance {b} : has_mem (lists α) (lists' α b) :=
72
+ ⟨λ a l, ∃ a' ∈ l.to_list, a ~ a'⟩
73
+
74
+ theorem mem_def {b a} {l : lists' α b} :
75
+ a ∈ l ↔ ∃ a' ∈ l.to_list, a ~ a' := iff.rfl
76
+
77
+ @[simp] theorem mem_cons {a y l} : a ∈ @cons α y l ↔ a ~ y ∨ a ∈ l :=
78
+ by simp [mem_def, or_and_distrib_right, exists_or_distrib]
79
+
80
+ theorem cons_subset {a} {l₁ l₂ : lists' α tt} :
81
+ lists'.cons a l₁ ⊆ l₂ ↔ a ∈ l₂ ∧ l₁ ⊆ l₂ :=
82
+ begin
83
+ refine ⟨λ h, _, λ ⟨⟨a', m, e⟩, s⟩, subset.cons e m s⟩,
84
+ generalize_hyp h' : lists'.cons a l₁ = l₁' at h,
85
+ cases h with l a' a'' l l' e m s, {cases a, cases h'},
86
+ cases a, cases a', cases h', exact ⟨⟨_, m, e⟩, s⟩
87
+ end
88
+
89
+ theorem of_list_subset {l₁ l₂ : list (lists α)} (h : l₁ ⊆ l₂) :
90
+ lists'.of_list l₁ ⊆ lists'.of_list l₂ :=
91
+ begin
92
+ induction l₁, {exact subset.nil},
93
+ refine subset.cons (equiv.refl _) _ (l₁_ih (list.subset_of_cons_subset h)),
94
+ simp at h, simp [h]
95
+ end
96
+
97
+ @[refl] theorem subset.refl {l : lists' α tt} : l ⊆ l :=
98
+ by rw ← lists'.of_to_list l; exact
99
+ of_list_subset (list.subset.refl _)
100
+
101
+ theorem subset_nil {l : lists' α tt} :
102
+ l ⊆ lists'.nil → l = lists'.nil :=
103
+ begin
104
+ rw ← of_to_list l,
105
+ induction to_list l; intro h, {refl},
106
+ rcases cons_subset.1 h with ⟨⟨_, ⟨⟩, _⟩, _⟩
107
+ end
108
+
109
+ theorem mem_of_subset' {a} {l₁ l₂ : lists' α tt}
110
+ (s : l₁ ⊆ l₂) (h : a ∈ l₁.to_list) : a ∈ l₂ :=
111
+ begin
112
+ induction s with _ a a' l l' e m s IH, {cases h},
113
+ simp at h, rcases h with rfl|h,
114
+ exacts [⟨_, m, e⟩, IH h]
115
+ end
116
+
117
+ theorem subset_def {l₁ l₂ : lists' α tt} :
118
+ l₁ ⊆ l₂ ↔ ∀ a ∈ l₁.to_list, a ∈ l₂ :=
119
+ ⟨λ H a, mem_of_subset' H, λ H, begin
120
+ rw ← of_to_list l₁,
121
+ revert H, induction to_list l₁; intro,
122
+ { exact subset.nil },
123
+ { simp at H, exact cons_subset.2 ⟨H.1 , ih H.2 ⟩ }
124
+ end ⟩
125
+
126
+ end lists'
127
+
128
+ namespace lists
129
+
130
+ @[pattern] def atom (a : α) : lists α := ⟨_, lists'.atom a⟩
131
+
132
+ @[pattern] def of' (l : lists' α tt) : lists α := ⟨_, l⟩
133
+
134
+ @[simp] def to_list : lists α → list (lists α)
135
+ | ⟨b, l⟩ := l.to_list
136
+
137
+ def is_list (l : lists α) : Prop := l.1
138
+
139
+ def of_list (l : list (lists α)) : lists α := of' (lists'.of_list l)
140
+
141
+ theorem is_list_to_list (l : list (lists α)) : is_list (of_list l) :=
142
+ eq.refl _
143
+
144
+ theorem to_of_list (l : list (lists α)) : to_list (of_list l) = l :=
145
+ by simp [of_list, of']
146
+
147
+ theorem of_to_list : ∀ {l : lists α}, is_list l → of_list (to_list l) = l
148
+ | ⟨tt, l⟩ _ := by simp [of_list, of']
149
+
150
+ instance [decidable_eq α] : decidable_eq (lists α) :=
151
+ by unfold lists; apply_instance
152
+
153
+ instance [has_sizeof α] : has_sizeof (lists α) :=
154
+ by unfold lists; apply_instance
155
+
156
+ def induction_mut (C : lists α → Sort *) (D : lists' α tt → Sort *)
157
+ (C0 : ∀ a, C (atom a)) (C1 : ∀ l, D l → C (of' l))
158
+ (D0 : D lists'.nil) (D1 : ∀ a l, C a → D l → D (lists'.cons a l)) :
159
+ pprod (∀ l, C l) (∀ l, D l) :=
160
+ begin
161
+ suffices : ∀ {b} (l : lists' α b),
162
+ pprod (C ⟨_, l⟩) (match b, l with
163
+ | tt, l := D l
164
+ | ff, l := punit
165
+ end ),
166
+ { exact ⟨λ ⟨b, l⟩, (this _).1 , λ l, (this l).2 ⟩ },
167
+ intros, induction l with a b a l IH₁ IH₂,
168
+ { exact ⟨C0 _, ⟨⟩⟩ },
169
+ { exact ⟨C1 _ D0, D0⟩ },
170
+ { suffices , {exact ⟨C1 _ this , this ⟩},
171
+ exact D1 ⟨_, _⟩ _ IH₁.1 IH₂.2 }
172
+ end
173
+
174
+ def mem (a : lists α) : lists α → Prop
175
+ | ⟨ff, l⟩ := false
176
+ | ⟨tt, l⟩ := a ∈ l
177
+
178
+ instance : has_mem (lists α) (lists α) := ⟨mem⟩
179
+
180
+ theorem is_list_of_mem {a : lists α} : ∀ {l : lists α}, a ∈ l → is_list l
181
+ | ⟨_, lists'.nil⟩ _ := rfl
182
+ | ⟨_, lists'.cons' _ _⟩ _ := rfl
183
+
184
+ theorem equiv.antisymm_iff {l₁ l₂ : lists' α tt} :
185
+ of' l₁ ~ of' l₂ ↔ l₁ ⊆ l₂ ∧ l₂ ⊆ l₁ :=
186
+ begin
187
+ refine ⟨λ h, _, λ ⟨h₁, h₂⟩, equiv.antisymm h₁ h₂⟩,
188
+ cases h with _ _ _ h₁ h₂,
189
+ { simp [lists'.subset.refl] }, { exact ⟨h₁, h₂⟩ }
190
+ end
191
+
192
+ attribute [refl] equiv.refl
193
+
194
+ theorem equiv_atom {a} {l : lists α} : atom a ~ l ↔ atom a = l :=
195
+ ⟨λ h, by cases h; refl, λ h, h ▸ equiv.refl _⟩
196
+
197
+ theorem equiv.symm {l₁ l₂ : lists α} (h : l₁ ~ l₂) : l₂ ~ l₁ :=
198
+ by cases h with _ _ _ h₁ h₂; [refl, exact equiv.antisymm h₂ h₁]
199
+
200
+ theorem equiv.trans : ∀ {l₁ l₂ l₃ : lists α}, l₁ ~ l₂ → l₂ ~ l₃ → l₁ ~ l₃ :=
201
+ begin
202
+ let trans := λ (l₁ : lists α), ∀ ⦃l₂ l₃⦄, l₁ ~ l₂ → l₂ ~ l₃ → l₁ ~ l₃,
203
+ suffices : pprod (∀ l₁, trans l₁)
204
+ (∀ (l : lists' α tt) (l' ∈ l.to_list), trans l'), {exact this.1 },
205
+ apply induction_mut,
206
+ { intros a l₂ l₃ h₁ h₂,
207
+ rwa ← equiv_atom.1 h₁ at h₂ },
208
+ { intros l₁ IH l₂ l₃ h₁ h₂,
209
+ cases h₁ with _ _ l₂, {exact h₂},
210
+ cases h₂ with _ _ l₃, {exact h₁},
211
+ cases equiv.antisymm_iff.1 h₁ with hl₁ hr₁,
212
+ cases equiv.antisymm_iff.1 h₂ with hl₂ hr₂,
213
+ apply equiv.antisymm_iff.2 ; split; apply lists'.subset_def.2 ,
214
+ { intros a₁ m₁,
215
+ rcases lists'.mem_of_subset' hl₁ m₁ with ⟨a₂, m₂, e₁₂⟩,
216
+ rcases lists'.mem_of_subset' hl₂ m₂ with ⟨a₃, m₃, e₂₃⟩,
217
+ exact ⟨a₃, m₃, IH _ m₁ e₁₂ e₂₃⟩ },
218
+ { intros a₃ m₃,
219
+ rcases lists'.mem_of_subset' hr₂ m₃ with ⟨a₂, m₂, e₃₂⟩,
220
+ rcases lists'.mem_of_subset' hr₁ m₂ with ⟨a₁, m₁, e₂₁⟩,
221
+ exact ⟨a₁, m₁, (IH _ m₁ e₂₁.symm e₃₂.symm).symm⟩ } },
222
+ { rintro _ ⟨⟩ },
223
+ { intros a l IH₁ IH₂, simpa [IH₁] using IH₂ }
224
+ end
225
+
226
+ instance : setoid (lists α) :=
227
+ ⟨(~), equiv.refl, @equiv.symm _, @equiv.trans _⟩
228
+
229
+ section decidable
230
+
231
+ @[simp] def equiv.decidable_meas :
232
+ (psum (Σ' (l₁ : lists α), lists α) $
233
+ psum (Σ' (l₁ : lists' α tt), lists' α tt)
234
+ Σ' (a : lists α), lists' α tt) → ℕ
235
+ | (psum.inl ⟨l₁, l₂⟩) := sizeof l₁ + sizeof l₂
236
+ | (psum.inr $ psum.inl ⟨l₁, l₂⟩) := sizeof l₁ + sizeof l₂
237
+ | (psum.inr $ psum.inr ⟨l₁, l₂⟩) := sizeof l₁ + sizeof l₂
238
+
239
+ local attribute [-simp] add_comm add_assoc
240
+ open well_founded_tactics
241
+
242
+ theorem sizeof_pos {b} (l : lists' α b) : 0 < sizeof l :=
243
+ by cases l; {unfold_sizeof, trivial_nat_lt}
244
+
245
+ theorem lt_sizeof_cons' {b} (a : lists' α b) (l) :
246
+ sizeof (⟨b, a⟩ : lists α) < sizeof (lists'.cons' a l) :=
247
+ by {unfold_sizeof, exact lt_add_of_pos_right _ (sizeof_pos _)}
248
+
249
+ @[instance] mutual def equiv.decidable , subset.decidable , mem.decidable [decidable_eq α]
250
+ with equiv.decidable : ∀ l₁ l₂ : lists α, decidable (l₁ ~ l₂)
251
+ | ⟨ff, l₁⟩ ⟨ff, l₂⟩ := decidable_of_iff' (l₁ = l₂) $
252
+ by cases l₁; refine equiv_atom.trans (by simp [atom])
253
+ | ⟨ff, l₁⟩ ⟨tt, l₂⟩ := is_false $ by rintro ⟨⟩
254
+ | ⟨tt, l₁⟩ ⟨ff, l₂⟩ := is_false $ by rintro ⟨⟩
255
+ | ⟨tt, l₁⟩ ⟨tt, l₂⟩ := begin
256
+ haveI :=
257
+ have sizeof l₁ + sizeof l₂ <
258
+ sizeof (⟨tt, l₁⟩ : lists α) + sizeof (⟨tt, l₂⟩ : lists α),
259
+ by default_dec_tac,
260
+ subset.decidable l₁ l₂,
261
+ haveI :=
262
+ have sizeof l₂ + sizeof l₁ <
263
+ sizeof (⟨tt, l₁⟩ : lists α) + sizeof (⟨tt, l₂⟩ : lists α),
264
+ by default_dec_tac,
265
+ subset.decidable l₂ l₁,
266
+ exact decidable_of_iff' _ equiv.antisymm_iff,
267
+ end
268
+ with subset.decidable : ∀ l₁ l₂ : lists' α tt, decidable (l₁ ⊆ l₂)
269
+ | lists'.nil l₂ := is_true subset.nil
270
+ | (@lists'.cons' _ b a l₁) l₂ := begin
271
+ haveI :=
272
+ have sizeof (⟨b, a⟩ : lists α) + sizeof l₂ <
273
+ sizeof (lists'.cons' a l₁) + sizeof l₂,
274
+ from add_lt_add_right (lt_sizeof_cons' _ _) _,
275
+ mem.decidable ⟨b, a⟩ l₂,
276
+ haveI :=
277
+ have sizeof l₁ + sizeof l₂ <
278
+ sizeof (lists'.cons' a l₁) + sizeof l₂,
279
+ by default_dec_tac,
280
+ subset.decidable l₁ l₂,
281
+ exact decidable_of_iff' _ (@lists'.cons_subset _ ⟨_, _⟩ _ _)
282
+ end
283
+ with mem.decidable : ∀ (a : lists α) (l : lists' α tt), decidable (a ∈ l)
284
+ | a lists'.nil := is_false $ by rintro ⟨_, ⟨⟩, _⟩
285
+ | a (lists'.cons' b l₂) := begin
286
+ haveI :=
287
+ have sizeof a + sizeof (⟨_, b⟩ : lists α) <
288
+ sizeof a + sizeof (lists'.cons' b l₂),
289
+ from add_lt_add_left (lt_sizeof_cons' _ _) _,
290
+ equiv.decidable a ⟨_, b⟩,
291
+ haveI :=
292
+ have sizeof a + sizeof l₂ <
293
+ sizeof a + sizeof (lists'.cons' b l₂),
294
+ by default_dec_tac,
295
+ mem.decidable a l₂,
296
+ refine decidable_of_iff' (a ~ ⟨_, b⟩ ∨ a ∈ l₂) _,
297
+ rw ← lists'.mem_cons, refl
298
+ end
299
+ using_well_founded {
300
+ rel_tac := λ _ _, `[exact ⟨_, measure_wf equiv.decidable_meas⟩],
301
+ dec_tac := `[assumption] }
302
+
303
+ end decidable
304
+
305
+ end lists
306
+
307
+ namespace lists'
308
+
309
+ theorem mem_equiv_left {l : lists' α tt} :
310
+ ∀ {a a'}, a ~ a' → (a ∈ l ↔ a' ∈ l) :=
311
+ suffices ∀ {a a'}, a ~ a' → a ∈ l → a' ∈ l,
312
+ from λ a a' e, ⟨this e, this e.symm⟩,
313
+ λ a₁ a₂ e₁ ⟨a₃, m₃, e₂⟩, ⟨_, m₃, e₁.symm.trans e₂⟩
314
+
315
+ theorem mem_of_subset {a} {l₁ l₂ : lists' α tt}
316
+ (s : l₁ ⊆ l₂) : a ∈ l₁ → a ∈ l₂ | ⟨a', m, e⟩ :=
317
+ (mem_equiv_left e).2 (mem_of_subset' s m)
318
+
319
+ theorem subset.trans {l₁ l₂ l₃ : lists' α tt}
320
+ (h₁ : l₁ ⊆ l₂) (h₂ : l₂ ⊆ l₃) : l₁ ⊆ l₃ :=
321
+ subset_def.2 $ λ a₁ m₁, mem_of_subset h₂ $ mem_of_subset' h₁ m₁
322
+
323
+ end lists'
324
+
325
+ def finsets (α : Type *) := quotient (@lists.setoid α)
326
+
327
+ namespace finsets
328
+
329
+ instance : has_emptyc (finsets α) := ⟨⟦lists.of' lists'.nil⟧⟩
330
+
331
+ instance [decidable_eq α] : decidable_eq (finsets α) :=
332
+ by unfold finsets; apply_instance
333
+
334
+ end finsets
0 commit comments