Zulip Chat Archive

Stream: maths

Topic: partial derivatives


Kenny Lau (Jul 12 2019 at 14:42):

namespace mv_polynomial

variables {σ : Type u} [decidable_eq σ]
variables {α : Type v} [comm_semiring α] [decidable_eq α]
variables (i j : σ) (p q : mv_polynomial σ α) (r : α)

def partial_deriv : mv_polynomial σ α :=
-- p.sum $ λ v r, C r * (add_monoid.smul (v i) (X i ^ (v i - 1)) * v.prod (λ j n, if i = j then 1 else (mv_polynomial.X j)^n))
p.sum $ λ v r, finsupp.single (v.sum $ λ j n, finsupp.single j (if i = j then n-1 else n)) (add_monoid.smul (v i) r)

-- #exit
theorem partial_deriv_add : (p + q).partial_deriv i = p.partial_deriv i + q.partial_deriv i :=
finsupp.sum_add_index (λ v, by rw [add_monoid.smul_zero, finsupp.single_zero]; refl) $
λ v a1 a2, by rw [add_monoid.smul_add, finsupp.single_add]

theorem partial_deriv_zero : (0 : mv_polynomial σ α).partial_deriv i = 0 :=
finsupp.sum_zero_index

theorem partial_deriv_C : (C r).partial_deriv i = 0 :=
(finsupp.sum_single_index $ by rw [add_monoid.smul_zero, finsupp.single_zero]; refl).trans $
by rw [finsupp.zero_apply, add_monoid.zero_smul, finsupp.single_zero]; refl

theorem partial_deriv_X : (X i : mv_polynomial σ α).partial_deriv j = if i = j then 1 else 0 :=
begin
  rw [partial_deriv, X, monomial, finsupp.sum_single_index, finsupp.sum_single_index, nat.sub_self, finsupp.single_apply],
  { split_ifs with hji hij hij,
    { rw [add_monoid.one_smul, finsupp.single_zero], refl },
    { exact absurd hji.symm hij },
    { exact absurd hij.symm hji },
    { rw [add_monoid.zero_smul, finsupp.single_zero], refl } },
  { split_ifs with hji,
    { rw [nat.zero_sub, finsupp.single_zero] },
    { rw finsupp.single_zero } },
  { rw [add_monoid.smul_zero, finsupp.single_zero], refl }
end

theorem partial_deriv_one : (1 : mv_polynomial σ α).partial_deriv i = 0 :=
by rw [ C_1, partial_deriv_C]

instance : semimodule α (mv_polynomial σ α) := finsupp.to_semimodule _ _

theorem C_mul'' : C r * p = r  p :=
begin
  refine finsupp.induction p _ _,
  { exact (mul_zero _).trans (smul_zero _).symm },
  { intros v s f hfv hs ih,
    rw [mul_add, smul_add, ih],
    rw [C, monomial, finsupp.mul_def, finsupp.sum_single_index, finsupp.sum_single_index, zero_add],
    rw [finsupp.smul_single, smul_eq_mul],
    { rw [mul_zero, finsupp.single_zero] },
    { rw [finsupp.sum_single_index]; rw [zero_mul, finsupp.single_zero] } }
end

theorem partial_deriv_smul : (r  p).partial_deriv i = r  p.partial_deriv i :=
begin
  rw [partial_deriv, finsupp.sum_smul_index', partial_deriv,  C_mul'', finsupp.mul_sum], refine finset.sum_congr rfl _,
  { intros v hv, dsimp only, rw [add_monoid.smul_eq_mul, add_monoid.smul_eq_mul, mul_left_comm,  smul_eq_mul,  finsupp.smul_single, C_mul''] },
  { intros v, rw [add_monoid.smul_zero, finsupp.single_zero], refl }
end

theorem partial_deriv_mul : (p * q).partial_deriv i = p * q.partial_deriv i + q * p.partial_deriv i :=
begin
  have :  v w : σ  , w i  0  finsupp.sum (v + w) (λ (j : σ) (n : ), finsupp.single j (ite (i = j) (n - 1) n)) =
    v + finsupp.sum w (λ (j : σ) (n : ), finsupp.single j (ite (i = j) (n - 1) n)),
  { intros v w hw, ext j,
    rw [finsupp.sum_apply, finsupp.add_apply, finsupp.sum_apply, finsupp.sum, finset.sum_eq_single j, finsupp.sum, finset.sum_eq_single j],
    { rw [finsupp.single_apply, finsupp.single_apply, if_pos rfl, if_pos rfl], split_ifs with hij,
      { subst hij, rw [finsupp.add_apply, nat.add_sub_assoc], exact nat.one_le_of_lt (nat.pos_of_ne_zero hw) },
      { refl } },
    { intros k hk hkj, rw [finsupp.single_apply, if_neg hkj] },
    { intros hjw, rw [finsupp.single_apply, if_pos rfl], split_ifs; rw [finsupp.not_mem_support_iff.1 hjw] },
    { intros k hk hkj, rw [finsupp.single_apply, if_neg hkj] },
    { intros hjw, rw [finsupp.single_apply, if_pos rfl], split_ifs; rw [finsupp.not_mem_support_iff.1 hjw] } },
  refine finsupp.induction p _ (λ v r p hpv hr ihp, _),
  { erw zero_mul, rw zero_add, erw partial_deriv_zero, rw mul_zero },
  rw [add_mul, partial_deriv_add], refine eq.trans (congr_arg _ ihp) _,
  rw [add_mul, partial_deriv_add, mul_add, add_comm₄], congr' 1,
  refine finsupp.induction q _ (λ w s q hqw hs ihq, _),
  { erw mul_zero, rw zero_add, erw zero_mul, rw partial_deriv_zero },
  rw [mul_add, partial_deriv_add], refine eq.trans (congr_arg _ ihq) _,
  rw [add_mul, partial_deriv_add, mul_add, add_comm₄], congr' 1,
  rw [finsupp.single_mul_single, finsupp.single_eq_smul_one v r, finsupp.single_eq_smul_one w s, finsupp.single_eq_smul_one (v+w) (r*s)],
  rw [partial_deriv_smul, partial_deriv_smul, partial_deriv_smul,  C_mul'',  C_mul'',  C_mul'',  C_mul'',  C_mul''],
  rw [mul_comm₄,  C_mul, mul_comm₄,  C_mul, mul_comm s r,  mul_add], congr' 1,
  rw [partial_deriv, finsupp.sum_single_index], swap, { rw [add_monoid.smul_zero, finsupp.single_zero], refl },
  rw [partial_deriv, finsupp.sum_single_index], swap, { rw [add_monoid.smul_zero, finsupp.single_zero], refl },
  rw [partial_deriv, finsupp.sum_single_index], swap, { rw [add_monoid.smul_zero, finsupp.single_zero], refl },
  rw [finsupp.add_apply, finsupp.single_mul_single, finsupp.single_mul_single, one_mul, one_mul],
  by_cases hv : v i = 0,
  { rw [hv, zero_add, add_monoid.zero_smul, finsupp.single_zero], erw add_zero,
    by_cases hw : w i = 0,
    { rw [hw, add_monoid.zero_smul, finsupp.single_zero, finsupp.single_zero] },
    { rw [this v w hw] } },
  by_cases hw : w i = 0,
  { rw [hw, add_monoid.zero_smul, finsupp.single_zero, add_zero], erw zero_add, rw [add_comm v w, this w v hv] },
  rw [add_monoid.add_smul, finsupp.single_add, add_comm], congr' 1,
  { rw this v w hw }, { rw [add_comm v w, this w v hv] }
end

theorem vars_add : (p + q).vars  p.vars  q.vars :=
λ i, by unfold vars; simp only [finset.mem_union, multiset.mem_to_finset]; exact
λ hi, multiset.mem_add.1 (multiset.subset_of_le
  (le_trans (degrees_add p q) $ lattice.sup_le (multiset.le_add_right _ _) (multiset.le_add_left _ _)) hi)

theorem vars_mul : (p * q).vars  p.vars  q.vars :=
λ i, by unfold vars; simp only [finset.mem_union, multiset.mem_to_finset]; exact
λ hi, multiset.mem_add.1 (multiset.subset_of_le (degrees_mul p q) hi)

theorem vars_X_subset : vars (X i : mv_polynomial σ α)  {i} :=
λ j hj, multiset.subset_of_le (degrees_X i) $ multiset.mem_to_finset.1 hj

theorem of_not_mem_vars (h : i  p.vars) (v : σ  ) (hv : v  p.support) : v i = 0 :=
finsupp.not_mem_support_iff.1 $ λ hiv, h $
have h1 : v.to_multiset  p.degrees := finset.le_sup hv,
have h2 : _  v.to_multiset := finset.single_le_sum (λ _ _, multiset.zero_le _) hiv,
multiset.mem_to_finset.2 $ multiset.subset_of_le h1 $ multiset.subset_of_le h2 $
by rw  nat.succ_pred_eq_of_pos (nat.pos_of_ne_zero $ finsupp.mem_support_iff.1 hiv); exact
multiset.mem_cons_self _ _

theorem partial_deriv_of_not_mem_vars (h : i  p.vars) : p.partial_deriv i = 0 :=
finset.sum_eq_zero $ λ v hv, by dsimp only; rw [of_not_mem_vars i p h v hv, add_monoid.zero_smul, finsupp.single_zero]; refl

end mv_polynomial

Kenny Lau (Jul 12 2019 at 14:43):

PR-ready?

Johan Commelin (Jul 12 2019 at 15:03):

Looks pretty good to me. Maybe C_mul'' can be called C_mul_eq_smul?

Yury G. Kudryashov (Oct 04 2020 at 04:17):

I've started thinking about a proper way to introduce partial derivatives into mathlib.

Yury G. Kudryashov (Oct 04 2020 at 04:24):

It's clear how to define pderiv for a function f : (fin n → k) → E

Yury G. Kudryashov (Oct 04 2020 at 04:25):

But this definition won't work, e.g., for f : k × k → E or f : k → E, and this doesn't sound good for a mathematician.

Yury G. Kudryashov (Oct 04 2020 at 04:29):

I suggest introducing something like

class has_canonical_basis (k : Type*) [normed_field k] (E : Type*) [normed_group E] [normed_space k E] :=
(σ : Type)
[hfin : fintype σ]
(iso : (σ  k) L[k] E)

Yury G. Kudryashov (Oct 04 2020 at 04:30):

With instances for σ → k, euclidean_space, E × F (using σ = σE ⊕ σF), k (using σ = unit).

Yury G. Kudryashov (Oct 04 2020 at 04:31):

@Patrick Massot @Sebastien Gouezel What do you think?

Johan Commelin (Oct 04 2020 at 05:41):

We have the same problem in the omin repository. We introduced a has_coordinates typeclass.

Johan Commelin (Oct 04 2020 at 05:41):

@Reid Barton Do you think it is ready for PR?

Johan Commelin (Oct 04 2020 at 05:42):

(Of course it doesn't assume any normed* stuff. So we'll have to think whether it is good enough, or maybe you need some has_normed_coordinates extending it.

Yury G. Kudryashov (Oct 04 2020 at 05:45):

Actually, we can just upgrade from linear_equiv to continuous_linear_equiv using finiteness of σ.

Yury G. Kudryashov (Oct 04 2020 at 05:46):

Could you please post a link to your has_coordinates code?

Johan Commelin (Oct 04 2020 at 05:48):

https://github.com/rwbarton/lean-omin/blob/master/src/o_minimal/coordinates.lean

Johan Commelin (Oct 04 2020 at 05:50):

There is also Patrick's has_uncurry class in mathlib, which might be the right solution for your use case

Yury G. Kudryashov (Oct 04 2020 at 05:56):

No, it will uncurry f : k × k → E to k → k → E, not to (fin 2 → k) → E.

Yury G. Kudryashov (Oct 04 2020 at 05:57):

Or (unit ⊕ unit → k) → E

Yury G. Kudryashov (Oct 04 2020 at 05:59):

I would prefer to have any (σ : Type*) [fintype σ] as an index type, not necessarily fin n.

Yury G. Kudryashov (Oct 04 2020 at 06:00):

Because for E × F it's easier to deal with sum.inl k than some fin magic.

Yury G. Kudryashov (Oct 04 2020 at 06:01):

And I need coordinates to be linear. So, probably I'll add another typeclass.

Sebastien Gouezel (Oct 04 2020 at 07:31):

There is still the issue that, on EFE \oplus F, some people call partial derivative the derivative with respect to EE (so, it's not a number, it's really a matrix). But it is impossible to get a notion that covers all these variants, so I think your idea is a very nice one to cover one-dimensional partial derivatives.

Yury G. Kudryashov (Oct 04 2020 at 07:37):

We can mention that ∂f/∂x : E →L[k] G for f : E × F → G can be written as fderiv (λ x, f (x, y)).

Sebastien Gouezel (Oct 04 2020 at 07:37):

Yes, sure!

Reid Barton (Oct 04 2020 at 15:06):

In general, the problem is how to replace a given fin.dim. R-vector space with some fixed model R^ι (ι a finite type) or R^n in a conventional way. For some purposes the order of coordinates is irrelevant, and then R^ι is enough, but for other purposes the order really matters and you need R^n. For example, consider row reduction of the matrices that represent linear maps, or classifying subspaces by how they meet the standard flag inside R^n. Likewise in model theory, quantifier elimination works by eliminating one variable at a time, say, the "last" one, and for this it's again better to work with R^(n+1) than with fintypes. (Actually row reduction of matrices is basically a special case of this, I think.)

Reid Barton (Oct 04 2020 at 15:10):

So, unless we think it makes sense to have both concepts, I think the R^n version is better.

Reid Barton (Oct 04 2020 at 15:13):

Yury G. Kudryashov said:

Because for E × F it's easier to deal with sum.inl k than some fin magic.

With some version of the "reindexing" concept you can hide the details of exactly how the coordinates of (x, y) : E × F are related to those of x : E and y : F.

Reid Barton (Oct 04 2020 at 15:24):

The main advantage of a fintype version would be that you can have an instance for ι → R itself whose coordinates are given by the identity and so, in particular, the coordinates for (ι ⊕ ι') → R are related to those for ι → R and ι' → R specifically by composing with sum.inl and sum.inr. In lean-omin this has never come up because we have actually never had a use for specifically ι → R with [fintype ι]. But, you could have an instance which uses choice to pick an ordering on ι and uses it to define coordinates. In that case, there would be no specific relationship between the coordinates for (ι ⊕ ι') → R and ι → R and ι' → R. I claim this doesn't really matter because you can describe the coordinate change as a reindexing, anyways. However, probably a sensible thing to do would be to only have a global instance when ι is an instance of docs#fin_enum and then ensure that ι ⊕ ι' has a sensible fin_enum instance.

Yury G. Kudryashov (Oct 04 2020 at 15:24):

Is R^ι with a decidable_linear_order on ι any worse than fin n?

Reid Barton (Oct 04 2020 at 15:25):

Another consideration about the fintype version is that either you introduce a second universe variable, or in the ι → R instance you only handle ι in Type 0.

Reid Barton (Oct 04 2020 at 15:26):

It is worse because fin n has a bunch of API that is not conveniently available on an arbitrary finite decidable linear order, as well as somewhat better definitional behavior.

Reid Barton (Oct 04 2020 at 15:28):

(Also, conceptually the point of this whole construction is to reduce some problem/construction from general fin.dim. vector spaces to specific model spaces, so why stop at R^ι when you could go all the way to R^n?)

Reid Barton (Oct 04 2020 at 15:34):

Once you're working in this setting, the general objects are like (V : Type*) [has_coordinates R V] and the specific objects are like fin n -> R, so there's no longer any special significance to ι → R with [fintype ι].

Reid Barton (Oct 04 2020 at 15:35):

It only comes up if you have a [fintype ι] that comes from outside, so to speak. And then perhaps it would be better to have [fin_enum ι] which is basically the non-linear analogue of this setup.

Yury G. Kudryashov (Oct 04 2020 at 15:38):

OK, I'll try fin n. Thank you for the explanation.

Reid Barton (Oct 04 2020 at 15:53):

I should probably also add that in lean-omin this reindexing stuff is only ever used to prove Props, but you would probably also want to for example say what the partial derivatives of prod.fst : E \x F -> E are, so that might affect the design.

Yury G. Kudryashov (Oct 04 2020 at 15:56):

I'll just declare an instance on E × F using docs#equiv.sum_fin_sum_equiv.

Patrick Massot (Nov 16 2021 at 13:35):

@Sebastien Gouezel and @Yury G. Kudryashov what is the current status of partial derivatives and CkC^k functions? Say for instance I have a C1C^1 function F:E×FGF : E \times F \to G. How am I meant to express that F/e\partial F/\partial e is a continuous function?

Patrick Massot (Nov 16 2021 at 13:36):

And how should I prove this? Is it already somewhere?

Sebastien Gouezel (Nov 16 2021 at 21:08):

F/e\partial F / \partial e is just the composition of DFDF with the injection of EE in E×FE \times F. I don't think we have a special notation for it (unless Yury has introduced something when doing the implicit function theorem, where this kind of thing is used all the time).

Patrick Massot (Nov 16 2021 at 21:10):

I had a look in the implicit function file, having exactly this idea in mind, but I didn't see anything relevant.

Patrick Massot (Nov 16 2021 at 21:12):

The continuity issue is related to the trichotomy of has_fderiv fderiv and times_cont_diff which complicates everything.

Patrick Massot (Nov 16 2021 at 21:13):

And actually I think what I needed when I posted this message was the continuity of eF/x(e,x0)e \mapsto \partial F/\partial x(e, x_0) or something like this which makes things even more complicated in Lean (but still obvious on paper).

Yury G. Kudryashov (Nov 17 2021 at 22:40):

I did not introduce any notation. Probably you need something like docs#continuous_linear_map.compL with docs#continuous_linear_map.inl. To make things worse, you might need to use flip on compL.

Do other proof assistants have automation for things like this? How does it work?

rtertr (Sonia) (Mar 23 2023 at 16:47):

Hello everyone,
I am wondering how to work around the partial derivatives, since I realized they are not formalized. Under the Schwartz space page #analysis.schwartz_space they say they have defined rapid decay in such a way ‖x‖^k * ‖iterated_fderiv ℝ n f x‖ < C. This approach completely avoids using partial derivatives as well as polynomials.
I am just not sure how to work with x : fin d → ℝ then. As an undergraduate student, I am sure I have enough mathematical background to fully work around partial derivatives in Lean. I have yet to find a way to transform iterated_fderiv into something I can work with. In one dimension, I used that ‖(λ (x : ℝ), eval ↑x p * cexp (-a * ↑x ^ 2)) x‖ ≤ C.
Any help would be greatly appreciated as I am a bit stuck at the moment.
Kind regards,
Sonia

Sophie Morel (Mar 23 2023 at 17:24):

It probably depends on what you want to do with the partial derivatives. I may misunderstand the question, but I'll have a go.
If f is a function on Rk\mathbb{R}^k and (e1,,ek)(e_1,\ldots,e_k) is the canonical basis, then iterated_fderiv R n f x will be a n-linear function on Rk\mathbb{R}^k, let's call it Fn(x)F_n(x). You can go between it and the partial derivatives by the formula:

nfn1x1nkxk(x)=Fn(x)(e1,,e1,,ek,,ek),\frac{\partial^n f}{\partial^{n_1}x_1\ldots\partial^{n_k}x_k}(x)=F_n(x)(e_1,\ldots,e_1,\ldots,e_k,\ldots,e_k),

where each basis element eie_i is repeated nin_i times, at least for f nice enough and if I didn't get confused in my indices. Here I am implicitly assuming that Schwartz's theorem holds, so it doesn't matter in which order I take the partial derivatives; this means that the iterated_fderiv R f n x should be a symmetric multilinear map if f is nice enough (one problem being to give optimal conditions on f for this to hold). I couldn't find that statement in mathlib, except for n=2 (see fderiv_symmetric); technically the case n=2 implies the general case but it might be a pain to prove.

Patrick Massot (Mar 23 2023 at 17:26):

Sonia, we need a more specific question to give you a more specific answer.

Kevin Buzzard (Mar 23 2023 at 20:20):

My students have been finding this issue as well. Basically there are vector spaces, and there is Rn\R^n. If you work with Rn\R^n then you get concrete vectors (lists of numbers) and matrices and things. If you work with vector spaces then you get abstract vectors vv and linear maps. If you choose a basis then there's a dictionary between one language and the other. But mathlib prefers to not choose a basis if it can avoid doing so.

Jireh Loreaux (Mar 23 2023 at 21:52):

I also prefer to avoid choosing a basis, including when I'm teaching! :smiley:

Moritz Doll (Mar 23 2023 at 23:22):

I think the answer to the question "how do I prove that something is a Schwartz function" is to hold your breath until Sebastien's PR that gives API for the norms of iterated_fderiv exists.

Moritz Doll (Mar 23 2023 at 23:29):

You should also not work with fin d → ℝ, but with inner_product_space.

Kevin Buzzard (Mar 24 2023 at 00:09):

ie don't choose a basis :-)

Moritz Doll (Mar 24 2023 at 00:43):

yes, I wanted to give the answer to the question what is the correct level of generality.

Sebastien Gouezel (Mar 24 2023 at 09:51):

If you really want to work on this now, you could start from the branch #18643, in which I prove bounds for the n-th derivative of a composition. But note that this is not in mathlib master yet!

rtertr (Sonia) (Mar 24 2023 at 16:25):

Hello again everyone,
Thank you so much for your input :D
So to answer Patrick's question about more information: I am working with Stein & Shakarchi's book on Fourier Analysis, and specifically Chapter: The Fourier Transform on ℝ^d. I ideally want to formalize theorem 2.4. image.png
The norm needs to be Euclidean norm. And the derivative is defined as the following image.png thus I need to prove image.png.
Now, I am not sure how the the {n: N} ‖iterated_fderiv ℝ n f x‖ is equivalent to the multi-index β, or if I am misunderstanding this.
I was thinking I could just try to work with my own definition between the connection between iterated_fderiv R n f x and the partial derivative in defined in the book. But I would be nervous to build all of my work on a potentially incorrect definition :)

rtertr (Sonia) (Mar 24 2023 at 16:29):

Sophie Morel said:

nfn1x1nkxk(x)=Fn(x)(e1,,e1,,ek,,ek),\frac{\partial^n f}{\partial^{n_1}x_1\ldots\partial^{n_k}x_k}(x)=F_n(x)(e_1,\ldots,e_1,\ldots,e_k,\ldots,e_k),

Looks very similar, except for the norm at

partialnf partial^ |n| f

Sophie Morel said:

fderiv_symmetric

I could not find this in mathlib

rtertr (Sonia) (Mar 24 2023 at 16:32):

Kevin Buzzard said:

My students have been finding this issue as well.

What do you then tell them? Do they manage to work around it, or do they just not work further on it?
How do you not choose a basis?

rtertr (Sonia) (Mar 24 2023 at 16:45):

This is a little bit related, I was trying to perhaps switch from R^d to the euclidean norm space, and I was not allowed to apply cont_diff_norm_sq . I haven't tried with inner_product_space, I will try that later, but for now I am unsure why it is upset. Here is a #mwe

import data.nat.choose.sum
import data.complex.exponential
import analysis.normed_space.exponential
import analysis.special_functions.log.basic
import data.polynomial.basic
import data.polynomial.eval
import analysis.schwartz_space
import analysis.normed_space.exponential
import tactic
import topology.basic
import analysis.special_functions.log.base
import analysis.calculus.cont_diff
import analysis.calculus.iterated_deriv
import analysis.special_functions.exp_deriv
import number_theory.dioph
import analysis.complex.real_deriv
import analysis.special_functions.gaussian
import analysis.inner_product_space.calculus

open complex

lemma  complex.cont_diff_coe2  {d:ℕ } {f : ((fin d)→ ℝ)→ ℝ} (hf : cont_diff ℝ   ⊤ (λ (x : (fin d)→ ℝ  ), f x)): cont_diff ℝ ⊤ (λ y,  (f y : ℂ)) :=
begin
  apply cont_diff.comp _ hf,
  show cont_diff ℝ _ complex.of_real_clm,
  exact of_real_clm.cont_diff,
end


lemma  complex.cont_diff_coe2_euclid  {d:ℕ } {f : euclidean_space ℝ (fin d)→ ℝ} (hf : cont_diff ℝ   ⊤ (λ (x : euclidean_space ℝ (fin d)  ), f x)): cont_diff ℝ ⊤ (λ y,  (f y : ℂ)) :=
begin
  apply cont_diff.comp _ hf,
  show cont_diff ℝ _ complex.of_real_clm,
  exact of_real_clm.cont_diff,
end



def gaussian_complex  {d:ℕ } {a:ℂ} (ha:0<a.re): schwartz_map (fin d -> ℝ)   ℂ :=
  { to_fun := λ x : (fin d -> ℝ), complex.exp (-a * ‖x‖^2),
    smooth' :=
    begin
      refine cont_diff.comp _ _,
      apply cont_diff.cexp,
      exact cont_diff_id,
      refine cont_diff.mul _ _,
      exact cont_diff_const,
      norm_cast,
      refine complex.cont_diff_coe2 _,
      convert cont_diff_norm_sq,
    end,
    decay' := sorry,}



def gaussian_complex_euclidean_space  {d:ℕ } {a:ℂ} (ha:0<a.re): schwartz_map (euclidean_space ℝ (fin d))   ℂ :=
  { to_fun := λ x : (euclidean_space ℝ (fin d)), complex.exp (-a * ‖x‖^2),
    smooth' :=
    begin
      refine cont_diff.comp _ _,
      apply cont_diff.cexp,
      exact cont_diff_id,
      refine cont_diff.mul _ _,
      exact cont_diff_const,
      norm_cast,
      refine complex.cont_diff_coe2_euclid _,
      convert cont_diff_norm_sq,
    end,
    decay' := sorry,}

Moritz Doll (Mar 25 2023 at 00:22):

You would have an easier time if you follow the advise we are giving:

variables {E : Type*} [inner_product_space  E]

lemma  complex.cont_diff_coe2_euclid {f : E  } (hf : cont_diff     (λ (x : E), f x)): cont_diff   (λ y,  (f y : )) :=
begin
  apply cont_diff.comp _ hf,
  show cont_diff  _ complex.of_real_clm,
  exact of_real_clm.cont_diff,
end

noncomputable
def gaussian_complex_euclidean_space  {a:} (ha:0<a.re): schwartz_map E  :=
  { to_fun := λ x : E, complex.exp (-a * x‖^2),
    smooth' :=
    begin
      refine cont_diff.comp _ _,
      apply cont_diff.cexp,
      exact cont_diff_id,
      refine cont_diff.mul _ _,
      exact cont_diff_const,
      norm_cast,
      exact complex.cont_diff_coe2_euclid cont_diff_norm_sq,
    end,
    decay' := sorry,}

Moritz Doll (Mar 25 2023 at 00:26):

fderiv_symmetric

I could not find this in mathlib

https://leanprover-community.github.io/mathlib_docs/analysis/calculus/fderiv_symmetric.html

Moritz Doll (Mar 25 2023 at 05:16):

If you really want to work on this now, you could start from the branch #18643, in which I prove bounds for the n-th derivative of a composition. But note that this is not in mathlib master yet!

I got too excited and proved the multiplication result for Schwartz functions: #18649

Moritz Doll (Mar 25 2023 at 05:19):

Composition should be very similar and if @rtertr (Sonia) does not object, then I will prove that as well.

rtertr (Sonia) (Mar 25 2023 at 18:28):

Hi Moritz, this looks very great! Interesting to see new tactics and way of doing proofs!
Now I have not looked too much at it yet, I will have more time tomorrow.
But when it comes to the bilinear proof, why is it not possible to do it by induction? :D
Also a proof of Composition would be great!
Kind regards, Sonia

Moritz Doll (Mar 26 2023 at 03:27):

It is certainly possible to prove everything by induction, but it is way more convenient to use general bounds for the iterated derivative. Half a year ago or so I've tried to use an the induction argument by hand and gave up because it is very messy, since iterated derivatives are so annoying to deal with. If you look at Sebastien's PR you will see what I mean.

Moritz Doll (Mar 26 2023 at 05:02):

After working a bit on the composition, I think it is easier in your case to use the bound on the iterated_fderiv for the composition directly, rather than using some theorem for Schwartz functions. The amount of hoops one has to jump through to get the Gaussian into a sensible composition is probably not worth the effort.

rtertr (Sonia) (Mar 26 2023 at 16:01):

Hi Moritz,
Was working a bit with updating my Lean.
Now, oddly enough, after updating, I run into issues with the inner_product_space.
Before it worked perfectly, but since I updated Lean, it is now unhappy:

import data.complex.basic
import data.nat.choose.sum
import data.complex.exponential
import analysis.normed_space.exponential
import analysis.special_functions.log.basic
import data.polynomial.basic
import data.polynomial.eval
import analysis.schwartz_space
import analysis.normed_space.exponential
import tactic
import topology.basic
import analysis.special_functions.log.base
import analysis.calculus.cont_diff
import analysis.calculus.iterated_deriv
import analysis.special_functions.exp_deriv
import number_theory.dioph
import analysis.complex.real_deriv
import analysis.special_functions.gaussian
import analysis.inner_product_space.calculus

variables {E : Type*} [inner_product_space  E]

lemma  complex.cont_diff_coe2_euclid {f : E  } (hf : cont_diff     (λ (x : E), f x)): cont_diff   (λ y,  (f y : )) :=
begin
  apply cont_diff.comp _ hf,
  show cont_diff  _ complex.of_real_clm,
  exact complex.of_real_clm.cont_diff,
end

noncomputable
def gaussian_complex_euclidean_space  {a:} (ha:0<a.re): schwartz_map E  :=
  { to_fun := λ x : E, complex.exp (-a * x‖^2),
    smooth' :=
    begin
      refine cont_diff.comp _ _,
      apply cont_diff.cexp,
      exact cont_diff_id,
      refine cont_diff.mul _ _,
      exact cont_diff_const,
      norm_cast,
      exact complex.cont_diff_coe2_euclid cont_diff_norm_sq,
    end,
    decay' := sorry,}

rtertr (Sonia) (Mar 26 2023 at 16:04):

It now says

failed to synthesize type class instance for
E : Type u_1
 normed_add_comm_group E

And if I add that, it asks for [normed_space ℝ E]. And if I add that, it no longer wants to apply

type mismatch at application
  complex.cont_diff_coe2_euclid cont_diff_norm_sq
term
  cont_diff_norm_sq
has type
   (𝕜 : Type ?) {E : Type ?} [_inst_1 : is_R_or_C 𝕜] [_inst_2 : normed_add_comm_group E]
  [_inst_3 : inner_product_space 𝕜 E] [_inst_6 : normed_space  E] {n : },
    cont_diff  n (λ (x : E), x ^ 2)
but is expected to have type
  cont_diff   (λ (x : E), x ^ 2)

Eric Wieser (Mar 26 2023 at 16:05):

Can you show the version after you "added that"?

Kevin Buzzard (Mar 26 2023 at 16:05):

Do you understand the current error? Just fix it.

Kevin Buzzard (Mar 26 2023 at 16:06):

Eric I think the issue now is simply that Sonia hasn't given k explicitly.

Eric Wieser (Mar 26 2023 at 16:06):

I would not expect adding [normed_space ℝ E] to be necessary

Eric Wieser (Mar 26 2023 at 16:06):

Or in other words, adding it would almost certainly be a mistake

rtertr (Sonia) (Mar 26 2023 at 16:07):

Eric Wieser said:

Can you show the version after you "added that"?

Like, I put as a condition on E.

lean
import data.complex.basic
import data.nat.choose.sum
import data.complex.exponential
import analysis.normed_space.exponential
import analysis.special_functions.log.basic
import data.polynomial.basic
import data.polynomial.eval
import analysis.schwartz_space
import analysis.normed_space.exponential
import tactic
import topology.basic
import analysis.special_functions.log.base
import analysis.calculus.cont_diff
import analysis.calculus.iterated_deriv
import analysis.special_functions.exp_deriv
import number_theory.dioph
import analysis.complex.real_deriv
import analysis.special_functions.gaussian
import analysis.inner_product_space.calculus


variables {E : Type*} [inner_product_space  E] [normed_add_comm_group E]

lemma  complex.cont_diff_coe2_euclid {f : E  } (hf : cont_diff     (λ (x : E), f x)): cont_diff   (λ y,  (f y : )) :=
begin
  apply cont_diff.comp _ hf,
  show cont_diff  _ complex.of_real_clm,
  exact complex.of_real_clm.cont_diff,
end

noncomputable
def gaussian_complex_euclidean_space  {a:} (ha:0<a.re): schwartz_map E  :=
  { to_fun := λ x : E, complex.exp (-a * x‖^2),
    smooth' :=
    begin
      refine cont_diff.comp _ _,
      apply cont_diff.cexp,
      exact cont_diff_id,
      refine cont_diff.mul _ _,
      exact cont_diff_const,
      norm_cast,
      exact complex.cont_diff_coe2_euclid cont_diff_norm_sq,
    end,
    decay' := sorry,}

Kevin Buzzard (Mar 26 2023 at 16:15):

docs#inner_product_space

Kevin Buzzard (Mar 26 2023 at 16:16):

Oh I don't know if the docs are up to date. This is a very recent change.

Kevin Buzzard (Mar 26 2023 at 16:18):

Have you posted the actual code you're running? inner_product_space shoudln't compile without normed_add_comm_group and in your posting you have them the wrong way around.

Kevin Buzzard (Mar 26 2023 at 16:21):

import analysis.schwartz_space
import analysis.inner_product_space.calculus

are the only imports you need by the way. Why are you importing all this other stuff?

rtertr (Sonia) (Mar 26 2023 at 16:26):

Yeah, I tend just to import at the thing I have open on my main file :D but it seems to still give the same issue. If I change the order, I still get the same issue:

lean
type mismatch at application
  complex.cont_diff_coe2_euclid cont_diff_norm_sq
term
  cont_diff_norm_sq
has type
   (𝕜 : Type ?) {E : Type ?} [_inst_1 : is_R_or_C 𝕜] [_inst_2 : normed_add_comm_group E]
  [_inst_3 : inner_product_space 𝕜 E] [_inst_6 : normed_space  E] {n : },
    cont_diff  n (λ (x : E), x ^ 2)
but is expected to have type
  cont_diff   (λ (x : E), x ^ 2)

It is just so odd because it used to work so smoothly :)

Eric Wieser (Mar 26 2023 at 16:29):

Kevin Buzzard said:

Oh I don't know if the docs are up to date. This is a very recent change.

They are up to date

Kevin Buzzard (Mar 26 2023 at 16:29):

@rtertr (Sonia) Yes but this is what happens when you upgrade mathlib, things change. It is not backwards compatible, so it's not odd. Read the error messge and fix the error.

Eric Wieser (Mar 26 2023 at 16:30):

It is just so odd because it used to work so smoothly :)

Mathlib changes quickly, you shouldn't expect code on an old version to work perfectly on a newer version.
However, this particular issue is trivial to fix, the error message is telling you everything you need to know

rtertr (Sonia) (Mar 26 2023 at 16:52):

Sorry I was gone for a few minutes. I tried to add it the conditions, but I unfortunately can't get it work quite, but I will try to talk with someone about in person this week :D


Last updated: Dec 20 2023 at 11:08 UTC