Repository navigation
New Smooth Take-Off planet - #160
Conversation
|
Overall structure with Boss = (derivative computation) and final level = (main statement as easy corollary) looks good to me. Still has a number of tactics that we haven't introduced in the game (like refine and convert). You could introduce these, but that would require additional levels for practising these tactics. So it might be easier to try to find alternative proofs that avoid them. |
|
I think |
Indeed. Sorry I didn't notice this. |
|
Yes, you're right. By the way, I think we could also introduce the variant syntax of obtain ⟨x, hx⟩ : ∃ x, p x := proof Here |
|
On |
Ah, right, I see your point about |
|
Just for the moment, please don't push any further commits here while I'm reviewing the next levels. |
|
I'm still playing around with how the derivatives are computed. This all culminates in the last third of L08. The syntax deriv f x as a functional alternative, but I guess working with this we would need to make additional statements that |
|
Anyway, here's a more constructive idea. I came up with a variant for computation in L08. Starting from the proof state p : ℝ[X]
x : ℝ
hx : 0 < x
hf : f x = rexp (-x⁻¹)
⊢ HasDerivAt (fun (y : ℝ) ↦ eval y⁻¹ p * rexp (-y⁻¹)) (eval x⁻¹ (X ^ 2 * (p - derivative p)) * f x) xI do: have h_comp : (fun (y : ℝ) ↦ eval y⁻¹ p * Real.exp (-y⁻¹)) = (fun y ↦ p.eval y * Real.exp (-y)) ∘ Inv.inv := by
rfl
rw [h_comp]
clear h_comp
have h₁ := p.hasDerivAt x⁻¹
have h_neg := hasDerivAt_neg x⁻¹
have h₂ := HasDerivAt.exp h_neg
have h_mul := HasDerivAt.mul h₁ h₂
have h₃ := hasDerivAt_inv (x := x) (by grind) -- or hasDerivAt_inv hx.ne.symm
have h_comp := HasDerivAt.comp x h_mul h₃
convert! h_comp using 1
simp [hf]
ringThe advantage is that I don't need to write out a single derivative by hand. I only need to write out in full how I want to view the function as a composition, but that part follows the current solution. All the computations are done for me. The disadvantage is that I need this new tactic What's your take on this? |
Actually, the final levels do use the functional version of the derivative, and its iterated generalization. My reading is that, as it stands, the final result |
| convert! h_comp using 1 | ||
| simp [hf] | ||
| ring |
There was a problem hiding this comment.
| convert! h_comp using 1 | |
| simp [hf] | |
| ring | |
| convert h_comp using 1 | |
| · rfl | |
| · rfl | |
| · simp [hf] | |
| ring |
We can close the goal without !, but there will be two more subgoals. Plain convert only tries rfl at reducible transparency, meaning it will only unfold definitions marked @[reducible]. convert! uses default transparency, so it can also unfold ordinary definitions and instances. Therefore, it closed the first two subgoals when using convert h_comp using 1.
I'm not against introducing convert in the game. I think it's a useful tactic, and it can simplify some of the derivative computations. In practice, we could encourage players to try convert! first: it produces the same goals as convert but closes more of the trivial ones automatically, so it usually just works. I'm happy to discuss where we could introduce it.
There was a problem hiding this comment.
We need to solve the other issue first (deriv & iteratedDeriv versus HasDerivAt). Do you have an idea for how to fix the planet so that we have a mathematically meaningful result at the end? Once it's fixed, we need to analyse whether it pays off to keep HasDerivAt, or whether we can switch to deriv. If we switch to deriv, then we probably won't need convert. If we need to keep HasDerivAt, then yes, I would vote to introduce convert.
There was a problem hiding this comment.
Right. If we use deriv then we need to introduce DifferentiableAt, which "equals" to HasDerivAt.
There was a problem hiding this comment.
The reason we need DifferentiableAt is that we need this for derivative calculations. For example, deriv_mul.
There was a problem hiding this comment.
Ah, I got your point. We can rephrase L08 via deriv as follows:
example (p : ℝ[X]) (x : ℝ) (hx : 0 < x) :
deriv (fun x ↦ p.eval x⁻¹ * f x) x =
((X ^ 2 * (p - derivative p)).eval x⁻¹ * f x) := by
have hf : f x = rexp (-x⁻¹) := by
unfold f
rw [if_neg]
grind
have hev : f =ᶠ[𝓝 x] fun y ↦ rexp (-y⁻¹) := by
filter_upwards [eventually_gt_nhds hx] with y hy
unfold f
rw [if_neg]
grind
rw [deriv_fun_mul]
· rw [hev.deriv_eq]
rw [show (fun y ↦ p.eval y⁻¹) = (fun y ↦ p.eval y) ∘ Inv.inv from rfl,
deriv_comp x p.differentiableAt (differentiableAt_inv hx.ne')]
have hn : DifferentiableAt ℝ (fun y : ℝ ↦ -y⁻¹) x := (differentiableAt_inv hx.ne').neg
rw [deriv_exp hn, deriv.fun_neg, Polynomial.deriv, deriv_inv, hf]
simp
ring
· exact p.differentiableAt.comp x (differentiableAt_inv hx.ne')
· rw [hev.differentiableAt_iff]
exact (differentiableAt_inv hx.ne').neg.expPlease excuse the rough proof. I had Claude put together a quick one to see how far deriv can take the calculation. It seems to simplify the derivative computations quite a bit! :)
There was a problem hiding this comment.
That would certainly be the cleanest solution, if its doable.
There was a problem hiding this comment.
Yes, it is doable. The solution only contains 6 lines of code. However, this requires our original design in L08 (HasDerivAt version).
Statement : ContDiff ℝ ∞ f := by
apply contDiff_of_differentiable_iteratedDeriv
intro m _
rw [iteratedDeriv_eq_poly]
intro x
apply HasDerivAt.differentiableAt
apply hasDerivAt_polynomial_eval_inv_mulThere was a problem hiding this comment.
OK, then I guess we should keep HasDerivAt, but introduce convert. Feel free to start work on this; I'll ping you before I start editing here again.
There was a problem hiding this comment.
Thanks! I will do it.
There was a problem hiding this comment.
I resolved our previous discussion. While I was rewriting the third case in current level 8, I came up an alternative proof using DifferentiableAt.hasDerivAt, which I recorded in a branch.
|
Thanks for the update! I'm just making some last adjustments now. |
|
I'm tending now towards calling this planet "Cauchy". I wasn't previously aware of this, but it turns out that essentially this example was one of Cauchy's motivations to work out his theory of derivatives. See the first page of this preprint:
And here's a primary source: Cauchy mentions this example in his Résumé des leçons données à l'École royale polytechnique sur le calcul infinitésimal, see the last paragraph of the printed page 152:
|
|
In the story, I think Cauchy will be a fierce dragon living in an egg. The formalosophers living on the egg don't want the egg to crack and the dragon to come out. So our heroes need to land and take off very, very softly … |
Uh oh!
There was an error while loading. Please reload this page.