@@ -14,9 +14,8 @@ import ring_theory.polynomial.basic
14
14
15
15
* `lagrange.basis s x` where `s : finset F` and `x : F`: the Lagrange basis polynomial
16
16
that evaluates to `1` at `x` and `0` at other elements of `s`.
17
- * `lagrange.interpolate s f` where `s : finset F` and `f : s → F`: the Lagrange interpolant
17
+ * `lagrange.interpolate s f` where `s : finset F` and `f : F → F`: the Lagrange interpolant
18
18
that evaluates to `f x` at `x` for `x ∈ s`.
19
-
20
19
-/
21
20
22
21
noncomputable theory
@@ -38,6 +37,9 @@ def basis (x : F) : polynomial F :=
38
37
@[simp] theorem basis_empty (x : F) : basis ∅ x = 1 :=
39
38
rfl
40
39
40
+ @[simp] theorem basis_singleton_self (x : F) : basis {x} x = 1 :=
41
+ by rw [basis, finset.erase_singleton, finset.prod_empty]
42
+
41
43
@[simp] theorem eval_basis_self (x : F) : (basis s x).eval x = 1 :=
42
44
begin
43
45
rw [basis, ← coe_eval_ring_hom, (eval_ring_hom x).map_prod, coe_eval_ring_hom,
@@ -77,26 +79,26 @@ begin
77
79
{ rw ← pow_one (X : polynomial F) at hz, exact X_pow_sub_C_ne_zero zero_lt_one _ hz } }
78
80
end
79
81
80
- variables (f : s → F)
82
+ variables (f : F → F)
81
83
82
- /-- Lagrange interpolation: given a finset `s` and a function `f : s → F`,
84
+ /-- Lagrange interpolation: given a finset `s` and a function `f : F → F`,
83
85
`interpolate s f` is the unique polynomial of degree `< s.card`
84
86
that takes value `f x` on all `x` in `s`. -/
85
87
def interpolate : polynomial F :=
86
- ∑ x in s.attach , C (f x) * basis s x
88
+ ∑ x in s, C (f x) * basis s x
87
89
88
90
@[simp] theorem interpolate_empty (f) : interpolate (∅ : finset F) f = 0 :=
89
91
rfl
90
92
91
- @[simp] theorem eval_interpolate (x) (H : x ∈ s) : eval x (interpolate s f) = f ⟨x, H⟩ :=
93
+ @[simp] theorem interpolate_singleton (f) (x : F) : interpolate {x} f = C (f x) :=
94
+ by rw [interpolate, finset.sum_singleton, basis_singleton_self, mul_one]
95
+
96
+ @[simp] theorem eval_interpolate (x) (H : x ∈ s) : eval x (interpolate s f) = f x :=
92
97
begin
93
- rw [interpolate,
94
- ← coe_eval_ring_hom, (eval_ring_hom x).map_sum, coe_eval_ring_hom,
95
- finset.sum_eq_single (⟨x, H⟩ : { x // x ∈ s })],
96
- { rw [eval_mul, eval_C, subtype.coe_mk, eval_basis_self, mul_one] },
97
- { rintros ⟨y, hy⟩ _ hyx, rw [eval_mul, subtype.coe_mk, eval_basis_ne s y x H, mul_zero],
98
- { rintros rfl, exact hyx rfl } },
99
- { intro h, exact absurd (finset.mem_attach _ _) h }
98
+ rw [interpolate, ←coe_eval_ring_hom, ring_hom.map_sum, coe_eval_ring_hom, finset.sum_eq_single x],
99
+ { simp },
100
+ { intros y hy hxy, simp [eval_basis_ne s y x H hxy.symm] },
101
+ { intro h, exact (h H).elim }
100
102
end
101
103
102
104
theorem degree_interpolate_lt : (interpolate s f).degree < s.card :=
@@ -107,11 +109,26 @@ calc (C (f b) * basis s b).degree
107
109
... ≤ 0 + (basis s b).degree : add_le_add_right degree_C_le _
108
110
... = (basis s b).degree : zero_add _
109
111
... ≤ (basis s b).nat_degree : degree_le_nat_degree
110
- ... = (s.card - 1 : ℕ) : by { rw nat_degree_basis s b b. 2 }
112
+ ... = (s.card - 1 : ℕ) : by { rwa nat_degree_basis }
111
113
... < s.card : with_bot.coe_lt_coe.2 (nat.pred_lt $ mt finset.card_eq_zero.1 H)
112
114
115
+ theorem degree_interpolate_erase {x} (hx : x ∈ s) :
116
+ (interpolate (s.erase x) f).degree < (s.card - 1 : ℕ) :=
117
+ begin
118
+ convert degree_interpolate_lt (s.erase x) f,
119
+ rw [finset.card_erase_of_mem hx, nat.pred_eq_sub_one]
120
+ end
121
+
122
+ theorem interpolate_eq_of_eval_eq (f g : F → F) {s : finset F} (hs : ∀ x ∈ s, f x = g x) :
123
+ interpolate s f = interpolate s g :=
124
+ begin
125
+ rw [interpolate, interpolate],
126
+ refine finset.sum_congr rfl (λ x hx, _),
127
+ rw hs x hx,
128
+ end
129
+
113
130
/-- Linear version of `interpolate`. -/
114
- def linterpolate : (s → F) →ₗ[F] polynomial F :=
131
+ def linterpolate : (F → F) →ₗ[F] polynomial F :=
115
132
{ to_fun := interpolate s,
116
133
map_add' := λ f g, by { simp_rw [interpolate, ← finset.sum_add_distrib, ← add_mul, ← C_add],
117
134
refl },
@@ -147,6 +164,13 @@ eq_of_sub_eq_zero $ eq_zero_of_eval_eq_zero s'
147
164
(lt_of_le_of_lt (degree_sub_le f g) $ max_lt hf hg)
148
165
(λ x hx, by rw [eval_sub, hfg x hx, sub_self])
149
166
167
+ theorem eq_interpolate_of_eval_eq {g : polynomial F} (hg : g.degree < s.card)
168
+ (hgf : ∀ x ∈ s, g.eval x = f x) : interpolate s f = g :=
169
+ eq_of_eval_eq s (degree_interpolate_lt _ _) hg $ λ x hx, begin
170
+ rw hgf x hx,
171
+ exact eval_interpolate _ _ _ hx,
172
+ end
173
+
150
174
theorem eq_interpolate (f : polynomial F) (hf : f.degree < s.card) :
151
175
interpolate s (λ x, f.eval x) = f :=
152
176
eq_of_eval_eq s (degree_interpolate_lt s _) hf $ λ x hx, eval_interpolate s _ x hx
@@ -156,12 +180,45 @@ of degree less than `s.card`. -/
156
180
def fun_equiv_degree_lt : degree_lt F s.card ≃ₗ[F] (s → F) :=
157
181
{ to_fun := λ f x, f.1 .eval x,
158
182
map_add' := λ f g, funext $ λ x, eval_add,
159
- map_smul' := λ c f, funext $ λ x, by
160
- { change eval ↑x (c • f).val = (c • λ (x : s), eval ↑x f.val) x,
161
- rw [pi.smul_apply, smul_eq_mul, ← @eval_C F c _ x,
162
- ← eval_mul, eval_C, C_mul'], refl },
163
- inv_fun := λ f, ⟨interpolate s f, mem_degree_lt.2 $ degree_interpolate_lt s f⟩,
164
- left_inv := λ f, subtype.eq $ eq_interpolate s f $ mem_degree_lt.1 f.2 ,
165
- right_inv := λ f, funext $ λ ⟨x, hx⟩, eval_interpolate s f x hx }
183
+ map_smul' := λ c f, funext $ by simp,
184
+ inv_fun := λ f, ⟨interpolate s (λ x, if hx : x ∈ s then f ⟨x, hx⟩ else 0 ),
185
+ mem_degree_lt.2 $ degree_interpolate_lt _ _⟩,
186
+ left_inv := λ f, begin apply subtype.eq,
187
+ simp only [subtype.coe_mk, subtype.val_eq_coe, dite_eq_ite],
188
+ convert eq_interpolate s f (mem_degree_lt.1 f.2 ) using 1 ,
189
+ rw interpolate_eq_of_eval_eq,
190
+ intros x hx,
191
+ rw if_pos hx end ,
192
+ right_inv := λ f, funext $ λ ⟨x, hx⟩, begin
193
+ convert eval_interpolate s _ x hx,
194
+ simp_rw dif_pos hx end }
195
+
196
+ theorem interpolate_eq_interpolate_erase_add {x y : F} (hx : x ∈ s) (hy : y ∈ s) (hxy : x ≠ y) :
197
+ interpolate s f =
198
+ C (y - x)⁻¹ * ((X - C x) * interpolate (s.erase x) f + (C y - X) * interpolate (s.erase y) f) :=
199
+ begin
200
+ refine eq_interpolate_of_eval_eq _ _ _ (λ z hz, _),
201
+ { rw [degree_mul, degree_C (inv_ne_zero (sub_ne_zero.2 hxy.symm)), zero_add],
202
+ refine lt_of_le_of_lt (degree_add_le _ _) (max_lt _ _),
203
+ { rw [degree_mul, degree_X_sub_C],
204
+ convert (with_bot.add_lt_add_iff_left (with_bot.coe_ne_bot _)).2
205
+ (degree_interpolate_erase s f hx),
206
+ simp [nat.one_add, nat.sub_one, nat.succ_pred_eq_of_pos (finset.card_pos.2 ⟨x, hx⟩)] },
207
+ { rw [degree_mul, ←neg_sub, degree_neg, degree_X_sub_C],
208
+ convert (with_bot.add_lt_add_iff_left (with_bot.coe_ne_bot _)).2
209
+ (degree_interpolate_erase s f hy),
210
+ simp [nat.one_add, nat.sub_one, nat.succ_pred_eq_of_pos (finset.card_pos.2 ⟨y, hy⟩)] } },
211
+ { by_cases hzx : z = x,
212
+ { simp [hzx, eval_interpolate (s.erase y) f x (finset.mem_erase_of_ne_of_mem hxy hx),
213
+ inv_mul_eq_iff_eq_mul₀ (sub_ne_zero_of_ne hxy.symm)] },
214
+ { by_cases hzy : z = y,
215
+ { simp [hzy, eval_interpolate (s.erase x) f y (finset.mem_erase_of_ne_of_mem hxy.symm hy),
216
+ inv_mul_eq_iff_eq_mul₀ (sub_ne_zero_of_ne hxy.symm)] },
217
+ { simp only [eval_interpolate (s.erase x) f z (finset.mem_erase_of_ne_of_mem hzx hz),
218
+ eval_interpolate (s.erase y) f z (finset.mem_erase_of_ne_of_mem hzy hz),
219
+ inv_mul_eq_iff_eq_mul₀ (sub_ne_zero_of_ne hxy.symm), eval_mul, eval_C, eval_add,
220
+ eval_sub, eval_X],
221
+ ring } } }
222
+ end
166
223
167
224
end lagrange
0 commit comments