Zulip Chat Archive

Stream: Is there code for X?

Topic: division of DualNumbers


Frederick Pu (Apr 06 2024 at 03:01):

Is there any code or division of DualNumbers? More specifically Div (DualNumber F) where F is a field. If not, would it be possible for me to get a pull request from formalizing it? Right now I working on some proofs about negative binomials that geometric sequences on DualNumbers would really help with.

Yaël Dillies (Apr 06 2024 at 07:16):

If @Eric Wieser doesn't have it then nobody has it

Eric Wieser (Apr 06 2024 at 08:28):

You can work with Units (DualNumber _) to get division of invertible elements. If you also want support for non-invertible elements; what do you intend to define 1/eps as?

Frederick Pu (Apr 06 2024 at 22:28):

Frederick Pu said:

Is there any code or division of DualNumbers? More specifically Div (DualNumber F) where F is a field. If not, would it be possible for me to get a pull request from formalizing it? Right now I working on some proofs about negative binomials that geometric sequences on DualNumbers would really help with.

Here's a quick demo of what I've done so far with division:

Definition of division:

noncomputable instance : Div (DualNumber ) :=
{
  div := fun a, b c, d => a/c, (b*c - a*d)/c^2
}

Basic lemmas to make proofs easier

theorem div_eq (a b : DualNumber ) : a / b = a.fst / b.fst, (a.snd * b.fst - a.fst * b.snd) / b.fst^2 := by rfl
theorem add_eq (a b : DualNumber ) : a + b = a.fst + b.fst, a.snd + b.snd := by exact rfl
theorem diff_eq (a b : DualNumber ) : a - b = a.fst - b.fst, a.snd - b.snd := by exact rfl

Basic arithmetic equations:

theorem sum_one_div (a b : DualNumber ) (ha : a.fst  0) (hb : b.fst  0) : 1 / a + 1 / b = (b + a) / (a*b) := by
  ...
theorem diff_one_div (a b : DualNumber ) (ha : a.fst  0) (hb : b.fst  0) : 1 / a - 1 / b = (b - a) / (a*b) := by
  ...

Projection equations:

theorem fst_one_div_real (a : ) : (1 / TrivSqZeroExt.inl a : DualNumber ).1 = 1 / a := by
  rw [div_eq]
  simp
theorem snd_one_div_real (a : ) : (1 / TrivSqZeroExt.inl a : DualNumber ).2 = 0 := by
  rw [div_eq]
  simp

Putting it all together into a usage example:

example (a b : ) (ha : a  0) : ε / (TrivSqZeroExt.inl a + (TrivSqZeroExt.inl b)*DualNumber.eps : DualNumber ) = ε * (1 / (TrivSqZeroExt.inl a)) := by
  rw [div_eq]
  apply congr_arg₂

  simp
  apply Or.inl
  rfl

  simp [fst_one_div_real, snd_one_div_real]
  field_simp
  have : (ε :DualNumber ).2 = 1 := by rfl
  rw [this]
  ring

Eric Wieser (Apr 06 2024 at 22:29):

Something to watch out for here; you should not use .1(Prod.fst) on dual numbers; you should use .fst (TrivSqZeroExt.fst) instead

Eric Wieser (Apr 06 2024 at 22:31):

Similarly, using ⟨re, dual⟩ will get you into trouble because this is Prod.mk; the API assumes you will write algebraMap _ _ re + dual*eps instead (or inl re + inr dual)

Frederick Pu (Apr 09 2024 at 03:05):

Eric Wieser said:

You can work with Units (DualNumber _) to get division of invertible elements. If you also want support for non-invertible elements; what do you intend to define 1/eps as?

I'm thinking of treating division as the deriv operator. That is if the division exists than it is well defined but otherwise it'll give a garbage output of 0+0ϵ0 + 0\epsilon.

Frederick Pu (Apr 09 2024 at 03:08):

Eric Wieser said:

Something to watch out for here; you should not use .1(Prod.fst) on dual numbers; you should use .fst (TrivSqZeroExt.fst) instead

Please correct me if I'm wrong but it feels like using the Prod notation makes a lot of elementary proofs easier to do using simp.

For example:

theorem fst_one_div_real (a : ) : (1 / TrivSqZeroExt.inl a : DualNumber ).1 = 1 / a := by
  rw [div_eq]
  simp
theorem snd_one_div_real (a : ) : (1 / TrivSqZeroExt.inl a : DualNumber ).2 = 0 := by
  rw [div_eq]
  simp

Kevin Buzzard (Apr 09 2024 at 09:10):

If you're only looking to divide by units then I would define Inv to be inverse on units and 0 off them, I would consider using IsUnit rather than a.1 != 0 as your normal form, and I would define Div to be a * b^{-1}.

Eric Wieser (Apr 09 2024 at 09:14):

Please correct me if I'm wrong but it feels like using the Prod notation makes a lot of elementary proofs easier to do using simp.

The rest of the TrivSqZeroExt API is not written with Prod.fst and Prod.snd, so if you use these functions then Mathlib has nothing to offer you

Eric Wieser (Apr 09 2024 at 09:14):

I think those lemmas are a bad example, because you should just prove them with rfl anyway

Eric Wieser (Apr 09 2024 at 09:17):

Anyway, I think this is close enough to iterate on; could you make a PR adding Div for TrivSqZeroExt?

Frederick Pu (Apr 10 2024 at 00:45):

Eric Wieser said:

I think those lemmas are a bad example, because you should just prove them with rfl anyway

Yeah I would love to. I don't think I have access to any of the mathlib sub-branches though

Kim Morrison (Apr 11 2024 at 16:27):

What do you mean by sub-branches?

Kevin Buzzard (Apr 11 2024 at 16:42):

I conjecture that Frederick might mean that they would like push access to non-master branches? What's your GitHub userid Frederick? It's not in your profile.

Or tell us what you actually meant :-)

Frederick Pu (Apr 11 2024 at 19:10):

Yeah that's what I meant. In the the "how to contribute to mathlib" page it said that you should get accesss to a non-master branch. Also, should I develop a lot of the lemma for it first or just start by commiting the definition?

Kevin Buzzard (Apr 11 2024 at 19:14):

Well you can't do any of those things until you answer the question about your GitHub userid. I think a reasonable PR would be the definition of Inv and Div, and some basic lemmas. As a general rule I wouldn't go over 100 lines for the first PR.

Eric Wieser (Apr 11 2024 at 19:15):

You need to tell us your github username (or put it in your zulip profile) for us to give you access :)

Frederick Pu (Apr 11 2024 at 19:15):

Ok my user id for github is FrederickPu

Eric Wieser (Apr 11 2024 at 19:18):

Invite sent!

Eric Wieser (Apr 11 2024 at 19:19):

Regarding the generalization to TrivSqZeroExt; I think it's something like

instance : Inv (tsze R M) where
  inv x := x.fst⁻¹, -(x.fst⁻¹ •> x.snd <• x.fst⁻¹)⟩

Frederick Pu (Apr 11 2024 at 19:57):

Created the pull request. I just did it using HDiv instead of inverses since I feel like it would be weird to assume that the internal division of M and R sepereatly should have anything to do with how they interact with eachother. Although this may lead to some compatibility issue in the future since I was mainly thinking about TrivExtZero R R

Eric Wieser (Apr 11 2024 at 20:10):

The case to be careful of is TrivSqZeroExt R R when R is non-commutativie

Eric Wieser (Apr 11 2024 at 20:16):

In the non-commutative case, division is a pretty useless operator, since it only lets you write a * inv b not inv a * b. So I think it is better to approach this thinking about defining the inverse; and then define division such that a / b = a * inv b, perhaps with a slightly nicer implementation.

The important thing is to prove a div_eq_mul_inv lemma!

Frederick Pu (Apr 11 2024 at 20:26):

Oh sorry should I redo it and submit another PR or wait till you reject my current one first?

Eric Wieser (Apr 11 2024 at 20:33):

You can edit the PR in place, no need to redo it or delete it; just make another commit with the changes and push again

Eric Wieser (Apr 11 2024 at 20:36):

Ah sorry, you do need to redo this

Eric Wieser (Apr 11 2024 at 20:36):

Because you pushed to origin, not upstream

Frederick Pu (Apr 11 2024 at 20:37):

Also it seems like the definition of inv should be more like this:

instance inv [HSub R M M] [Mul R] [Inv R] [SMul Rᵐᵒᵖ M] [SMul R M] : Inv (tsze R M) :=
  fun b => (b.1⁻¹, (b.1 - b.2) <• (b.1 * b.1)⁻¹)⟩

Frederick Pu (Apr 11 2024 at 20:38):

But HSub R M M is a bit sketch

Frederick Pu (Apr 11 2024 at 20:48):

ok. Can I get some feed back of my definition before I submit a PR?

Eric Wieser (Apr 11 2024 at 20:48):

The best place for feedback is in the PR itself!

Eric Wieser (Apr 11 2024 at 20:48):

Frederick Pu said:

Also it seems like the definition of inv should be more like this:

instance inv [HSub R M M] [Mul R] [Inv R] [SMul Rᵐᵒᵖ M] [SMul R M] : Inv (tsze R M) :=
  fun b => (b.1⁻¹, (b.1 - b.2) <• (b.1 * b.1)⁻¹)⟩

But I can tell you that your hunch is right, HSub R M M is too sketchy for this to be reasonable

Eric Wieser (Apr 11 2024 at 20:49):

I think you made an error when substituting $$1 + 0\eps$$, and that b.1 should be 0.

Frederick Pu (Apr 11 2024 at 20:49):

Which of these do you think is better?

instance inv [HSub R M M] [Mul R] [Field R] [Semiring M] [SMul Rᵐᵒᵖ M] [SMul R M] : Inv (tsze R M) :=
  fun b => (b.1⁻¹, (b.1 * (b.1 * b.1)⁻¹)  •> (1:M) + (b.2 <• (b.1 * b.1)⁻¹))⟩
instance inv [HSub R M M] [Mul R] [Inv R] [One M] [Add M] [SMul Rᵐᵒᵖ M] [SMul R M] : Inv (tsze R M) :=
  fun b => (b.1⁻¹, (b.1 * (b.1 * b.1)⁻¹)  •> (1:M) + (b.2 <• (b.1 * b.1)⁻¹))⟩

Frederick Pu (Apr 11 2024 at 20:50):

I feel like the Field and Semiring conditions nicely encapsulate the requirements but might be too restrictive if someone wants to go crazy

Eric Wieser (Apr 11 2024 at 20:51):

Eric Wieser said:

Regarding the generalization to TrivSqZeroExt; I think it's something like

instance : Inv (tsze R M) where
  inv x := x.fst⁻¹, -(x.fst⁻¹ •> x.snd <• x.fst⁻¹)⟩

I'm pretty sure this one is right, as it matches docs#fderiv_inv'

Eric Wieser (Apr 11 2024 at 20:53):

1 : M is suspicious in your code above too; remember that (1 : tsze R M) = inl (1 : R) + inr (0 : M)

Eric Wieser (Apr 11 2024 at 20:54):

So if you take your division formula for fun ⟨a, b⟩ ⟨c, d⟩ => ⟨a/c, (b*c - a*d)/c^2⟩, you should be subsituting a = 1 and b = 0.

Eric Wieser (Apr 11 2024 at 20:56):

Frederick Pu said:

I feel like the Field and Semiring conditions nicely encapsulate the requirements but might be too restrictive if someone wants to go crazy

I am afraid that a lot of the design of TrivSqZeroExt is precise because someone wanted to go crazy with non-commutative rings (such as the dual quaternions); that someone is me.

Frederick Pu (Apr 11 2024 at 20:59):

Eric Wieser said:

Eric Wieser said:

Regarding the generalization to TrivSqZeroExt; I think it's something like

instance : Inv (tsze R M) where
  inv x := x.fst⁻¹, -(x.fst⁻¹ •> x.snd <• x.fst⁻¹)⟩

I'm pretty sure this one is right, as it matches docs#fderiv_inv'

Wait so M is responsible for the negativeness? also why not group the inverses together?

Eric Wieser (Apr 11 2024 at 21:01):

Because grouping together inverses in the derivative of x⁻¹ is a lie told to you by commutative algebraists :devil:

Eric Wieser (Apr 11 2024 at 21:01):

Wait so M is responsible for the negativeness?

I don't think it really matters; in any real situation docs#neg_smul and docs#smul_neg applies anyway

Frederick Pu (Apr 11 2024 at 21:03):

@[simps apply]
def inlHom [Semiring R] [AddCommMonoid M] [Module R M] [Module Rᵐᵒᵖ M] : R →+* tsze R M where

It seems like R usually carries more ring structure

Eric Wieser (Apr 11 2024 at 21:03):

In that example, neither R nor M have negation

Frederick Pu (Apr 11 2024 at 21:03):

so might as well put the negative in :shrug:

Eric Wieser (Apr 11 2024 at 21:03):

The version with negation is [Ring R] [AddCommGroup M], in which case both have negation

Frederick Pu (Apr 11 2024 at 21:04):

Oh sorry

Eric Wieser (Apr 11 2024 at 21:04):

Here's an argument for why it should be M and not R; if you assume some kind of derivative model, then maybe R is the space of positive reals; the derivative of a function that's always positive can sometimes be negative, so arguably it's the differential piece (M) that should be carrying the negation

Frederick Pu (Apr 11 2024 at 21:04):

theorem snd_list_prod [Semiring R] [AddCommMonoid M] [Module R M] [Module Rᵐᵒᵖ M]
    [SMulCommClass R Rᵐᵒᵖ M] (l : List (tsze R M))

Frederick Pu (Apr 11 2024 at 21:05):

Eric Wieser said:

Here's an argument for why it should be M and not R; if you assume some kind of derivative model, then maybe R is the space of positive reals; the derivative of a function that's always positive can sometimes be negative, so arguably it's the differential piece (M) that should be carrying the negation

that's a good point, but why is always somethign R over M?

Eric Wieser (Apr 11 2024 at 21:05):

What do you mean by "over"?

Frederick Pu (Apr 11 2024 at 21:07):

Never mind, I thought that semirings had inverses for some reason

Eric Wieser (Apr 11 2024 at 21:08):

It's an easy mistake to make, mathlib is full of generalizations you don't usually have to think about

Frederick Pu (Apr 11 2024 at 21:08):

The interface is actually pretty clean i think:

instance inv [Neg M] [Inv R] [SMul Rᵐᵒᵖ M] [SMul R M] : Inv (tsze R M) :=
  fun b => (b.1⁻¹,  - (b.1⁻¹ •> b.2 <• b.1⁻¹))⟩

Frederick Pu (Apr 11 2024 at 21:10):

Also how do you motivate using b.1⁻¹ •> b.2 <• b.1⁻¹ vs b.2 <• b.1⁻¹ <• b.1⁻¹

Eric Wieser (Apr 11 2024 at 21:10):

Now you should define Div as well, and prove that the two agree

Eric Wieser (Apr 11 2024 at 21:10):

The motivation will appear when you try to prove that x * x⁻¹ = 1 for [DivisionRing R] and x.fst \ne 0

Frederick Pu (Apr 11 2024 at 21:11):

but if you're doing DivisionRing don't you have commutivity?

Eric Wieser (Apr 11 2024 at 21:14):

Nope, a division ring is a field without commutativity!

Frederick Pu (Apr 11 2024 at 21:14):

ahhhhh

Eric Wieser (Apr 11 2024 at 21:15):

(I think in French the words are swapped in some way, though I might be misremembering)

Frederick Pu (Apr 11 2024 at 21:16):

I'm not french tho, just a dumb undergrad

Eric Wieser (Apr 11 2024 at 21:19):

If you're writing lean code as an undergrad you're probably not dumb :)

Eric Wieser (Apr 11 2024 at 21:20):

Perhaps it's worth considering a more fun way to play this game:

  • Define division and inverses in a way that works on fields and vector spaces, prove they work well with multiplication
  • Once you have that working, try to remove commutativity

Frederick Pu (Apr 11 2024 at 21:39):

here's what I got so far:

theorem mul_inv [DivisionRing R] [AddCommGroup M] [Module Rᵐᵒᵖ M] [Module R M] {x : tsze R M} (hx : fst x  0) :
  x * x⁻¹ = 1 := by
{
  ext
  rw [fst_mul, fst_inv, fst_one, mul_inv_cancel hx]
  rw [snd_mul, snd_inv, smul_neg,  smul_assoc, smul_eq_mul, mul_inv_cancel hx, one_smul, fst_inv, add_left_neg, snd_one]
}

Frederick Pu (Apr 11 2024 at 21:40):

it's tough because you need the module to bring the negative to the outside

Frederick Pu (Apr 11 2024 at 21:41):

actually no you don't I don't know what was requiring me to have a Module

Eric Wieser (Apr 11 2024 at 21:42):

I think it's fine to assume a module if you need it

Frederick Pu (Apr 11 2024 at 21:42):

But module requires addcommgroup

Eric Wieser (Apr 11 2024 at 21:43):

One again, no it doesn't; at least, not in mathlib!

Frederick Pu (Apr 11 2024 at 21:44):

Screenshot-2024-04-11-174407.png

Frederick Pu (Apr 11 2024 at 21:44):

So you still need commutivity on M no?

Eric Wieser (Apr 11 2024 at 21:44):

This is referring to additive commutativity, a + b = b + a

Frederick Pu (Apr 11 2024 at 21:45):

so you dont care about addcommgroup?

Eric Wieser (Apr 11 2024 at 21:45):

Only really crazy people care about non-commutative addition

Frederick Pu (Apr 11 2024 at 21:46):

the thing is don't really need addcommgroup in the proof. You're never swapping terms

Eric Wieser (Apr 11 2024 at 21:46):

Frederick Pu said:

so you dont care about addcommgroup?

What you've written looks good to me

Frederick Pu (Apr 11 2024 at 21:46):

is there a semimodule or smth

Eric Wieser (Apr 11 2024 at 21:46):

Yes, but in mathlib it's written Module

Eric Wieser (Apr 11 2024 at 21:47):

A semimodule is just a module without negation, but we established you need negation on M anyway

Frederick Pu (Apr 11 2024 at 21:47):

how can they have the exact same name?

Frederick Pu (Apr 11 2024 at 21:48):

oh cause no mul comm i see what u mean

Frederick Pu (Apr 11 2024 at 21:49):

Ok, submitting the PR

Frederick Pu (Apr 11 2024 at 22:02):

How do I run the linter on my local machine

Eric Wieser (Apr 11 2024 at 22:28):

Can you write the PR number here after a # so that it auto-Links?

Eric Wieser (Apr 11 2024 at 22:48):

The style linter can be run with scripts/lint-style.sh

Eric Wieser (Apr 11 2024 at 22:49):

The other linter can be run by writing #lint in the file (and deleting it when you're done)

Notification Bot (Apr 11 2024 at 22:51):

95 messages were moved from this topic to #new members > making pull requests by Eric Wieser.

Frederick Pu (Apr 12 2024 at 00:34):

Do you know where I can find proofs of the following lemmas?

have op_smul_smul : ((fst x)⁻¹ •> (snd x <• (fst x)⁻¹)) <• fst x  = (fst x)⁻¹ •> ((snd x <• (fst x)⁻¹) <• fst x) := by sorry
have op_smul_assoc : (snd x <• (fst x)⁻¹ <• fst x) = (snd x <• ((fst x)⁻¹ <• fst x)) := by sorry
have op_smul_one : (snd x) <• (1:R) = snd x := by sorry

Eric Wieser (Apr 12 2024 at 00:48):

The first one needs [SMulCommClass R Rᵐᵒᵖ M], then is smul_comm

Eric Wieser (Apr 12 2024 at 00:49):

simp? or rw? can maybe help find the others

Frederick Pu (Apr 12 2024 at 01:27):

I got the first and the third one but the second one is giving me grief

Frederick Pu (Apr 12 2024 at 15:16):

Actually I don't think this second equation holds

Kevin Buzzard (Apr 12 2024 at 15:55):

Can you make a #mwe if you want other people to think about your question?

Frederick Pu (Apr 12 2024 at 16:24):

Kevin Buzzard said:

Can you make a #mwe if you want other people to think about your question?

I should have used op_smul_op_smul instead

Frederick Pu (Apr 12 2024 at 17:20):

How long do you think until I will be able to use this on dual numbers?

theorem tsum_geometric_of_norm_lt_one{K : Type u_4} [NormedField K] {ξ : K} (h : ξ < 1) :
∑' (n : ), ξ ^ n = (1 - ξ)⁻¹

Eric Wieser (Apr 12 2024 at 17:21):

You won't be able to use that theorem as written, because dual numbers don't form a field or even a division ring (eps has no invers)

Frederick Pu (Apr 12 2024 at 17:22):

so will we need to reprove the theorem but for whatever the dual numbers are?

Frederick Pu (Apr 12 2024 at 17:22):

Maybe NormedRing, and it holds for all units

Frederick Pu (Apr 12 2024 at 17:23):

I feel like if you know convergence then u don't really use any field properties to prove the geometric series, just dividing by the common ratio, which is ok if it's not eps

Eric Wieser (Apr 12 2024 at 17:24):

I think a good goal would be to prove that lemma for just DualNumbers, then work out the generalizatoin when you have the proof

Frederick Pu (Apr 12 2024 at 17:24):

Yeah, but I'm gonna need the fact that the geometric sequence is summable in the first place. Which is some metric space stuff

Eric Wieser (Apr 12 2024 at 17:25):

We _do_ have a metric space on the dual numbers

Frederick Pu (Apr 12 2024 at 17:25):

should be fine then

Frederick Pu (Apr 12 2024 at 17:26):

Do u think I need anymore api stuff on TrivEqZeroExt inorder to get started?

Eric Wieser (Apr 12 2024 at 17:29):

I think it would be great to polish the PR on Inv and DIv first; then embark on that larger goal

Frederick Pu (Apr 12 2024 at 17:29):

Ok, should I edit my actual pull request comment?

Frederick Pu (Apr 12 2024 at 17:30):

also did you see my latest pull request, I proved all the lemmas u asked (except for 1/eps because I can't find that in Triv)

Eric Wieser (Apr 12 2024 at 17:32):

No, I didn't! looking at #12075 now

Frederick Pu (Apr 12 2024 at 17:36):

theorem summable_iff_vanishing_norm{ι : Type u_1} {E : Type u_3} [SeminormedAddCommGroup E] [CompleteSpace E] {f : ι  E} :
Summable f   ε > 0,  (s : Finset ι),  (t : Finset ι), Disjoint t s  Finset.sum t fun (i : ι) => f i < ε

just so i remember

Eric Wieser (Apr 12 2024 at 17:59):

Frederick Pu said:

also did you see my latest pull request, I proved all the lemmas u asked (except for 1/eps because I can't find that in Triv)

That would go in the DualNumber.lean file; it's fine to edit multiple files in the same PR if the changes are closely related.

Antoine Chambert-Loir (Apr 13 2024 at 07:12):

Frederick Pu said:

how can they have the exact same name?

In Mathlib, the docs#Module structure just adds the scalar action of R on M and how it interacts with addition. The interaction with negation, if there is some negation on M by way of a docs#AddCommGroup structure on M, the interaction of scalar multiplication with neg or subtraction comes for free.

Frederick Pu (Apr 13 2024 at 15:37):

Can anyone explain why tsum_mul_left isn't solvling this goal?

import Mathlib.Algebra.DualNumber
import Mathlib.Topology.Algebra.InfiniteSum.Ring

example {R : Type*} [DivisionRing R] (p : DualNumber R) [TopologicalSpace (DualNumber R)] [T2Space (DualNumber R)] (f : Nat  DualNumber R):
  ∑' (i : Nat), p^i = 1 + p * ∑' (x : Nat), f x := by
{
  have : ∑' (x : Nat), p * f x = p * ∑' (x : Nat), f x := tsum_mul_left
}
#check tsum_mul_left

Frederick Pu (Apr 13 2024 at 15:43):

Frederick Pu said:

Can anyone explain why tsum_mul_left isn't solvling this goal?

import Mathlib.Algebra.DualNumber
import Mathlib.Topology.Algebra.InfiniteSum.Ring

example {R : Type*} [DivisionRing R] (p : DualNumber R) [TopologicalSpace (DualNumber R)] [T2Space (DualNumber R)] (f : Nat  DualNumber R):
  ∑' (i : Nat), p^i = 1 + p * ∑' (x : Nat), f x := by
{
  have : ∑' (x : Nat), p * f x = p * ∑' (x : Nat), f x := tsum_mul_left
}
#check tsum_mul_left

Oh my bad, DualNumbers arent a DivisionRing. Seem like we need to basically redo a lot of the tsum lemmas

Frederick Pu (Apr 13 2024 at 15:48):

Actually Summable.tsum_mul_left seems fine

Eric Wieser (Apr 14 2024 at 18:37):

Note hat instead of assuming TopologicalSpace (DualNumber R) you should import the TrivSqZeroExt file in analysis

Eric Wieser (Apr 14 2024 at 18:38):

@loogle NormedSpace, TrivSqZeroExt

loogle (Apr 14 2024 at 18:38):

:search: TrivSqZeroExt.instL1NormedSpace, TrivSqZeroExt.instL1NormedAlgebra

Kevin Buzzard (Apr 14 2024 at 19:54):

Eric Wieser said:

Note hat instead of assuming TopologicalSpace (DualNumber R) you should import the TrivSqZeroExt file in analysis

Just to be clear here -- Eric is saying that writing [TopologicalSpace (DualNumber R)] is mathematically wrong, because it means "put a completely arbitrary topology on the dual numbers which is completely unrelated to the algebraic structure".

Eric Wieser (Apr 14 2024 at 20:13):

I guess you can fix "completely unrelated"by adding [TopologicalRing (DualNumber R)], but that's still probably "related but not in the ways you would expect"

Frederick Pu (Apr 14 2024 at 20:44):

yeah I noticed that the typeclasses required for tsum_left_mul and summable_of_vanishing_norm seem to really not like eachother for some reason

Eric Wieser (Apr 14 2024 at 20:46):

Can you show what you wrote?

Eric Wieser (Apr 14 2024 at 20:46):

This sounds a bit like "Semiring and AddCommGroup don't like each other", for which the answer is "of course not, that has two different +s; use Ring instead"

Frederick Pu (Apr 14 2024 at 20:48):

Screenshot-2024-04-14-164702.png
Screenshot-2024-04-14-164719.png

Eric Wieser (Apr 14 2024 at 20:48):

Please paste code (as a #mwe) not images!

Frederick Pu (Apr 14 2024 at 20:50):

theorem bruh.{u_3, u_1} {ι : Type u_1} {R : Type u_3} [SeminormedAddCommGroup (DualNumber R)]
  [CompleteSpace (DualNumber R)] {f : ι  (DualNumber R)} (x : DualNumber R): Summable (fun i : Nat => x) := by
{
/--
ι : Type u_1
R : Type u_3
inst✝¹ : SeminormedAddCommGroup (DualNumber R)
inst✝ : CompleteSpace (DualNumber R)
f : ι → DualNumber R
x : DualNumber R
⊢ ∀ ε > 0, ∃ s, ∀ (t : Finset ℕ), Disjoint t s → ‖Finset.sum t fun i ↦ x‖ < ε
--/
  rw [summable_iff_vanishing_norm]
}

works but

theorem bruh.{u_3, u_1} {ι : Type u_1} {R : Type u_3} [SeminormedAddCommGroup (DualNumber R)]

  [CompleteSpace (DualNumber R)] [Ring (DualNumber R)] {f : ι  (DualNumber R)} (x : DualNumber R): Summable (fun i : Nat => x) := by

{
/ --
tactic 'rewrite' failed, did not find instance of the pattern in the target expression
  Summable ?m.9232
--/
  rw [summable_iff_vanishing_norm]

}

doesn't

Frederick Pu (Apr 14 2024 at 20:50):

so adding [Ring (DualNumber R)] breaks the type inference

Ruben Van de Velde (Apr 14 2024 at 20:51):

Please read #mwe

Ruben Van de Velde (Apr 14 2024 at 20:51):

And you should never have a [Ring (Concrete type)] argument

Frederick Pu (Apr 14 2024 at 20:57):

okay, let's go back to this example then:

import Mathlib.Algebra.DualNumber
import Mathlib.Topology.Algebra.InfiniteSum.Ring
import Mathlib.Analysis.Normed.Group.InfiniteSum

theorem extracted_1.{u_1} {R : Type u_1} [inst : DivisionRing R] [inst_1 : TopologicalSpace (DualNumber R)]
    [inst_2 : TopologicalSemiring (DualNumber R)] (p : DualNumber R) (h : Summable fun i  p ^ i)
    [inst_3 : T2Space (DualNumber R)] : ∑' (i : ), p ^ i = 1 + p * ∑' (x : ), p ^ x := sorry

Frederick Pu (Apr 14 2024 at 20:58):

I think we need to be able to infer TopologicalSpace (DualNumber R) from TopologicalSpace R

Frederick Pu (Apr 14 2024 at 20:59):

Shouldn't this be from the product topology?

Eric Wieser (Apr 14 2024 at 21:05):

Like I said above, you're missing an import

Kevin Buzzard (Apr 14 2024 at 21:14):

I have a mathematical question. You seem to want to put a topology on the dual numbers. What topology do you want to put on it?

Eric Wieser (Apr 14 2024 at 21:19):

You also seem to want a norm (from an earlier message); what norm do you want?

Frederick Pu (Apr 14 2024 at 21:19):

The topology for R^2, since we want to treat it like a normed vector space

Eric Wieser (Apr 14 2024 at 21:21):

@loogle TrivSqZeroExt, TopologicalSpace

loogle (Apr 14 2024 at 21:21):

:search: TrivSqZeroExt.instTopologicalSpace, TrivSqZeroExt.continuous_fst, and 44 more

Eric Wieser (Apr 14 2024 at 21:21):

That is the topology that matches R²; but you have to import that file for Lean to find it automatically

Frederick Pu (Apr 14 2024 at 21:25):

TrivSqZeroExt.instL1NormedAddCommGroup

Frederick Pu (Apr 14 2024 at 21:26):

I think that's pretty good, also matches the signature of our inverse lemmas

Kevin Buzzard (Apr 14 2024 at 21:43):

So I asked you which topology, and you replied "I have a specific topology in mind", and that's why stuff like [inst_1 : TopologicalSpace (DualNumber R)] must be wrong, because there you're saying "put an arbitrary topology on it" (you can see it must be wrong becuase there is no mention of the topology you want). And I don't understand your answer -- R is just a random division ring. What is "the topology for R^2"?

Frederick Pu (Apr 14 2024 at 23:11):

Those instances were just to test the lemmas I was using. I think I'm gonna have R be topological ring and then take the the product topology

Kevin Buzzard (Apr 14 2024 at 23:21):

I guess I am a bit confused about what you're trying to achieve at this point.

Frederick Pu (Apr 14 2024 at 23:33):

That the theorem for geometric series applies for DualNumbers. that is:
1 + p + p^2 + p^3 +.... = 1/(1 - p) for $p.snd \neq 0$

Kevin Buzzard (Apr 15 2024 at 06:07):

That's not true -- for example it's not true if p=1+eps or if p=37+eps.

Frederick Pu (Apr 15 2024 at 15:29):

I think you need the additional condition of ||p|| < 1

Frederick Pu (Apr 15 2024 at 15:34):

Basically I'm trying have the geo_normed_field thing work for rings with units

Jireh Loreaux (Apr 15 2024 at 16:46):

IIRC @Eric Wieser had some ideas about generalizing this to certain topological rings, but maybe I'm misremembering and it was about exp instead.

Eric Wieser (Apr 15 2024 at 17:18):

What's a "geo_normed_field"?

Eric Wieser (Apr 15 2024 at 20:35):

@Frederick Pu , are you looking for docs#NormedRing.tsum_geometric_of_norm_lt_one ?

Eric Wieser (Apr 15 2024 at 20:35):

Ah no, that's not the statement I expected

Frederick Pu (Apr 15 2024 at 20:52):

theorem tsum_geometric_of_norm_lt_one{K : Type u_4} [NormedField K] {ξ : K} (h : ξ < 1) :
∑' (n : ), ξ ^ n = (1 - ξ)⁻¹

Frederick Pu (Apr 15 2024 at 20:53):

theorem geom_series_mul_neg {R : Type u_4} [NormedRing R] [CompleteSpace R] (x : R) (h : x < 1) :
(∑' (i : ), x ^ i) * (1 - x) = 1

Frederick Pu (Apr 15 2024 at 20:53):

the second one should be easy to use for dualnumbers

Eric Wieser (Apr 15 2024 at 21:02):

I made #12164 which generalizes the first lemma to DivisionRing, but indeed that doesn't help you here

Frederick Pu (Apr 15 2024 at 21:16):

Here's the minimum you need for it to work:

import Mathlib.Algebra.DualNumber
import Mathlib.Analysis.NormedSpace.TrivSqZeroExt
import Mathlib.Analysis.SpecificLimits.Normed

example {R : Type*} [NormedRing R] [CompleteSpace R] (x : DualNumber R) (h : x < 1) :
  (∑' (i : ), x ^ i) * (1 - x) = 1 :=
  geom_series_mul_neg x h

Frederick Pu (Apr 15 2024 at 21:16):

i think u get NormedRing (DualNumber R) and CompleteSpace (DualNumber R) for free because of products or smth

Eric Wieser (Apr 15 2024 at 21:24):

Mathlib indeed has both of those instances already

Eric Wieser (Apr 15 2024 at 21:25):

(You get it for free because I contributed it to mathlib as a very small part of my PhD!)

Frederick Pu (Apr 15 2024 at 21:26):

theorem geom_series_of_fst_ne_zero {R : Type*} [NormedDivisionRing R] [CompleteSpace R] (x : DualNumber R) (h : x < 1) (h1 : x.fst  1) :
    (∑' (i : ), x ^ i) = (1 - x : DualNumber R)⁻¹ := by
  have := geom_series_mul_neg x h
  have w : ((∑' (i : ), x ^ i) * (1 - x)) * (1 - x)⁻¹ = (1 - x)⁻¹ := by
    rw [this, one_mul]
  rw [ w, mul_assoc, TrivSqZeroExt.mul_inv_cancel, mul_one]

  rw [TrivSqZeroExt.fst_sub]
  exact sub_ne_zero_of_ne h1.symm

Eric Wieser (Apr 15 2024 at 21:27):

Are you sure you need ‖x‖ < 1? Is ‖x.fst‖ < 1 enough?

Frederick Pu (Apr 15 2024 at 21:28):

isnt ||a + bε|| = sqrt(a^2 + b^2)

Eric Wieser (Apr 15 2024 at 21:34):

The one in mathlib is ‖a + bε‖ = ‖a‖ + ‖b‖

Frederick Pu (Apr 15 2024 at 21:35):

then how is ||x.fst|| < 1 enough?

Frederick Pu (Apr 15 2024 at 21:35):

intuitively i don't think you can just ignore the derivative component

Eric Wieser (Apr 15 2024 at 21:37):

The derivative component is n*x.fst^(n-1)* x.snd (at least, in the commutative case), which should converge irrespective of the value of x.snd

Frederick Pu (Apr 15 2024 at 21:38):

yee that makes sense

Eric Wieser (Apr 15 2024 at 21:39):

Frederick Pu said:

theorem geom_series_mul_neg {R : Type u_4} [NormedRing R] [CompleteSpace R] (x : R) (h : x < 1) :
(∑' (i : ), x ^ i) * (1 - x) = 1

So this won't actually help for that stronger result; but it would be great to prove it anyway

Frederick Pu (Apr 15 2024 at 21:40):

Eric Wieser said:

Frederick Pu said:

theorem geom_series_mul_neg {R : Type u_4} [NormedRing R] [CompleteSpace R] (x : R) (h : x < 1) :
(∑' (i : ), x ^ i) * (1 - x) = 1

So this won't actually help for that stronger result; but it would be great to prove it anyway

wdym. That's already in mahthlib

Eric Wieser (Apr 15 2024 at 21:41):

Oh! Usually people write docs#geom_series_mul_neg (which creates an automatic link) to talk about things that already exist

Frederick Pu (Apr 15 2024 at 21:42):

sorry I didn't know

Eric Wieser (Apr 15 2024 at 21:43):

No worries, good job on finding it

Frederick Pu (Apr 15 2024 at 21:43):

I think this lemma is missing from DualNumber.lean:

example {R : Type*} [Ring R] (x : DualNumber R) (n : Nat) :
    x^n = inl (x.fst ^ n) + inr (n * x.fst ^ (n - 1) * x.snd) := by
  sorry

Frederick Pu (Apr 15 2024 at 21:44):

is it in TrivSqZeroExt?

Eric Wieser (Apr 15 2024 at 21:44):

I think generally the API tries to avoid writing lemmas like that right now

Eric Wieser (Apr 15 2024 at 21:45):

Instead it has docs#TrivSqZeroExt.fst_pow and docs#TrivSqZeroExt.snd_pow

Eric Wieser (Apr 15 2024 at 21:45):

The expectation is that if you're going to split it into components, you want to handle them separately rather than double the number of terms in the expression

Frederick Pu (Apr 15 2024 at 21:47):

so is there tsum x = inl (tsum.fst) + inr (tsum.snd)

Eric Wieser (Apr 15 2024 at 21:48):

No, but there is docs#TrivSqZeroExt.fst_tsum

Eric Wieser (Apr 15 2024 at 21:48):

... or not

Eric Wieser (Apr 15 2024 at 21:49):

I guess I only added docs#TrivSqZeroExt.hasSum_fst

Frederick Pu (Apr 15 2024 at 21:49):

also on a side note, can loogle search based on doc comments? seems like that would make it a lot easier to find stuff

Eric Wieser (Apr 15 2024 at 21:50):

Frederick Pu said:

so is there tsum x = inl (tsum.fst) + inr (tsum.snd)

This is false, because if only the fst part converges the LHS is 0 and the rhs is inl (tsum _)

Eric Wieser (Apr 15 2024 at 21:50):

Eric Wieser said:

No, but there is docs#TrivSqZeroExt.fst_tsum

This would be false for the same reason

Frederick Pu (Apr 15 2024 at 21:51):

the thing is those go in the wrong direction. We need to show if fst and snd converge than the sequence converges

Eric Wieser (Apr 15 2024 at 21:53):

The secret is that you rarely want to show "the sequence converges"; "the sequence converges to x" is much more interesting, and this is what docs#HasSum means

Eric Wieser (Apr 15 2024 at 21:54):

I think you want (TrivSqZeroExt.hasSum_inl _).add (TrivSqZeroExt.hasSum_inr _)

Eric Wieser (Apr 15 2024 at 21:55):

I guess it's probably reasonable to add something like HasSum (fun x => (f x).fst) a.fst -> HasSum (fun x => (f x).snd) a.snd -> HasSum f a

Eric Wieser (Apr 15 2024 at 21:56):

Which should follow fairly immediately from my .add message above.

Eric Wieser (Apr 15 2024 at 21:56):

It's probably even true as an Iff

Eric Wieser (Apr 15 2024 at 21:57):

There's a lot missing here because I developed just as much as I needed for docs#TrivSqZeroExt.fst_exp (and the rest of that file) and little else.

Frederick Pu (Apr 15 2024 at 22:05):

what about something like this:

theorem hasSum_inl_inr (f g : Nat  ) (a b : ) : HasSum f a  HasSum g b  (HasSum (fun n => (inl (f n) + inr (g n) : (DualNumber ))) (inl a + inr b : DualNumber )) := by
{
  intro hf hg
  apply HasSum.add
  apply TrivSqZeroExt.hasSum_inl
  exact hf
  apply TrivSqZeroExt.hasSum_inr
  exact hg
}

Eric Wieser (Apr 15 2024 at 22:06):

For this type of thing it's often more useful to have the free variable in the conclusion

Frederick Pu (Apr 15 2024 at 22:06):

lean seems to get really confused when u tryy to use hasSum_inl directly

Eric Wieser (Apr 15 2024 at 22:06):

(TrivSqZeroExt.hasSum_inl _ hf).add (TrivSqZeroExt.hasSum_inr _ hg) should work for that?

Frederick Pu (Apr 15 2024 at 22:07):

it doesnt

Eric Wieser (Apr 15 2024 at 22:09):

Edited: see if you can see how I worked out the fix from the error message

Frederick Pu (Apr 15 2024 at 22:09):

oh the extra _

Frederick Pu (Apr 15 2024 at 22:10):

but why tho, the lemma only takes 1 input

Notification Bot (Apr 15 2024 at 22:11):

This topic was moved here from #general > Is there any code or division of DualNumbers? by Eric Wieser.

Eric Wieser (Apr 15 2024 at 22:12):

Frederick Pu said:

but why tho, the lemma only takes 1 input

What makes you say that?

Frederick Pu (Apr 15 2024 at 22:13):

theorem hasSum_inr [AddCommMonoid R] [AddCommMonoid M] {f : α  M} {a : M} (h : HasSum f a)

Frederick Pu (Apr 15 2024 at 22:13):

only 1 non implicit argument right?

Eric Wieser (Apr 15 2024 at 22:13):

Nope, there's a variable line higher up that adds more

Eric Wieser (Apr 15 2024 at 22:13):

You can read off the variables by hovering over hasSum_inr and reading the tooltip instead of the source

Frederick Pu (Apr 16 2024 at 02:03):

I feel like in this case it's better to prove that the sequence converges and then get the value this converges to afterward. Since evaluating the sum of i * x^{i - 1} is very nasty

Kevin Buzzard (Apr 16 2024 at 05:57):

It's just the derivative of the sum of x^i which is 1/(1-x)

Frederick Pu (Apr 16 2024 at 14:15):

Yeah but the whole point of using dual numbers was to bypass using derivatives

Kevin Buzzard (Apr 16 2024 at 15:52):

Another approach is just to multiply by (1-x)^2 and observe that a miracle occurs

Frederick Pu (Apr 16 2024 at 20:38):

But wouldn't that trick still require you to assume convergence in the first place?

Frederick Pu (Apr 16 2024 at 20:39):

The only trick like that I know is from kumon where you multiply by x, and when u subtract the two sequences you get a geoemtric sequence or smth

Frederick Pu (Apr 16 2024 at 20:39):

anyhow I'm stuck with this chonker for now that I'll have to golf later

example (x : DualNumber ) (x : DualNumber ) (hx1 : |x.fst| < 1) (hx2 : x.fst  0):
  Summable (fun i : Nat => x^i) := by
{
  have : (fun i : Nat => x^i) = (fun i : Nat => (inl (x.fst ^ i) + inr ((i:) * x.fst ^ (i.pred) * x.snd))) := by
    ext i
    · rw [fst_pow, fst_add, fst_inl, fst_inr, add_zero]

    · rw [snd_pow, snd_add, snd_inl, snd_inr, zero_add,  smul_assoc, smul_eq_mul, nsmul_eq_mul]
  rw [this]
  apply Summable.add
  suffices h :  Summable (fun b => x.fst ^ b) by {
    match h with
    | t, ht => {
      use (inl t)
      exact TrivSqZeroExt.hasSum_inl _ ht
    }
  }
  rw [summable_geometric_iff_norm_lt_one]
  exact hx1

  suffices h :  Summable (fun b : Nat => (b:) * fst x ^ Nat.pred b * snd x) by {
    match h with
    | t, ht => {
      use (inr t)
      exact TrivSqZeroExt.hasSum_inr _ ht
    }
  }
  apply Summable.mul_right
  -- apply summable_of_ratio_test_tendsto_lt_one _
  -- sorry
  have : Filter.Tendsto (fun n  ‖↑(n + 1) * fst x ^ Nat.pred (n + 1) / ‖↑n * fst x ^ Nat.pred n) Filter.atTop (nhds x.fst) := by {
    have : Filter.EventuallyEq (Filter.atTop) (fun n:Nat  (n + 1 : ) / n * x.fst) (fun n => ‖↑(n + 1) * fst x ^ Nat.pred (n + 1) / ‖↑n * x.fst ^ (n.pred)) := by {
      rw [Filter.EventuallyEq, Filter.eventually_atTop]
      use 1
      intro b hb
      cases h : b with
      | zero => {
        linarith
      }
      | succ b => {
        simp
        have : |(b + 1 : )| * |fst x| ^ b  0 := by {
          apply mul_ne_zero
          rw [h] at hb
          simp only [ne_eq, abs_eq_zero]
          intro _
          linarith

          rw [ne_eq, pow_eq_zero_iff', abs_eq_zero]
          tauto
        }
        field_simp
        ring
      }
    }
    rw [Filter.tendsto_congr' this.symm]
    {
      have : Filter.Tendsto (fun n:Nat  ((n + 1 : Nat) : ) / n) Filter.atTop (nhds (1:)) := by {
        have : (fun n:Nat  ((n + 1 : Nat) : ) / n) =ᶠ[Filter.atTop] (fun n:Nat  1 + (n:)⁻¹) := by {
          rw [Filter.EventuallyEq, Filter.eventually_atTop]
          use 1
          intro b hb
          have : b  0 := by linarith
          rw [Real.norm_eq_abs, abs_of_pos]
          field_simp
          apply div_pos
          push_cast
          linarith
          have : (1:Nat)  (b : ) := by
            rw [Nat.cast_le]
            exact hb
          push_cast at this
          linarith
        }
        rw [Filter.tendsto_congr' this]

        have crux1 : Filter.Tendsto (fun n : Nat  (1 : )) Filter.atTop (nhds 1) :=
          tendsto_const_nhds
        have crux2 : Filter.Tendsto (fun n : Nat  (n:)⁻¹) Filter.atTop (nhds 0) :=
          tendsto_inverse_atTop_nhds_zero_nat
        have := Filter.Tendsto.add crux1 crux2
        rw [add_zero] at this
        exact this
      }
      have := Filter.Tendsto.mul_const (fst x) this
      push_cast at this
      rw [one_mul] at this
      exact this
    }
  }

  exact summable_of_ratio_test_tendsto_lt_one hx1 (by {
    rw [Filter.eventually_atTop]
    use 1
    intro b hb
    cases b with
    | zero => simp at hb
    | succ b => {
      simp
      intro h
      cases h with
      | inl l => linarith
      | inr r => exact hx2 r.left
    }
  }) this

}

Frederick Pu (Apr 16 2024 at 21:06):

Here's the golfed version:

theorem wow (x : DualNumber ) (hx : x.fst  0) :
      Filter.Tendsto (fun n  ‖↑(n + 1) * fst x ^ Nat.pred (n + 1) / ‖↑n * fst x ^ Nat.pred n) Filter.atTop (nhds x.fst) := by
  have : Filter.EventuallyEq (Filter.atTop) (fun n:Nat  (n + 1 : ) / n * x.fst) (fun n => ‖↑(n + 1) * fst x ^ Nat.pred (n + 1) / ‖↑n * x.fst ^ (n.pred)) := by
    rw [Filter.EventuallyEq, Filter.eventually_atTop]
    use 1
    intro b hb
    cases h : b with
    | zero => linarith
    | succ b =>
      simp
      have : |(b + 1 : )| * |fst x| ^ b  0 := by
        apply mul_ne_zero
        rw [h] at hb; simp only [ne_eq, abs_eq_zero]; linarith
        rw [ne_eq, pow_eq_zero_iff', abs_eq_zero]; tauto
      field_simp
      ring
  rw [Filter.tendsto_congr' this.symm]
  have : Filter.Tendsto (fun n:Nat  ((n + 1 : Nat) : ) / n) Filter.atTop (nhds (1:)) := by
    have : (fun n:Nat  ((n + 1 : Nat) : ) / n) =ᶠ[Filter.atTop] (fun n:Nat  1 + (n:)⁻¹) := by
      rw [Filter.EventuallyEq, Filter.eventually_atTop]
      use 1
      intro b hb
      rw [Real.norm_eq_abs, abs_of_pos]
      field_simp [show b  0 by linarith]
      exact div_pos (by push_cast; linarith) (by linarith [show (b : )  1 by exact Nat.one_le_cast.mpr hb])
    rw [Filter.tendsto_congr' this]

    have crux1 : Filter.Tendsto (fun n : Nat  (1 : )) Filter.atTop (nhds 1) :=
      tendsto_const_nhds
    have crux2 : Filter.Tendsto (fun n : Nat  (n:)⁻¹) Filter.atTop (nhds 0) :=
      tendsto_inverse_atTop_nhds_zero_nat
    have := Filter.Tendsto.add crux1 crux2
    rw [add_zero] at this
    exact this
  have := Filter.Tendsto.mul_const (fst x) this
  push_cast at this
  rw [one_mul] at this
  exact this

example (x : DualNumber ) (hx1 : |x.fst| < 1) (hx2 : x.fst  0):
      Summable (fun i : Nat => x^i) := by
  have : (fun i : Nat => x^i) = (fun i : Nat => (inl (x.fst ^ i) + inr ((i:) * x.fst ^ (i.pred) * x.snd))) := by
    ext i
    · rw [fst_pow, fst_add, fst_inl, fst_inr, add_zero]
    · rw [snd_pow, snd_add, snd_inl, snd_inr, zero_add,  smul_assoc, smul_eq_mul, nsmul_eq_mul]
  rw [this]
  apply Summable.add
  suffices h :  Summable (fun b => x.fst ^ b) by
    match h with
    | t, ht =>
      use (inl t)
      exact TrivSqZeroExt.hasSum_inl _ ht
  rw [summable_geometric_iff_norm_lt_one]
  exact hx1

  suffices h :  Summable (fun b : Nat => (b:) * fst x ^ Nat.pred b * snd x) by
    match h with
    | t, ht =>
      use (inr t)
      exact TrivSqZeroExt.hasSum_inr _ ht

  exact Summable.mul_right x.snd <|
   summable_of_ratio_test_tendsto_lt_one hx1 (by {
    rw [Filter.eventually_atTop]
    use 1
    intro b hb
    cases b with
    | zero => simp at hb
    | succ b => {
      simp
      intro h
      cases h with
      | inl l => linarith
      | inr r => exact hx2 r.left
    }
  }) (wow x hx2)

wow just prooves that u can atlually use ratio test

Frederick Pu (Apr 16 2024 at 21:36):

also smth like this should take us home

example  {R : Type*} [inst : NormedRing R] [inst_1 : CompleteSpace R] (x : R) :
  Summable (fun i  x ^ i)  (∑' (i : ), x ^ i) * (1 - x) = 1 := by {
    intro this
    have := this.hasSum.mul_right (1 - x)
    refine' tendsto_nhds_unique this.tendsto_sum_nat _
    have : Filter.Tendsto (fun n :   1 - x ^ n) Filter.atTop (nhds 1) := by
      simpa using tendsto_const_nhds.sub (show Filter.Tendsto (fun n  x ^ n) Filter.atTop (nhds 0) by sorry)
    convert this
    rw [ geom_sum_mul_neg, Finset.sum_mul]
  }

Eric Wieser (Apr 16 2024 at 21:57):

I think that last one is true much more generally, it doesn't need a norm at all

Frederick Pu (Apr 16 2024 at 22:00):

Can you have tsum without norm

Eric Wieser (Apr 16 2024 at 22:01):

Yes, T2Space and TopologicalAddGroup is enough

Frederick Pu (Apr 16 2024 at 22:06):

theorem womp  {R : Type*} [TopologicalSpace R] [Ring R] [inst : TopologicalRing R] [T2Space R] (x : R) :
  Summable (fun i  x ^ i)  Filter.Tendsto (fun n  x ^ n) Filter.atTop (nhds 0)   (∑' (i : ), x ^ i) * (1 - x) = 1 := by {
    intro h1 h2
    have := h1.hasSum.mul_right (1 - x)
    refine' tendsto_nhds_unique this.tendsto_sum_nat _
    have : Filter.Tendsto (fun n :   1 - x ^ n) Filter.atTop (nhds 1) := by
      simpa using tendsto_const_nhds.sub h2
    convert this
    rw [ geom_sum_mul_neg, Finset.sum_mul]
  }

Frederick Pu (Apr 16 2024 at 22:10):

here's a rough sketch of the final proof:

example (x : DualNumber ) (hx1 : |x.fst| < 1) (hx2 : x.fst  0):
  (∑' (i : ), x ^ i) * (1 - x) = 1 := by {
    apply womp
    exact summable_geom_dual_real x hx1 hx2
    have : (fun i : Nat => x^i) = (fun i : Nat => (inl (x.fst ^ i) + inr ((i:) * x.fst ^ (i.pred) * x.snd))) := by
      ext i
      · rw [fst_pow, fst_add, fst_inl, fst_inr, add_zero]
      · rw [snd_pow, snd_add, snd_inl, snd_inr, zero_add,  smul_assoc, smul_eq_mul, nsmul_eq_mul]
    rw [this]
    rw [show (0:DualNumber ) = inl 0 + inr 0 by simp]
    apply Filter.Tendsto.add
    {
      apply Filter.Tendsto.comp (continuous_inl.tendsto 0)
      exact tendsto_pow_atTop_nhds_zero_of_norm_lt_one hx1
    }
    {
      apply Filter.Tendsto.comp (continuous_inr.tendsto 0)
      rw [show 0 = 0 * x.snd by sorry]
      apply Filter.Tendsto.mul_const
      suffices Filter.Tendsto (fun k:Nat  k * fst x ^ k) Filter.atTop (nhds 0) by sorry
      exact tendsto_self_mul_const_pow_of_abs_lt_one hx1
    }

  }

Eric Wieser (Apr 16 2024 at 22:12):

Here's womp with even fewer assumptions:

theorem Summable.hasSum_geom_sries_mul_sub
    {R : Type*} [TopologicalSpace R] [Ring R] [TopologicalRing R]
    (x : R) (hx : Summable (x ^ ·)) :
    HasSum (fun i => x ^ i * (1 - x)) 1 := by
  obtain a, hx := hx
  have hx' := hx
  rw [ hasSum_nat_add_iff' 1, Finset.sum_range_one, pow_zero] at hx'
  simp_rw [mul_sub, mul_one, pow_succ]
  simpa using hx.sub hx'

Eric Wieser (Apr 16 2024 at 22:13):

(you can use HasSum.tsum_eq to get the tsum version)

Frederick Pu (Apr 16 2024 at 22:29):

theorem Summable.hasSum_geom_sries_mul_sub

    {R : Type*} [TopologicalSpace R] [Ring R] [TopologicalRing R]

    (x : R) (hx : Summable (x ^ ·)) :

    HasSum (fun i => x ^ i * (1 - x)) 1 := by

  obtain a, hx := hx

  have hx' := hx

  rw [ hasSum_nat_add_iff' 1, Finset.sum_range_one, pow_zero] at hx'

  simp_rw [mul_sub, mul_one, pow_succ]

  simpa using hx.sub hx'

theorem womp  {R : Type*} [TopologicalSpace R] [Ring R] [inst : TopologicalRing R] [T2Space R] (x : R) :

  Summable (fun i  x ^ i)    (∑' (i : ), x ^ i) * (1 - x) = 1 := by {

    intro h1

    have := h1.hasSum.mul_right (1 - x)

    have :   ∑' (i : ), (x ^ i * (1 - x))  = (∑' (i : ), x ^ i) * (1 - x) := by sorry -- tsum_mul_right

    rw [ this]

    exact HasSum.tsum_eq <| Summable.hasSum_geom_sries_mul_sub x h1

  }

example (x : DualNumber ) (hx1 : |x.fst| < 1) (hx2 : x.fst  0):

      (∑' (i : ), x ^ i) * (1 - x) = 1 :=

  womp x <| summable_geom_dual_real x hx1 hx2

Mitchell Lee (Apr 17 2024 at 05:10):

You can show the summability by using docs#hasSum_coe_mul_geometric_of_norm_lt_one

Eric Wieser (Apr 17 2024 at 06:28):

We started with that but the side z-condition is too strong I think?

Kevin Buzzard (Apr 17 2024 at 06:36):

Right, nilpotent things should have norm infinitesimally small (ie however big the value of r is, r * epsilon should have norm less than 1)

Eric Wieser (Apr 17 2024 at 06:39):

That's not possible with our signature for norms, right? The closest we could do is set the norm to zero, but then we don't have a t2 space and our sums don't converge to a single value

Kevin Buzzard (Apr 17 2024 at 06:48):

Yes that's right, this is a higher rank valuation, not a rank one (aka real-valued) valuation (aka norm).

Kevin Buzzard (Apr 17 2024 at 06:50):

I don't even know if it works in the Archimedean case to be honest! In my examples the underlying norm on the base ring R is nonarchimedean and then the extension to infinitesimals is untroublesome

Mitchell Lee (Apr 17 2024 at 07:20):

Eric Wieser said:

We started with that but the side z-condition is too strong I think?

What does that mean?

I am just pointing out that it seems Frederick was using the ratio test to prove the convergence of a certain series of real numbers, when the convergence of that series (and its value) is already in mathlib.

Mitchell Lee (Apr 17 2024 at 08:08):

Kevin Buzzard said:

Yes that's right, this is a higher rank valuation, not a rank one (aka real-valued) valuation (aka norm).

If you put a topology on R[ϵ]/ϵ2\mathbb{R}[\epsilon]/\epsilon^2 using this higher rank norm, wouldn't that make Rϵ\mathbb{R}\epsilon open? Then it would be difficult for anything to converge.

Antoine Chambert-Loir (Apr 17 2024 at 11:16):

Kevin Buzzard said:

Right, nilpotent things should have norm infinitesimally small (ie however big the value of r is, r * epsilon should have norm less than 1)

Why should they? Nilpotent operators usually don't have a zero operator norm.

Kevin Buzzard (Apr 17 2024 at 11:31):

They do for the supremum seminorm on an affinoid

Kevin Buzzard (Apr 17 2024 at 11:32):

But actually I'm confused about this for two reasons -- first that the reals aren't nonarchimedean and secondly that valuations are supposed to be multiplicative

Frederick Pu (Apr 17 2024 at 15:16):

The dual numbers have L_p norm, so both the real and derivative components are equally important. The thing is that (a + b\e) ^n = a^n + a^(n-1)b\e. So you can consider the sums seperately.

Mitchell Lee (Apr 17 2024 at 15:40):

Kevin Buzzard said:

But actually I'm confused about this for two reasons -- first that the reals aren't nonarchimedean and secondly that valuations are supposed to be multiplicative

It seems that in mathlib, the norm of a normed ring is only required to be submultiplicative. (docs#NormedRing) The definition of a normed field requires the norm to be (exactly) multiplicative, though. (docs#NormedField)

It wouldn't be possible to put an (exactly) multiplicative norm on the dual numbers, because they are not a domain.

Mitchell Lee (Apr 17 2024 at 16:21):

Also, it is possible I am misunderstanding something, but I don't think it is desirable for ϵ\|\epsilon\| to be infinitesimal. If it were, then the sequence 1,12,13,1, \frac{1}{2}, \frac{1}{3}, \ldots wouldn't converge, because it never comes within ϵ\|\epsilon\| of 00. So the inclusion RR[ϵ]/ϵ2\mathbb{R} \to \mathbb{R}[\epsilon]/\epsilon^2 would not be continuous. This is a problem even if R\mathbb{R} is replaced by a nonarchimedean ring.

I think the coefficientwise product topology on R[ϵ]/ϵ2\mathbb{R}[\epsilon]/\epsilon^2 is the "correct" one.

Antoine Chambert-Loir (Apr 17 2024 at 21:01):

If R[ε]/(ε2)\mathbf R[\varepsilon]/(\varepsilon^2) is endowed with the 1\ell^1-norm, one gets a normed algebra structure ((x+yε)(x+yε)=xx+(xy+xy)ε(x+y\varepsilon)(x'+y'\varepsilon)=xx'+(xy'+x'y)\varepsilon has norm xx+xy+xy(x+y)(x+y)|xx'|+|xy'+x'y| \leq (|x|+|y|)(|x'|+|y'|)), and the geometric series (x+yε)n\sum (x+y\varepsilon)^n is summable provided the (necessary) condition x<1|x|<1 holds.

Eric Wieser (Apr 17 2024 at 22:20):

That normed algebra structure is in mathlib

Frederick Pu (Apr 17 2024 at 23:42):

yeah... how does lean know which norm to inherit?

Eric Wieser (Apr 17 2024 at 23:44):

Lean just finds the only norm that mathlib provides, which for dual numbers is the L1 norm


Last updated: May 02 2025 at 03:31 UTC