Zulip Chat Archive

Stream: PhysLean

Topic: Vector calculus


ZhiKai Pong (Apr 05 2025 at 21:36):

although there is gradient in mathlib, will it still be useful to state the usual 3D gradient? (I assume making it compatible with SpaceTime requires this anyway) so we can state things like

theorem curl_of_grad_eq_zero (x: SpaceTime)
    (A : SpaceTime  EuclideanSpace  (Fin 3)) : ∇× ( A) x = 0 := by
  sorry

and things like the Laplacian operator

ZhiKai Pong (Apr 05 2025 at 21:55):

/-- The gradient of a function `SpaceTime → EuclideanSpace ℝ (Fin 3)`. -/
def spaceGrad (f : SpaceTime  EuclideanSpace  (Fin 3)) :
    SpaceTime  EuclideanSpace  (Fin 3) := fun x j =>
  match j with
  | 0 => deriv 0 (fun y => f y 0) x
  | 1 => deriv 1 (fun y => f y 1) x
  | 2 => deriv 2 (fun y => f y 2) x

@[inherit_doc spaceGrad]
scoped[SpaceTime] notation "∇" => spaceGrad

attempt following how spaceDiv and spaceCurl are defined

ZhiKai Pong (Apr 10 2025 at 15:15):

I realized f should be from SpaceTime to R (scalar function)... I'll correct this in the next PR

ZhiKai Pong (Apr 14 2025 at 21:23):

I'm working on some vector calculus identities, should we assume everything is ContDiff 𝕜 ⊤ f or keep all the assumptions as minimal as possible?

ZhiKai Pong (Apr 14 2025 at 21:23):

i.e. for example only assume ContDiff 𝕜 2 f for deriv_commute

ZhiKai Pong (Apr 14 2025 at 21:24):

Or maybe the identities should have minimal assumption, then we prove the physical functions satisfies those?

Kevin Buzzard (Apr 14 2025 at 21:31):

The philosophy in mathlib is to stick to minimal assumptions as far as is reasonably possible, and in mathlib this has its advantages. At the very least it seems pointless putting more hypothesis in a theorem than the proof uses!

Joseph Tooby-Smith (Apr 15 2025 at 13:09):

I would like it if for div and curl we could have ∇ × f and ∇ ⬝ f instead of ∇× f and ∇⬝ f (note the different spacings). I couldn't find any easy way to do this with notation or marcos.

Joseph Tooby-Smith (Apr 15 2025 at 13:14):

Actually never mind, something like:

macro (name := divNotation) "∇" "⬝" f:term:100  : term => `(div $f)

works. I was trying

macro (name := divNotation) "∇ ⬝" f:term:100  : term => `(div $f)

which doesn't work.

ZhiKai Pong (Apr 16 2025 at 15:15):

trying to define the Laplacian, which one of ∇² and Δ is more commonly used? I'm thinking of using ∇² for the scalar and Δ for the vector Laplacian, not sure if that's a good idea.

Joseph Tooby-Smith (Apr 16 2025 at 15:26):

I don't really have an opinion here, so don't mind too much. Both seem equally as common.

But I will say (somewhat related), at some point it would be really nice to have the (scalar) Laplacian written in e.g. spherical coordinates and an easy way to go between cartesian and spherical coordinates on space. I think this will be very useful in situations with spherical symmetry.

Joseph Tooby-Smith (Apr 16 2025 at 15:28):

I think your suggestion for using ∇² for the scalar and Δ for the vector is good - though if possible I think it would be nicer to use the same notation for both

ZhiKai Pong (Apr 16 2025 at 15:51):

Joseph Tooby-Smith said:

I don't really have an opinion here, so don't mind too much. Both seem equally as common.

But I will say (somewhat related), at some point it would be really nice to have the (scalar) Laplacian written in e.g. spherical coordinates and an easy way to go between cartesian and spherical coordinates on space. I think this will be very useful in situations with spherical symmetry.

is spherical coordinates in mathlib? I found docs#polarCoord but don't seem to find spherical coordinates.

ZhiKai Pong (Apr 16 2025 at 16:01):

ok I think it's safe to say it's just not a thing in mathlib :sweat_smile: #maths > polar coordinates @ 💬 is pretty much the only discussion on this

ZhiKai Pong (Apr 16 2025 at 21:49):

Joseph Tooby-Smith said:

I think your suggestion for using ∇² for the scalar and Δ for the vector is good - though if possible I think it would be nicer to use the same notation for both

I don't think having the same notation works, lean throws an error

hmm nevermind it might work, let me do some more testing

Tomas Skrivan (Apr 16 2025 at 22:28):

There are multiple ways to have the same notation for different things. I think there are three main approaches:

  • overloaded notation
  • use notation for a specialized typeclass and provide instances for every use case. The canonical example is + and the associated type class HAdd
  • write custom elaborator, this is most flexible but requires meta programming

I think the typeclass approach should work in this case.

Tomas Skrivan (Apr 16 2025 at 22:29):

Personally, I would reserve ∇² for Hessian i.e. matrix of all second order derivatives.

Tomas Skrivan (Apr 16 2025 at 22:30):

For Laplacian I would go with Δ

Joseph Tooby-Smith (Apr 18 2025 at 07:50):

One place it would be nice to implement these results is in
PhysLean.QuantumMechanics .OneDimension.GeneralPotential.Basic, and more generally in quantum mechanics.

I also think it may be worth making Space, and Time non-reducible(?) to prevent casting from say to Time. One way of doing this is to make them structures, but I think there is probably a better way (I've discussed this with some people before but forgot what the conclusion was).

(Not expecting anyone to do any of this just getting it out there :) )

ZhiKai Pong (Apr 18 2025 at 15:19):

I think this is somewhat related, if I want to show Time.deriv and Space.deriv commute, is it sufficient to state that their respective underlying fderiv commute, or do we want a more "physical" approach? (I don't know what that would look like)

ZhiKai Pong (Apr 18 2025 at 15:21):

for example ∂ₜ (∇ × E) = ∇ × (∂ₜ E)

Joseph Tooby-Smith (Apr 18 2025 at 15:22):

I have no problem with you using the underlying fderiv :).

My comment about non-reduciablity is to stop you doing something like:

def oddDef (t : Time) : Space 1 := t

which would currently work because Lean tries to help by casting types - but in this case isn't helping.

Tomas Skrivan (Apr 18 2025 at 22:00):

Joseph Tooby-Smith said:

I also think it may be worth making Space, and Time non-reducible(?) to prevent casting from say to Time. One way of doing this is to make them structures, but I think there is probably a better way (I've discussed this with some people before but forgot what the conclusion was).

I understand that from a philosophical standpoint this is desirable but I would be very cautious about this. You might end up duplicating lots of API for not technical benefit but only philosophical one.

Alex Meiburg (Apr 19 2025 at 16:45):

Hot take: the real issue here (philsophically - and this can be reflected in the Lean!) is that Space and Time aren't reals, they're AddTorsor ℝ.

That is, Time is some generic Type* equipped with an AddTorsor ℝ Time instance; Space k is some other generic Type* equipped with an AddTime ℝ^k (Space k) instance.

docs#AddTorsor

Alex Meiburg (Apr 19 2025 at 16:46):

This correctly reflects the fact that, for instance, there's no notion of adding a Time to a Time: I can't add last Wednesday to tomorrow to get a meaningful number. Same goes for locations in space

You can take the differences between times, though, and get a Real out, with p₁ -ᵥ p₂

Alex Meiburg (Apr 19 2025 at 16:48):

And I contend that casting that Real acrossSpace 1 and Time is actually a much smaller sin. Since it's only ever measuring distances (and not absolute positions), this is just converting distance to durations (at, presumably, the speed of light), which is a "cast" that physicists happily do very often all the time anyway

Alex Meiburg (Apr 19 2025 at 16:53):

It's actually a failing that docs#deriv has the type signature

{𝕜 : Type u} [NontriviallyNormedField 𝕜] {F : Type v} [AddCommGroup F] [Module 𝕜 F] [TopologicalSpace F] (f : 𝕜  F) (x : 𝕜) : F

when it could just as well have the type signature

{𝕜 : Type u} [NontriviallyNormedField 𝕜] {P : Type w} [AddTorsor 𝕜 P] {F : Type v} [AddCommGroup F] [Module 𝕜 F] [TopologicalSpace F] (f : P  F) (x : 𝕜) : F

which would correctly let us talk about derivatives on a torsor. Similarly, fderiv requires the domain be a module AddCommGroup E when it really should be AddTorsor P E.

Then it would use the instance addGroupIsAddTorsor by default anyway, and basically work the same for "simple" cases.

Alex Meiburg (Apr 19 2025 at 16:59):

I guess I would be willing to try to make this change in upstream mathlib (assuming that mathlib folks are okay with it - will open thread in a sec). I recognize that doing calculus is kind of a bare minimum for a useful definition, so I wouldn't expect PhysLean to accept torsors as the basis for spacetime until you can do derivatives with them in a reasonable way... but I feel confident this is the "right" way to state (flat) spacetime!

Joseph Tooby-Smith (Apr 19 2025 at 17:07):

Hi Alex, I agree with pretty much all of this. This is somewhat related to my post about the definition of a second and how is equipped with a norm in a way that Time really shouldn't be.

I think (correct me if you disagree) that we can take Time as manifold should be taken as isomorphic to . (I know in some systems you take time to be isomorphic to the circle as a manifold, or a closed interval etc.) But I think taking it isomorphic to is most useful for most purposes.
So maybe defining Time as the type without any additional structure (so def not abbrev), then putting on it an instance of AddTorsor ℝ Time and any other bona-fide instances instead of just inheriting things from .

This will also make it much easier to make Time non-reducible which solves my problem.

Alex Meiburg (Apr 19 2025 at 17:17):

Yeah, I think that taking it as an AddTorsor should be logically equivalent to taking it as a simply connected manifold with zero curvature...

At least, it is a fact that AddTorsor G P always means that P is isomorphic to a group G. It just has no "canonical" origin, and so no canonical isomorphism. This is a special case of how a group is a manifold for itself, I guess

Alex Meiburg (Apr 19 2025 at 17:23):

Other thread about mathlib

Joseph Tooby-Smith (Apr 19 2025 at 17:25):

This relies you on having the type P in the first place though, and I think it is better to have a specific type called Time, then having a variable P in all equations which can equivalently represent time (although the category theorist in me doesn't want to say this :().

In any case I think we are agreeing on the main points.
I will create an issue on PhysLean regarding this. To others: This shouldn't discourage anyone from working with Time and Space as they currently are - we can refactor later :).

Alex Meiburg (Apr 19 2025 at 17:26):

Ah yes, that's how I meant it too. :)

Tomas Skrivan (Apr 19 2025 at 21:39):

On a high level, I guess I disagree. I believe that simple things should be kept simple. A huge part of physics is classical, no relativity and no quantum physics, and adding all this complexity has very little benefit there.

I would also consider the cost this will incur on onboarding new people to the project. Someone wants to do a simple thing in classical mechanics and suddenly has to learn how manifolds are done in mathlib or what an AddTorsor is.

What I want to say is that unless you have a concrete project where this is really beneficial I would strongly recommend keeping simple things simple. I think I'm talking from experience, multiple times I tried to make something "future proof" only to realize that I didn't consider some really common case and had to refactor everything again. (To give you an example, for a very long time I tried making symbolic/automatic differentiation in SciLean to also work for variational calculus too but it was adding so much more complexity than I had to abandoned it. I think I wasted lots of time and effort on it which could have been used elsewhere more efficiently.)

Joseph Tooby-Smith (Apr 20 2025 at 06:44):

I agree that it is wise to worry if there is going to be a cost to onboarding new people by doing this - and by making any such change in PhysLean.

I think this is something we can actually test. We have enough usages of Time and Space in classical mechanics, quantum mechanics, vector calculus etc. in PhysLean that I think we can test if this change is going to make a massive difference to it's usage and the end user experience.

But the way I see this is that you will only notice this change in definition of Time if you were doing something with Time that you shouldn't be.
For example, add two times, take the zero time, multiply two times etc.

The definition actual definition of Time will still be

def  Time : Type := 

we're just not going to inherit every instance on .
So unless you actually are doing something related to smoothness etc. you are not going to need to worry about the definition of a manifold etc.

Kevin Buzzard (Apr 20 2025 at 22:03):

I would also consider the cost this will incur on onboarding new people to the project. Someone wants to do a simple thing in classical mechanics and suddenly has to learn how manifolds are done in mathlib or what an AddTorsor is.

For many years in the 2010s I was vehemently arguing that we should just get on and prove the fundamental theorem of calculus the way it's proved in a 1st year undergraduate course, so that 1st year undergraduates could get on formalizing analysis. There was a huge pushback from the analysts here; their argument was that the correct way to formalize integration was via some exotic integral taking values in a topological vector space, and that there was no point setting up the theory of 1-variable calculus, it should all be deduced from a multivariable theory; the argument was that multivariable calculus is not done by induction on number of variables, and there was simply no point doing the one-variable case when we knew we wanted the multivariable case. The idea was to deduce the FTC from some form of Stokes' theorem applied to an interval in the reals, with boundary the two endpoints. I argued and I argued (because I had a pile of 1st year undergraduates desperate to formalize analysis as they were being taught it) but I didn't get my way, and ultimately I think that the community made the right decision by ignoring me and doing things the way Bourbaki did them.

Tyler Josephson ⚛️ (Apr 21 2025 at 03:07):

Onboarding cost is very real. I’ve guided many scientists / engineers into Lean, and it remains a steep learning curve. But I find it interesting how it’s gotten easier over the years - better documentation helped, Mechanics of Proof helped, search engine tools like Moogle helped. When I started, it was Lean 3, and my UG ChemE student didn’t know what a ring was or anything about abstract algebra, and he had to learn it to make any headway. Now, students come in with exactly the same background, and they can make more headway because powerful tactics and other tools just help.

I’ve been curious about differential manifolds since watching a few lovely videos about thermodynamics and manifolds, but I don’t understand them, I haven’t had the time to learn that version of thermo. I intuit that the rigorous way to formalize classical thermo will be through manifolds, and that such derivations will be more elegant and more powerful than those in all the engineering textbooks. But, I’d struggle with even reading such proofs, in the end. I’d struggle to communicate such results with people in my field, and they would struggle to build on it.

Tyler Josephson ⚛️ (Apr 21 2025 at 03:24):

I wonder if PhysLean should be like Mathlib in this regard - make it as rigorous as possible, relying on present or future tactics / tools to make it accessible. Or is PhysLean just different? Kevin is glad Mathlib didn’t align with the math level of undergrads, and that’s wise because the people driving the field of mathematics forward have much more math expertise. But in science and engineering, “undergrad math” is not just a reasonable level of math for most learners, but many/most of the people driving the field forward don’t have much more math than the typical core taught to scientists and engineers. I’d like it if a grad student with that kind of background could derive a new theory in their area of research and also be able to formalize it, needing no more than perhaps a one-semester introduction to proofs in Lean.

Joseph Tooby-Smith (Apr 21 2025 at 05:22):

I agree with you Tyler. Especially at this stage when the community needs growing, anything that turns people off contributing is necessarily a bad thing.

I really hope that we can have the best of both worlds here. That we can have the rigorous definitions sitting behind, or parallel to more conventional and easy to use approaches. Then someone who's work depends on the rigorous definitions can use that, whilst someone who wants to work with more down-to-earth definitions can.
I think this is really a case of making good API and documentation. Similar to what is currently happening around Space and Time.

To use the example of theormodyanmics (which I don't know too much about - so apologize if I say something stupid). Ideally I would like to have in PhysLean both the conventional approach and the manifold approach. If the manifold approach can sit behind the conventional approach in such a way that someone using the conventional approach doesn't need to know it exists, then this is good. But I don't think we should sacrifice the usability of the conventional approach for the manifold approach - but I do think we should have the manifold approach also.

Joseph Tooby-Smith (Apr 21 2025 at 05:35):

I guess by "doesn't need to know it exists" can mean a number of different things.

  • It could mean that the conventional approach is built completely separately from the manifold approach. And there may exist separate modules connecting the two.
  • It could mean that the basic definitions of the conventional approach come from the manifold approach, but enough API exists that this is hidden.

I think the exact choice of which we follow here will depend on the exact nature of the problem.

Joseph Tooby-Smith (Apr 21 2025 at 06:15):

Given we can't actually change the definition of Space and Time until
this is resolved, and that this doesn't seem to be possible anytime soon, I've made this PR improving the docs around Time and Space.

Basically it explains that we inherit instances on these types and this, for example automatically gives us a metric etc., but also a few things we don't necessarily want.

ZhiKai Pong (Apr 21 2025 at 22:22):

Just writing this down somewhere to document what I've learnt the past couple days (mainly through here).

ZhiKai Pong said:

if I want to show Time.deriv and Space.deriv commute, is it sufficient to state that their respective underlying fderiv commute

Few days ago I wrote the message above as I set out to prove ∂ₜ (∇ × E) = ∇ × (∂ₜ E). It turns out this is much more complicated than what I previously conceived so I thought it might be worth sharing. What I had in mind was pretty much just: after unfolding all definitions I should have a bunch of terms of the form
2xt=2tx\frac{\partial^2}{\partial_x\partial_t}=\frac{\partial^2}{\partial_t\partial_x}
and then I just show they commute. I've already proved differentiations along space coordinates (2xy=2yx\frac{\partial^2}{\partial_x\partial_y}=\frac{\partial^2}{\partial_y\partial_x}) commute so surely this can't be that bad.

Now I'm realizing that Space and Time lives in different domains, and I'm actually trying to do differentiation in ℝ × ℝ³. I think how I'll have to approach this is to turn Space and Time derivatives into SpaceTime derivatives where the domain is ℝ × ℝ³ via timeSlice, and in Lean terms this involves a whole lot of (un)currying.

Many thanks to @Joseph Tooby-Smith and @Tomas Skrivan for their help and patience!

Tomas Skrivan (Apr 22 2025 at 02:13):

I got intrigued by how annoying this is, here is my sketch of proving

theorem fderiv_swap (f : X  Y  Z) (x dx : X) (y dy : Y) (hf : IsSymmSndFDerivAt 𝕜 (f) (x,y)) :
    fderiv 𝕜 (fun x' => fderiv 𝕜 (fun y' => f x' y') y dy) x dx
    =
    fderiv 𝕜 (fun y' => fderiv 𝕜 (fun x' => f x' y') x dx) y dy := by ...

Full code missing just the final differentiability obligations. With PR #24056 they might be solvable simple by fun_prop if you add the assumption ContDiff 𝕜 2 (↿f).

code

There are six versions of fderiv_uncurry:/

Tomas Skrivan (Apr 22 2025 at 02:19):

At the bottom of that code you can find version of the theorem with dx and dy not applied.

theorem fderiv_swap' (f : X  Y  Z) (x : X) (y : Y) (hf : IsSymmSndFDerivAt 𝕜 (f) (x,y)) :
    fderiv 𝕜 (fun x' => fderiv 𝕜 (fun y' => f x' y') y) x
    =
    (fderiv 𝕜 (fun y' => fderiv 𝕜 (fun x' => f x' y') x) y).flip := ..

ZhiKai Pong (Apr 23 2025 at 16:55):

@Tomas Skrivan sorry for pinging, I have this as an intermediate step:

import Mathlib

local notation "ℝ³" => EuclideanSpace  (Fin 3)

lemma fderiv_coord (f :   ³  ³) (t dt : ) (x : ³) :
    (fderiv  (fun t' => f t' x i) t) dt = (fderiv  f t) dt x i := by
  sorry

codomain of the left fderiv is (fun x ↦ ℝ) i and codomain of the right fderiv is ℝ³ → ℝ³ . this manages to typecheck somehow, but how do I proceed to proof this?

ZhiKai Pong (Apr 23 2025 at 16:57):

(I think I'm getting the gist of what your previous message is doing, but it's getting quite complicated in my implementation due to all the coordinate functions i.e. EuclideanSpace.single )

Tomas Skrivan (Apr 23 2025 at 17:13):

I'm afraid that with the current mathlib you can't really prove this exactly because the codomain on rhs is ℝ³ → ℝ³. You can state it only because fderiv was generalized to general topological vector spaces but 99% of the theorems has not been generalized and they are formulated using normed vector spaces and ℝ³ → ℝ³ is not a normed vector space.

So my question is what is the original problem that got you to this lemma? Maybe you can't reformulate the original problem differently.

I will check with @Yury G. Kudryashov what are his thoughts on this as he is the one generalizing fderiv to topological vector spaces.

ZhiKai Pong (Apr 23 2025 at 17:39):

Tomas Skrivan said:

So my question is what is the original problem that got you to this lemma? Maybe you can't reformulate the original problem differently.

code

I think the problem stems from the original form of the statement itself?

In PhysLean the corresponding statement is

lemma time_deriv_curl (fₜ : Time  Space  EuclideanSpace  (Fin 3)) (t : Time) (x : Space) :
    ∂ₜ (fun t => ( × fₜ t) x) t = ( × (∂ₜ fₜ t)) x:= by

if that gives any insight.

Tomas Skrivan (Apr 23 2025 at 17:56):

Instead of curl (fderiv ℝ (fun t' => (fₜ t')) t 1) x I think you should have curl (fun x' => fderiv ℝ (fun t' => (fₜ t' x')) t 1) x.

The PhysLean statement has the same issue here (∇ × (∂ₜ fₜ t)) x as you are differentiating fₜ which has codomain Space → EuclideanSpace ℝ (Fin 3). I do not know how to reformulate it "correctly" with the PhysLean's fancy notation (correctly is relative here as we are fighting mathlib's deficiency).

You can of course write (∇ × (fun x' => ∂ₜ (fun t' => fₜ t' x') t)) x but it effectively looses the point of the nice notation.

In SciLean's derivative notation I would write ∇× (x':=x), ∂ (t':=t), fₜ t' x' except there is no ∇× operator defined right now. But there is notation like this for all kinds of derivatives ∂ ∇ ∂> <∂ (derivative, gradient, forward mode AD, reverse mode AD).

ZhiKai Pong (Apr 23 2025 at 18:19):

With this change
Tomas Skrivan said:

Instead of curl (fderiv ℝ (fun t' => (fₜ t')) t 1) x I think you should have curl (fun x' => fderiv ℝ (fun t' => (fₜ t' x')) t 1) x.

I'm still left with

(fderiv  (fun t' => ft t' x' i) t) dt = (fderiv  (fun t' => ft t' x) t) dt i

Maybe this is doable with fderiv_pi, let me try

ZhiKai Pong (Apr 23 2025 at 18:25):

ah ok this works! thanks

ZhiKai Pong (Apr 23 2025 at 18:53):

is there an idiomatic way to state the assumption that leads to DifferentiableAt ℝ (fun t' => f t' x i) t?

Edit: I think hf : Differentiable ℝ (↿f) works

ZhiKai Pong (Apr 23 2025 at 20:45):

@Tomas Skrivan I don't know how bad this is, can your PR (#24056) handle this?
I can imagine doing differentiability arguments on curried functions might be a terrible idea...

import Mathlib

local notation "ℝ³" => EuclideanSpace  (Fin 3)

example (ft :   ³  ³) (hf : ContDiff  2 ft) :
    DifferentiableAt  (fun t =>
    (fderiv  (fun x => ft t x 2) x) (EuclideanSpace.single 1 1)) t := by
  apply Differentiable.clm_apply
  . sorry
  · fun_prop

Tomas Skrivan (Apr 23 2025 at 20:48):

I think fun_prop should be able to do this, it is definitely designed to handle assumptions on uncurried functions. Right now I'm not at my computer so I can't test it

ZhiKai Pong (Apr 23 2025 at 21:12):

I'm not sure what I should do here, should I just wait for your PR to go through or will that take a long time?
Or is it the best to add the new lemmas manually for the time being then refactor later once the PR goes live?

Anyway, this is no hurry at all, so please don't feel pressured if you're busy, you are already extremely helpful and I appreciate it a lot :)

Tomas Skrivan (Apr 24 2025 at 00:52):

No idea what is the best approach. You can create a PR that depends on that PR but you won't have PhysLean unless you make a special branch that depends on that PR.

You(or me) could also harass someone to review it and merge it. Maybe I can make a topic in #mathlib4 about it to draw more attention. I don't know :man_shrugging:

Joseph Tooby-Smith (Apr 24 2025 at 06:42):

Sorry I've only managed to vaguely follow this conversation.

One option would be to, for the time being, make a definition of a Prop corresponding to the lemma you can't prove yet. Then

  1. carry around this Prop as an assumption in further results.
  2. Add that this Prop needs a proof, and that we are waiting on the relevant PR.

Joseph Tooby-Smith (Apr 24 2025 at 07:36):

Ok, this is not the nicest, and may not be what you actually want here, but this may hold over until we have this PR.

Code

PhysLean already has fderiv_uncurry in the TimeSlice file because I needed this there.

ZhiKai Pong (Apr 24 2025 at 18:55):

I realized that the fderiv_swapoccurs at ℝ × ℝ³, but then what I actually need is ℝ × (fun x ↦ ℝ) i since I'm working with fin_cases...

what I mean by that is I ended up with this:

import Mathlib

local notation "ℝ³" => EuclideanSpace  (Fin 3)

example (f :   ³  ³) (x dx : ³) (t dt : )
    (h : (fderiv  (fun t' => (fderiv  (fun x' => f t' x') x) dx) t) dt
    =
    (fderiv  (fun x => (fderiv  (fun x' => f x' x) t) dt) x) dx) :
    (fderiv  (fun t' => (fderiv  (fun x' => f t' x' i) x) dx) t) dt
    =
    (fderiv  (fun x' => (fderiv  (fun t' => f t' x' i) t) dt) x) dx := by
  sorry

I think I'll have to reformulate the fderiv_uncurry and fderiv_wrt_prod to handle the FinType explicitly? I'll have a go but let me know if there's a simpler way to do this directly on what's given above...

ZhiKai Pong (Apr 24 2025 at 19:10):

have hf' : IsSymmSndFDerivAt  (f) (t,x) :=
    sorry

ok I think it's just this^ statement has to be changed to be in in terms of the FinType, I'm just not sure how to state this

full code

Joseph Tooby-Smith (Apr 24 2025 at 20:14):

Wouldn't fderiv_pi work here? (may have to flip the arguments of f)

Joseph Tooby-Smith (Apr 24 2025 at 20:38):

Is something like the following what you are looking for?

code

Joseph Tooby-Smith (Apr 24 2025 at 20:54):

I think all the remaining sorry’s (except the first which is easy) here could be relatively straight forward applications of the same principal I used. Define a functions through compositions of functions which are known to be differentiable.

ZhiKai Pong (Apr 24 2025 at 21:13):

oh my, thanks a lot... I'll try to understand this and clean this up over the next few days.

Just curious, may I ask is this annoying and complicated for you as well or is it more or less straightforward with experience?

Kevin Buzzard (Apr 24 2025 at 21:24):

For some of us, solving these complicated problems is part of the fun :-)

Joseph Tooby-Smith (Apr 24 2025 at 21:39):

Yeah I agree with Kevin - its all part of the fun :)

I would say this is probably something that comes with time though, you get to know where to look, what sort of things are likely to work and what things are likely to be called etc. These all make some of the more annoying bits easier, and probably more enjoyable. Getting to know how to use loogle effectively helped me an awful lot.

Joseph Tooby-Smith (Apr 25 2025 at 07:02):

Here is a complete proof of fderiv_swap. It is very much a mess, but is sorry-free. It can very likely be broken down into a series of smaller lemmas.

The code below needs the preliminary material of the code in my last but one message (it goes over the character limit if I include it here).

Code

ZhiKai Pong (Apr 25 2025 at 13:41):

@Joseph Tooby-Smith

(fderiv 𝕜 (f) xy) dxy = (fderiv 𝕜 (Function.uncurry f) xy) dxy

this is resolvable by rflbut rw can't see through this. Which version do we want?

Joseph Tooby-Smith (Apr 25 2025 at 13:54):

IMO I think the former is better.

ZhiKai Pong (Apr 25 2025 at 16:00):

variable {k : Type} [NontriviallyNormedField k]
    {N W M : Type} [NormedAddCommGroup M] [NormedSpace k M]
    [NormedAddCommGroup N] [NormedSpace k N]
    [NormedAddCommGroup W] [NormedSpace k W]

In a declaration like this is it more idiomatic to write {k : Type} or just {k}?

Joseph Tooby-Smith (Apr 25 2025 at 17:26):

I prefer the former i.e. {k : Type}. My brain has to do slightly less thinking to process it :).

ZhiKai Pong (Apr 25 2025 at 17:48):

@Tomas Skrivan may I ask why is docs#Differentiable.comp' in Mathlib.Tactic.FunProp.Differentiable but not in Mathlib.Analysis.Calculus.FDeriv.Comp like docs#Differentiable.comp? I tried to find the former in FDeriv.Comp and only realized they're in a different directory later on...

Tomas Skrivan (Apr 25 2025 at 17:50):

Ohh that is for historical reasons, that file should be removed and those theorems moved/removed.

The reason was while developing fun_prop I didn't have to recompile the whole mathlib when I made changes to fun_prop tactic.

ZhiKai Pong (Apr 25 2025 at 17:53):

I was puzzled for a while why it runs fine on the web editor but not on my own setup until I realized I didn't have the right imports :melting_face:

ZhiKai Pong (Apr 26 2025 at 15:14):

@Tomas Skrivan does this actually require x and y to be real?

import Mathlib

variable {𝕜 : Type} [NontriviallyNormedField 𝕜]
    {X Y Z : Type} [NormedAddCommGroup X] [NormedSpace 𝕜 X]
    [NormedAddCommGroup Y] [NormedSpace 𝕜 Y]
    [NormedAddCommGroup Z] [NormedSpace 𝕜 Z]

example (x : X) (y : Y) : DifferentiableAt 𝕜 (fderiv 𝕜 fun y' => (x, y')) y := by
  fun_prop --doesn't work

example (x : ) (y : ) : DifferentiableAt  (fderiv  fun y' => (x, y')) y := by
  fun_prop --goes through analytic and requires CompleteSpace (X × Y)

ZhiKai Pong (Apr 26 2025 at 15:45):

import Mathlib

variable {𝕜 : Type} [NontriviallyNormedField 𝕜]
    {X Y Z : Type} [NormedAddCommGroup X] [NormedSpace 𝕜 X]
    [NormedAddCommGroup Y] [NormedSpace 𝕜 Y]
    [NormedAddCommGroup Z] [NormedSpace 𝕜 Z]

example (x : X) (y : Y) : DifferentiableAt 𝕜 (fderiv 𝕜 fun y' => (x, y')) y := by
  have hl (y' : Y) : (fderiv 𝕜 fun y' => (x, y')) y' = ContinuousLinearMap.inr 𝕜 X Y := by
    rw [(hasFDerivAt_prodMk_right x y').fderiv]
  conv_lhs =>
    enter [y]
    rw [hl]
  fun_prop

managed to prove it, probably just a matter of missing API then

Tomas Skrivan (Apr 26 2025 at 16:43):

Nice! I didn't test it but I would expect that this should be provable with #24056 by using just fun_prop

ZhiKai Pong (May 01 2025 at 19:11):

variable {𝕜 : Type} [NontriviallyNormedField 𝕜]
    {X Y Z : Type} [NormedAddCommGroup X] [NormedSpace 𝕜 X]
    [NormedAddCommGroup Y] [NormedSpace 𝕜 Y]
    [NormedAddCommGroup Z] [NormedSpace 𝕜 Z]

lemma ContDiff.uncurry (f : X  Y  Z) (x : X) (hf : ContDiff 𝕜 2 f) :
    ContDiff 𝕜 2 (f x) := by
  sorry

this looks like it's straightforward but I can't figure out how to proceed, suggestions appreciated

Joseph Tooby-Smith (May 01 2025 at 19:17):

I would expect something like the following:
f x is the composite of ↿f and the inclusion Y → X x Y taking y to (x, y). Then something like a comp property of ContDiff.


Last updated: May 02 2025 at 03:31 UTC