Zulip Chat Archive
Stream: Is there code for X?
Topic: Making `finset.sum` into an explicit sum
Vasily Ilin (Jun 06 2022 at 21:38):
How do I go between finset.sum
to an explicit sum? I'd imagine it's just simp
, using docs#finset.sum_cons three times. But simp
doesn't do it.
import tactic
import linear_algebra.basis
import data.matrix.notation
variables (k : Type) (V : Type) [field k] [add_comm_group V] [module k V]
example (f : fin 4 → k) (v0 v1 v2 v3 : V) : finset.univ.sum (λ (i : fin 4), f i • ![v0, v1, v2, v3] i) = f 0 • v0 + f 1 • v1 + f 2 • v2 + f 3 • v3 := sorry
Vasily Ilin (Jun 06 2022 at 21:47):
Also, what tactic would do this?
import tactic
import data.complex.basic
variables (k : Type) (V : Type) [field k] [add_comm_group V] [module k V]
example (g : fin 4 → k) (v0 v1 v2 v3 : V) :
g 0 • v0 + (g 1 - g 0) • v1 + (g 2 - g 1) • v2 + (g 3 - g 2) • v3 =
g 0 • (v0 - v1) + g 1 • (v1 - v2) + g 2 • (v2 - v3) + g 3 • v3 := sorry
Kevin Buzzard (Jun 06 2022 at 22:55):
import tactic
import data.complex.basic
variables (k : Type) (V : Type) [field k] [add_comm_group V] [module k V]
example (g : fin 4 → k) (v0 v1 v2 v3 : V) :
g 0 • v0 + (g 1 - g 0) • v1 + (g 2 - g 1) • v2 + (g 3 - g 2) • v3 =
g 0 • (v0 - v1) + g 1 • (v1 - v2) + g 2 • (v2 - v3) + g 3 • v3 :=
begin
simp only [smul_sub, sub_smul],
abel,
end
The hint
tactic suggests that you can't do this with one tactic.
Kevin Buzzard (Jun 06 2022 at 23:00):
import tactic
import linear_algebra.basis
import data.matrix.notation
variables (k : Type) (V : Type) [field k] [add_comm_group V] [module k V]
example (f : fin 4 → k) (v0 v1 v2 v3 : V) : finset.univ.sum (λ (i : fin 4), f i • ![v0, v1, v2, v3] i) = f 0 • v0 + f 1 • v1 + f 2 • v2 + f 3 • v3 :=
begin
simp [finset.sum_fin_eq_sum_range, finset.sum_range_succ],
end
works. I knew about finset.sum_range_succ
so could see that if I could translate into this I'd probably be done, and so I tried rw finset.sum_range
and auto-complete found finset.sum_fin_eq_sum_range
for me.
Eric Wieser (Jun 06 2022 at 23:05):
Eric Wieser (Jun 06 2022 at 23:06):
We seem to get a question asking for that lemma every week or so!
Vasily Ilin (Jun 07 2022 at 06:42):
With the help above I was able to finish the proof. But it looks quite ugly and takes a few seconds to compile. I'm sure such as simple proposition can be proven easier. Can anyone give me advice on how to make this proof better?
import tactic -- imports all the Lean tactics
import linear_algebra.basis
import data.real.basic
import data.complex.basic
import data.complex.module
import data.matrix.notation
variables (k : Type) (V : Type) [field k] [add_comm_group V] [module k V]
example (v1 v2 v3 v4: V) (lin_indep : linear_independent k ![v1, v2, v3, v4]) : linear_independent k ![v1-v2, v2-v3, v3-v4, v4] :=
begin
rw fintype.linear_independent_iff at *,
intros g h,
let f := ![g 0, g 1 - g 0, g 2 - g 1, g 3 - g 2],
specialize lin_indep f,
suffices hf : ∀ (i : fin 4), f i = 0,
have g0 : g 0 = 0,
calc g 0 = f 0 : rfl
... = 0 : hf 0,
have g1 : g 1 = 0,
calc g 1 = g 1 - g 0 + g 0 : by ring
... = f 1 + g 0 : by refl
... = 0 : by rw [hf 1, g0, zero_add],
have g2 : g 2 = 0,
calc g 2 = g 2 - g 1 + g 1 : by ring
... = f 2 + g 1 : by refl
... = 0 : by rw [hf 2, g1, zero_add],
have g3 : g 3 = 0,
calc g 3 = g 3 - g 2 + g 2 : by ring
... = f 3 + g 2 : by refl
... = 0 : by rw [hf 3, g2, zero_add],
intro i,
fin_cases i,
exact g0,
exact g1,
exact g2,
exact g3,
apply lin_indep,
calc finset.univ.sum (λ (i : fin 4), f i • ![v1, v2, v3, v4] i)
= f 0 • v1 + f 1 • v2 + f 2 • v3 + f 3 • v4 : by
begin
simp only [fin.sum_univ_succ, add_assoc, matrix.cons_val_zero, matrix.cons_val_succ, fin.succ_zero_eq_one, fin.succ_one_eq_two, fintype.univ_of_subsingleton, fin.mk_eq_subtype_mk, fin.mk_zero, finset.sum_singleton, add_right_inj],
refl,
end
... = g 0 • v1 + (g 1 - g 0) • v2 + (g 2 - g 1) • v3 + (g 3 - g 2) • v4 : rfl
... = g 0 • (v1 - v2) + g 1 • (v2 - v3) + g 2 • (v3 - v4) + g 3 • v4 : by
begin
simp only [smul_sub, sub_smul],
abel,
end
... = finset.univ.sum (λ (i : fin 4), g i • ![v1 - v2, v2 - v3, v3 - v4, v4] i) : by
begin
simp only [fin.sum_univ_succ, add_assoc, matrix.cons_val_zero, matrix.cons_val_succ, fin.succ_zero_eq_one, fin.succ_one_eq_two, fintype.univ_of_subsingleton, fin.mk_eq_subtype_mk, fin.mk_zero, finset.sum_singleton, add_right_inj],
refl,
end
... = 0 : h,
end
Wrenna Robson (Jun 07 2022 at 13:44):
import linear_algebra.basis
import data.matrix.notation
open matrix
variables (R : Type) (V : Type) [ring R] [add_comm_group V] [module R V]
lemma better_form (v1 v2 v3 v4 : V) :
![v1 - v2, v2 - v3, v3 - v4, v4] = ![v1, v2, v3, v4] - fin.snoc (fin.tail (![v1, v2, v3, v4])) 0 :=
by simp [vec_head, vec_tail, fin.snoc, fin.tail]; refl
lemma snoc_tail_lin_indep (v : fin 4 → V) (lin_indep : linear_independent R v) :
linear_independent R (v - fin.snoc (fin.tail v) 0) :=
begin
simp_rw fintype.linear_independent_iff at ⊢ lin_indep, intros g hg i,
suffices hli : finset.univ.sum (λ (i : fin 4),
(g - fin.cons 0 (fin.init g)) i • v i) = 0,
{ specialize lin_indep _ hli,
have g0 : g 0 - 0 = 0 := lin_indep 0, rw sub_zero at g0,
have g1 : g 1 - g 0 = 0 := lin_indep 1, rw g0 at g1, rw sub_zero at g1,
have g2 : g 2 - g 1 = 0 := lin_indep 2, rw g1 at g2, rw sub_zero at g2,
have g3 : g 3 - g 2 = 0 := lin_indep 3, rw g2 at g3, rw sub_zero at g3,
fin_cases i; [exact g0, exact g1, exact g2, exact g3] },
simp [fin.sum_univ_succ, smul_sub, sub_smul] at ⊢ hg,
change g 0 • v 0 + (g 1 • v 1 - g 0 • v 1 +
(g 2 • v 2 - g 1 • v 2 + (g 3 • v 3 - g 2 • v 3))) = 0,
change g 0 • v 0 - g 0 • v 1 + (g 1 • v 1 -
g 1 • v 2 + (g 2 • v 2 - g 2 • v 3 + (g 3 • v 3 - g 3 • 0))) = 0 at hg,
rw [smul_zero, sub_zero] at hg, simp_rw [sub_eq_add_neg] at ⊢ hg,
nth_rewrite 2 add_comm, nth_rewrite 4 add_comm, nth_rewrite 5 add_comm, simp_rw add_assoc at ⊢ hg,
exact hg
end
example (v1 v2 v3 v4 : V) (lin_indep : linear_independent R ![v1, v2, v3, v4]) :
linear_independent R ![v1-v2, v2-v3, v3 - v4, v4] :=
by rw better_form ; exact snoc_tail_lin_indep _ _ _ lin_indep
Wrenna Robson (Jun 07 2022 at 13:44):
This is a bit better :)
Wrenna Robson (Jun 07 2022 at 13:44):
The problem is ultimately in how you state the lemma - how you express ![v1-v2, v2-v3, v3 - v4, v4]
, basically.
Wrenna Robson (Jun 07 2022 at 13:46):
On some level this is a computational algebra task, which Lean has no natural facility in. That's the comm and assoc stuff at the end. Everything else is really just... making sure you're using sensible defintions.
Wrenna Robson (Jun 07 2022 at 13:48):
If you could express ![v1, v2, v3, v4]
as the image under a suitable linear map of ![v1-v2, v2-v3, v3 - v4, v4]
- bearing in mind that to use, say, linear_independent.map'
you would have to define a map onV
itself - this would be easier. But different expressions of ![v1-v2, v2-v3, v3 - v4, v4]
produce different difficulties.
Wrenna Robson (Jun 07 2022 at 13:50):
In general, given an arbitrary linear combination of ![v1, v2, v3, v4]
and proving linear independence from the linear independence of the v_i is going to be very close to showing that some matrix is non-singular...
Wrenna Robson (Jun 07 2022 at 13:54):
I note, by the way, that we don't seem to have something like vec_update
or vec_rotate
which makes this trickier to construct, as you can see.
Eric Wieser (Jun 07 2022 at 14:48):
vec_update
is docs#function.update
Eric Wieser (Jun 07 2022 at 14:48):
vec_rotate
is composition with docs#fin_rotate
Wrenna Robson (Jun 07 2022 at 19:52):
Aye. But we seem to have vec_cons
despite having fin.cons
also, unless I'm wrong?
Eric Wieser (Jun 07 2022 at 20:39):
I think the motivation is that the latter elaborates badly on non-dependent types. That may well be a concern for update
too.
Wrenna Robson (Jun 07 2022 at 20:41):
Huh, makes sense.
Anne Baanen (Jun 09 2022 at 09:59):
Eric Wieser said:
I think the motivation is that the latter elaborates badly on non-dependent types. That may well be a concern for
update
too.
The issue was specifically that the ![1, 2, 3]
notation elaborated badly and didn't get pretty-printed correctly (even with type ascriptions etc.)
Last updated: Dec 20 2023 at 11:08 UTC