Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 2445c98

Browse files
committed
fix(data/finsupp/basic): add missing decidable arguments in lemma statements (#18241)
The resulting lemmas are more general than they were before. In order to ensure that this doesn't regress again, `open_locale classical` is now also removed from these files. Instead, we use the approach of: * Using the `classical` tactic in proofs * Using `by haveI := _; exact` in definitions, as `by classical; exact` leaks classicality up to the end of the next section. In a few places this means that `variables` lines have to be repeated on `def`s as Lean doesn't look inside tactic blocks to work out which variables are used. I also switched some anonymous constructors for named constructors in order to make the proof / data distinction a little easier to see.
1 parent 68cc421 commit 2445c98

File tree

3 files changed

+169
-94
lines changed

3 files changed

+169
-94
lines changed

src/data/finsupp/basic.lean

Lines changed: 90 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ This file is a `noncomputable theory` and uses classical logic throughout.
4545
noncomputable theory
4646

4747
open finset function
48-
open_locale classical big_operators
48+
open_locale big_operators
4949

5050
variables {α β γ ι M M' N P G H R S : Type*}
5151

@@ -84,12 +84,16 @@ lemma apply_eq_of_mem_graph {a : α} {m : M} {f : α →₀ M} (h : (a, m) ∈ f
8484
@[simp] lemma not_mem_graph_snd_zero (a : α) (f : α →₀ M) : (a, (0 : M)) ∉ f.graph :=
8585
λ h, (mem_graph_iff.1 h).2.irrefl
8686

87-
@[simp] lemma image_fst_graph (f : α →₀ M) : f.graph.image prod.fst = f.support :=
88-
by simp only [graph, map_eq_image, image_image, embedding.coe_fn_mk, (∘), image_id']
87+
@[simp] lemma image_fst_graph [decidable_eq α] (f : α →₀ M) : f.graph.image prod.fst = f.support :=
88+
begin
89+
classical,
90+
simp only [graph, map_eq_image, image_image, embedding.coe_fn_mk, (∘), image_id'],
91+
end
8992

9093
lemma graph_injective (α M) [has_zero M] : injective (@graph α M _) :=
9194
begin
9295
intros f g h,
96+
classical,
9397
have hsup : f.support = g.support, by rw [← image_fst_graph, h, image_fst_graph],
9498
refine ext_iff'.2 ⟨hsup, λ x hx, apply_eq_of_mem_graph $ h.symm ▸ _⟩,
9599
exact mk_mem_graph _ (hsup ▸ hx)
@@ -114,11 +118,15 @@ end
114118
{ apply nodup_to_list }
115119
end
116120

117-
@[simp] lemma to_alist_keys_to_finset (f : α →₀ M) : f.to_alist.keys.to_finset = f.support :=
121+
@[simp] lemma to_alist_keys_to_finset [decidable_eq α] (f : α →₀ M) :
122+
f.to_alist.keys.to_finset = f.support :=
118123
by { ext, simp [to_alist, alist.mem_keys, alist.keys, list.keys] }
119124

120125
@[simp] lemma mem_to_alist {f : α →₀ M} {x : α} : x ∈ f.to_alist ↔ f x ≠ 0 :=
121-
by rw [alist.mem_keys, ←list.mem_to_finset, to_alist_keys_to_finset, mem_support_iff]
126+
begin
127+
classical,
128+
rw [alist.mem_keys, ←list.mem_to_finset, to_alist_keys_to_finset, mem_support_iff]
129+
end
122130

123131
end graph
124132

@@ -135,35 +143,44 @@ open list
135143

136144
/-- Converts an association list into a finitely supported function via `alist.lookup`, sending
137145
absent keys to zero. -/
138-
@[simps] def lookup_finsupp (l : alist (λ x : α, M)) : α →₀ M :=
139-
{ support := (l.1.filter $ λ x, sigma.snd x ≠ 0).keys.to_finset,
140-
to_fun := λ a, (l.lookup a).get_or_else 0,
146+
def lookup_finsupp (l : alist (λ x : α, M)) : α →₀ M :=
147+
{ support := by haveI := classical.dec_eq α; haveI := classical.dec_eq M; exact
148+
(l.1.filter $ λ x, sigma.snd x ≠ 0).keys.to_finset,
149+
to_fun := λ a, by haveI := classical.dec_eq α; exact (l.lookup a).get_or_else 0,
141150
mem_support_to_fun := λ a, begin
151+
classical,
142152
simp_rw [mem_to_finset, list.mem_keys, list.mem_filter, ←mem_lookup_iff],
143153
cases lookup a l;
144154
simp
145155
end }
146156

147-
alias lookup_finsupp_to_fun ← lookup_finsupp_apply
157+
@[simp] lemma lookup_finsupp_apply [decidable_eq α] (l : alist (λ x : α, M)) (a : α) :
158+
l.lookup_finsupp a = (l.lookup a).get_or_else 0 :=
159+
by convert rfl
160+
161+
@[simp] lemma lookup_finsupp_support [decidable_eq α] [decidable_eq M] (l : alist (λ x : α, M)) :
162+
l.lookup_finsupp.support = (l.1.filter $ λ x, sigma.snd x ≠ 0).keys.to_finset :=
163+
by convert rfl
148164

149-
lemma lookup_finsupp_eq_iff_of_ne_zero {l : alist (λ x : α, M)} {a : α} {x : M} (hx : x ≠ 0) :
165+
lemma lookup_finsupp_eq_iff_of_ne_zero [decidable_eq α]
166+
{l : alist (λ x : α, M)} {a : α} {x : M} (hx : x ≠ 0) :
150167
l.lookup_finsupp a = x ↔ x ∈ l.lookup a :=
151-
by { rw lookup_finsupp_to_fun, cases lookup a l with m; simp [hx.symm] }
168+
by { rw lookup_finsupp_apply, cases lookup a l with m; simp [hx.symm] }
152169

153-
lemma lookup_finsupp_eq_zero_iff {l : alist (λ x : α, M)} {a : α} :
170+
lemma lookup_finsupp_eq_zero_iff [decidable_eq α] {l : alist (λ x : α, M)} {a : α} :
154171
l.lookup_finsupp a = 0 ↔ a ∉ l ∨ (0 : M) ∈ l.lookup a :=
155-
by { rw [lookup_finsupp_to_fun, ←lookup_eq_none], cases lookup a l with m; simp }
172+
by { rw [lookup_finsupp_apply, ←lookup_eq_none], cases lookup a l with m; simp }
156173

157174
@[simp] lemma empty_lookup_finsupp : lookup_finsupp (∅ : alist (λ x : α, M)) = 0 :=
158-
by { ext, simp }
175+
by { classical, ext, simp }
159176

160-
@[simp] lemma insert_lookup_finsupp (l : alist (λ x : α, M)) (a : α) (m : M) :
177+
@[simp] lemma insert_lookup_finsupp [decidable_eq α] (l : alist (λ x : α, M)) (a : α) (m : M) :
161178
(l.insert a m).lookup_finsupp = l.lookup_finsupp.update a m :=
162179
by { ext b, by_cases h : b = a; simp [h] }
163180

164181
@[simp] lemma singleton_lookup_finsupp (a : α) (m : M) :
165182
(singleton a m).lookup_finsupp = finsupp.single a m :=
166-
by simp [←alist.insert_empty]
183+
by { classical, simp [←alist.insert_empty] }
167184

168185
@[simp] lemma _root_.finsupp.to_alist_lookup_finsupp (f : α →₀ M) : f.to_alist.lookup_finsupp = f :=
169186
begin
@@ -370,7 +387,11 @@ lemma equiv_map_domain_trans' (f : α ≃ β) (g : β ≃ γ) :
370387

371388
@[simp] lemma equiv_map_domain_single (f : α ≃ β) (a : α) (b : M) :
372389
equiv_map_domain f (single a b) = single (f a) b :=
373-
by ext x; simp only [single_apply, equiv.apply_eq_iff_eq_symm_apply, equiv_map_domain_apply]; congr
390+
begin
391+
classical,
392+
ext x,
393+
simp only [single_apply, equiv.apply_eq_iff_eq_symm_apply, equiv_map_domain_apply],
394+
end
374395

375396
@[simp] lemma equiv_map_domain_zero {f : α ≃ β} : equiv_map_domain f (0 : α →₀ M) = (0 : β →₀ M) :=
376397
by ext x; simp only [equiv_map_domain_apply, coe_zero, pi.zero_apply]
@@ -537,6 +558,7 @@ lemma map_domain_apply' (S : set α) {f : α → β} (x : α →₀ M)
537558
(hS : (x.support : set α) ⊆ S) (hf : set.inj_on f S) {a : α} (ha : a ∈ S) :
538559
map_domain f x (f a) = x a :=
539560
begin
561+
classical,
540562
rw [map_domain, sum_apply, sum],
541563
simp_rw single_apply,
542564
by_cases hax : a ∈ x.support,
@@ -646,6 +668,7 @@ lemma map_domain_inj_on (S : set α) {f : α → β}
646668
begin
647669
intros v₁ hv₁ v₂ hv₂ eq,
648670
ext a,
671+
classical,
649672
by_cases h : a ∈ v₁.support ∪ v₂.support,
650673
{ rw [← map_domain_apply' S _ hv₁ hf _, ← map_domain_apply' S _ hv₂ hf _, eq];
651674
{ apply set.union_subset hv₁ hv₂,
@@ -796,7 +819,7 @@ by { ext, simp, }
796819

797820
@[simp] lemma some_single_some [has_zero M] (a : α) (m : M) :
798821
(single (option.some a) m : option α →₀ M).some = single a m :=
799-
by { ext b, simp [single_apply], }
822+
by { classical, ext b, simp [single_apply], }
800823

801824
@[to_additive]
802825
lemma prod_option_index [add_comm_monoid M] [comm_monoid N]
@@ -831,8 +854,8 @@ variables [has_zero M] (p : α → Prop) (f : α →₀ M)
831854
/--
832855
`filter p f` is the finitely supported function that is `f a` if `p a` is true and 0 otherwise. -/
833856
def filter (p : α → Prop) (f : α →₀ M) : α →₀ M :=
834-
{ to_fun := λ a, if p a then f a else 0,
835-
support := f.support.filter (λ a, p a),
857+
{ to_fun := λ a, by haveI := classical.dec_pred p; exact if p a then f a else 0,
858+
support := by haveI := classical.dec_pred p; exact f.support.filter (λ a, p a),
836859
mem_support_to_fun := λ a, by split_ifs; { simp only [h, mem_filter, mem_support_iff], tauto } }
837860

838861
lemma filter_apply (a : α) [D : decidable (p a)] : f.filter p a = if p a then f a else 0 :=
@@ -849,16 +872,16 @@ by simp only [fun_like.ext_iff, filter_eq_indicator, set.indicator_apply_eq_self
849872
not_imp_comm]
850873

851874
@[simp] lemma filter_apply_pos {a : α} (h : p a) : f.filter p a = f a :=
852-
if_pos h
875+
by { classical, convert if_pos h }
853876

854877
@[simp] lemma filter_apply_neg {a : α} (h : ¬ p a) : f.filter p a = 0 :=
855-
if_neg h
878+
by { classical, convert if_neg h }
856879

857880
@[simp] lemma support_filter [D : decidable_pred p] : (f.filter p).support = f.support.filter p :=
858881
by rw subsingleton.elim D; refl
859882

860883
lemma filter_zero : (0 : α →₀ M).filter p = 0 :=
861-
by rw [← support_eq_empty, support_filter, support_zero, finset.filter_empty]
884+
by { classical, rw [← support_eq_empty, support_filter, support_zero, finset.filter_empty] }
862885

863886
@[simp] lemma filter_single_of_pos {a : α} {b : M} (h : p a) :
864887
(single a b).filter p = single a b :=
@@ -870,14 +893,18 @@ by rw [← support_eq_empty, support_filter, support_zero, finset.filter_empty]
870893
@[to_additive] lemma prod_filter_index [comm_monoid N] (g : α → M → N) :
871894
(f.filter p).prod g = ∏ x in (f.filter p).support, g x (f x) :=
872895
begin
896+
classical,
873897
refine finset.prod_congr rfl (λ x hx, _),
874898
rw [support_filter, finset.mem_filter] at hx,
875899
rw [filter_apply_pos _ _ hx.2]
876900
end
877901

878902
@[simp, to_additive] lemma prod_filter_mul_prod_filter_not [comm_monoid N] (g : α → M → N) :
879903
(f.filter p).prod g * (f.filter (λ a, ¬ p a)).prod g = f.prod g :=
880-
by simp_rw [prod_filter_index, support_filter, prod_filter_mul_prod_filter_not, finsupp.prod]
904+
begin
905+
classical,
906+
simp_rw [prod_filter_index, support_filter, prod_filter_mul_prod_filter_not, finsupp.prod]
907+
end
881908

882909
@[simp, to_additive] lemma prod_div_prod_filter [comm_group G] (g : α → M → G) :
883910
f.prod g / (f.filter p).prod g = (f.filter (λ a, ¬p a)).prod g :=
@@ -897,20 +924,26 @@ section frange
897924
variables [has_zero M]
898925

899926
/-- `frange f` is the image of `f` on the support of `f`. -/
900-
def frange (f : α →₀ M) : finset M := finset.image f f.support
927+
def frange (f : α →₀ M) : finset M :=
928+
by haveI := classical.dec_eq M; exact finset.image f f.support
901929

902930
theorem mem_frange {f : α →₀ M} {y : M} :
903931
y ∈ f.frange ↔ y ≠ 0 ∧ ∃ x, f x = y :=
904-
finset.mem_image.trans
932+
by classical; exact finset.mem_image.trans
905933
⟨λ ⟨x, hx1, hx2⟩, ⟨hx2 ▸ mem_support_iff.1 hx1, x, hx2⟩,
906934
λ ⟨hy, x, hx⟩, ⟨x, mem_support_iff.2 (hx.symm ▸ hy), hx⟩⟩
907935

908936
theorem zero_not_mem_frange {f : α →₀ M} : (0:M) ∉ f.frange :=
909937
λ H, (mem_frange.1 H).1 rfl
910938

911939
theorem frange_single {x : α} {y : M} : frange (single x y) ⊆ {y} :=
912-
λ r hr, let ⟨t, ht1, ht2⟩ := mem_frange.1 hr in ht2 ▸
913-
(by rw single_apply at ht2 ⊢; split_ifs at ht2 ⊢; [exact finset.mem_singleton_self _, cc])
940+
λ r hr, let ⟨t, ht1, ht2⟩ := mem_frange.1 hr in ht2 ▸ begin
941+
classical,
942+
rw single_apply at ht2 ⊢,
943+
split_ifs at ht2 ⊢,
944+
{ exact finset.mem_singleton_self _ },
945+
{ exact (t ht2.symm).elim }
946+
end
914947

915948
end frange
916949

@@ -925,7 +958,9 @@ variables [has_zero M] {p : α → Prop}
925958
/--
926959
`subtype_domain p f` is the restriction of the finitely supported function `f` to subtype `p`. -/
927960
def subtype_domain (p : α → Prop) (f : α →₀ M) : (subtype p →₀ M) :=
928-
⟨f.support.subtype p, f ∘ coe, λ a, by simp only [mem_subtype, mem_support_iff]⟩
961+
{ support := by haveI := classical.dec_pred p; exact f.support.subtype p,
962+
to_fun := f ∘ coe,
963+
mem_support_to_fun := λ a, by simp only [mem_subtype, mem_support_iff] }
929964

930965
@[simp] lemma support_subtype_domain [D : decidable_pred p] {f : α →₀ M} :
931966
(subtype_domain p f).support = f.support.subtype p :=
@@ -940,19 +975,23 @@ rfl
940975

941976
lemma subtype_domain_eq_zero_iff' {f : α →₀ M} :
942977
f.subtype_domain p = 0 ↔ ∀ x, p x → f x = 0 :=
943-
by simp_rw [← support_eq_empty, support_subtype_domain, subtype_eq_empty, not_mem_support_iff]
978+
begin
979+
classical,
980+
simp_rw [← support_eq_empty, support_subtype_domain, subtype_eq_empty, not_mem_support_iff]
981+
end
944982

945983
lemma subtype_domain_eq_zero_iff {f : α →₀ M} (hf : ∀ x ∈ f.support , p x) :
946984
f.subtype_domain p = 0 ↔ f = 0 :=
947985
subtype_domain_eq_zero_iff'.trans ⟨λ H, ext $ λ x,
948-
if hx : p x then H x hx else not_mem_support_iff.1 $ mt (hf x) hx, λ H x _, by simp [H]⟩
986+
by classical; exact
987+
if hx : p x then H x hx else not_mem_support_iff.1 $ mt (hf x) hx, λ H x _, by simp [H]⟩
949988

950989
@[to_additive]
951990
lemma prod_subtype_domain_index [comm_monoid N] {v : α →₀ M}
952991
{h : α → M → N} (hp : ∀x∈v.support, p x) :
953992
(v.subtype_domain p).prod (λa b, h a b) = v.prod h :=
954993
prod_bij (λp _, p.val)
955-
(λ _, mem_subtype.1)
994+
(λ _, by classical; exact mem_subtype.1)
956995
(λ _ _, rfl)
957996
(λ _ _ _ _, subtype.eq)
958997
(λ b hb, ⟨⟨b, hp b hb⟩, mem_subtype.2 hb, rfl⟩)
@@ -1075,6 +1114,7 @@ f.sum $ λp c, single p.1 (single p.2 c)
10751114
@[simp] lemma curry_apply (f : (α × β) →₀ M) (x : α) (y : β) :
10761115
f.curry x y = f (x, y) :=
10771116
begin
1117+
classical,
10781118
have : ∀ (b : α × β), single b.fst (single b.snd (f b)) x y = if b = (x, y) then f b else 0,
10791119
{ rintros ⟨b₁, b₂⟩,
10801120
simp [single_apply, ite_apply, prod.ext_iff, ite_and],
@@ -1115,6 +1155,7 @@ by refine ⟨finsupp.curry, finsupp.uncurry, λ f, _, λ f, _⟩; simp only [
11151155
lemma filter_curry (f : α × β →₀ M) (p : α → Prop) :
11161156
(f.filter (λa:α×β, p a.1)).curry = f.curry.filter p :=
11171157
begin
1158+
classical,
11181159
rw [finsupp.curry, finsupp.curry, finsupp.sum, finsupp.sum, filter_sum, support_filter,
11191160
sum_filter],
11201161
refine finset.sum_congr rfl _,
@@ -1143,7 +1184,8 @@ section sum
11431184
def sum_elim {α β γ : Type*} [has_zero γ]
11441185
(f : α →₀ γ) (g : β →₀ γ) : α ⊕ β →₀ γ :=
11451186
on_finset
1146-
((f.support.map ⟨_, sum.inl_injective⟩) ∪ g.support.map ⟨_, sum.inr_injective⟩)
1187+
(by haveI := classical.dec_eq α; haveI := classical.dec_eq β;
1188+
exact (f.support.map ⟨_, sum.inl_injective⟩) ∪ g.support.map ⟨_, sum.inr_injective⟩)
11471189
(sum.elim f g)
11481190
(λ ab h, by { cases ab with a b; simp only [sum.elim_inl, sum.elim_inr] at h; simpa })
11491191

@@ -1475,12 +1517,15 @@ between the subtype of finitely supported functions with support contained in `s
14751517
the type of finitely supported functions from `s`. -/
14761518
def restrict_support_equiv (s : set α) (M : Type*) [add_comm_monoid M] :
14771519
{f : α →₀ M // ↑f.support ⊆ s } ≃ (s →₀ M) :=
1478-
begin
1479-
refine ⟨λf, subtype_domain (λx, x ∈ s) f.1, λ f, ⟨f.map_domain subtype.val, _⟩, _, _⟩,
1480-
{ refine set.subset.trans (finset.coe_subset.2 map_domain_support) _,
1520+
{ to_fun := λ f, subtype_domain (λ x, x ∈ s) f.1,
1521+
inv_fun := λ f, ⟨f.map_domain subtype.val, begin
1522+
classical,
1523+
refine set.subset.trans (finset.coe_subset.2 map_domain_support) _,
14811524
rw [finset.coe_image, set.image_subset_iff],
1482-
exact assume x hx, x.2 },
1483-
{ rintros ⟨f, hf⟩,
1525+
exact assume x hx, x.2,
1526+
end⟩,
1527+
left_inv := begin
1528+
rintros ⟨f, hf⟩,
14841529
apply subtype.eq,
14851530
ext a,
14861531
dsimp only,
@@ -1490,12 +1535,13 @@ begin
14901535
{ convert map_domain_notin_range _ _ h,
14911536
rw [← not_mem_support_iff],
14921537
refine mt _ h,
1493-
exact assume ha, ⟨⟨a, hf ha⟩, rfl⟩ } },
1494-
{ assume f,
1538+
exact assume ha, ⟨⟨a, hf ha⟩, rfl⟩ }
1539+
end,
1540+
right_inv := λ f, begin
14951541
ext ⟨a, ha⟩,
14961542
dsimp only,
1497-
rw [subtype_domain_apply, map_domain_apply subtype.val_injective] }
1498-
end
1543+
rw [subtype_domain_apply, map_domain_apply subtype.val_injective]
1544+
end }
14991545

15001546
/-- Given `add_comm_monoid M` and `e : α ≃ β`, `dom_congr e` is the corresponding `equiv` between
15011547
`α →₀ M` and `β →₀ M`.
@@ -1556,7 +1602,8 @@ end
15561602

15571603
/-- Given `l`, a finitely supported function from the sigma type `Σ (i : ι), αs i` to `β`,
15581604
`split_support l` is the finset of indices in `ι` that appear in the support of `l`. -/
1559-
def split_support : finset ι := l.support.image sigma.fst
1605+
def split_support (l : (Σ i, αs i) →₀ M) : finset ι :=
1606+
by haveI := classical.dec_eq ι; exact l.support.image sigma.fst
15601607

15611608
lemma mem_split_support_iff_nonzero (i : ι) :
15621609
i ∈ split_support l ↔ split l i ≠ 0 :=

0 commit comments

Comments
 (0)