Zulip Chat Archive
Stream: new members
Topic: Nth derivative of a function
Icaro Costa (Jan 08 2023 at 22:09):
I want to write a definition Dn
that represents the nth derivative in one variable. This is what I'm trying:
import analysis.calculus.deriv
import data.real.basic
/-Function definitions-/
variable (f : ℝ -> ℝ)
noncomputable def D : (ℝ → ℝ) → (ℝ → ℝ)
| a := deriv a
noncomputable def Dn : ℕ × (ℝ → ℝ) → (ℝ → ℝ)
| (0, a) := a
| (1, a) := D a
| (n+1, a) := Dn (n, a)
I get the error:
failed to prove recursive application is decreasing, well founded relation
@has_well_founded.r (ℕ × (ℝ → ℝ))
(@prod.has_well_founded ℕ (ℝ → ℝ) (@has_well_founded_of_has_sizeof ℕ nat.has_sizeof)
(@has_well_founded_of_has_sizeof (ℝ → ℝ) (default_has_sizeof (ℝ → ℝ))))
Possible solutions:
- Use 'using_well_founded' keyword in the end of your definition to specify tactics for synthesizing well founded relations and decreasing proofs.
- The default decreasing tactic uses the 'assumption' tactic, thus hints (aka local proofs) can be provided using 'have'-expressions.
The nested exception contains the failure state for the decreasing tactic.
nested exception message:
default_dec_tac failed
state:
Dn : ℕ × (ℝ → ℝ) → ℝ → ℝ,
n : ℕ,
a : ℝ → ℝ
⊢ prod.lex has_lt.lt (λ (a₁ a₂ : ℝ → ℝ), false) (n, a) (n + 1, a)
I don't understand this error, what does using_well_founded
means?
Sky Wilshaw (Jan 08 2023 at 22:10):
Your function currently takes an argument of type ℕ × (ℝ → ℝ)
. I'd recommend switching this to a curried function style, where your function type is ℕ → (ℝ → ℝ) → (ℝ → ℝ)
.
Sky Wilshaw (Jan 08 2023 at 22:11):
Then I believe the error will disappear.
Sky Wilshaw (Jan 08 2023 at 22:11):
Are you familiar with functional programming in other languages?
Yaël Dillies (Jan 08 2023 at 22:12):
You will find docs#nat.iterate useful
Icaro Costa (Jan 08 2023 at 22:12):
Sky Wilshaw said:
Are you familiar with functional programming in other languages?
This is my first time working with this sort of language
Sky Wilshaw (Jan 08 2023 at 22:13):
I'd recommend looking at this page in Functional Programming in Lean for more information, but basically:
Sky Wilshaw (Jan 08 2023 at 22:14):
Suppose your function takes multiple inputs, say, a
and b
, and outputs c
. It's usually easier to define it as a function which takes an input a
and spits out a second function, which takes an input b
and outputs c
.
Sky Wilshaw (Jan 08 2023 at 22:14):
So you'd write the type as a -> (b -> c)
, or more concisely, a -> b -> c
.
Sky Wilshaw (Jan 08 2023 at 22:15):
All of Lean's syntax is built to accommodate this programming style, including things like function applications, where you just write f a b
instead of f(a)(b)
.
Sky Wilshaw (Jan 08 2023 at 22:16):
To answer your original question, Lean will check every definition you write to make sure that it doesn't infinitely loop. The in-built method for determining this wasn't able to verify that Dn
doesn't infinitely loop, because it used the comparatively more complicated type ℕ × (ℝ → ℝ)
. If instead you use just ℕ
, then pass (ℝ → ℝ)
as another parameter afterwards, it's easier to figure out that it doesn't infinitely loop.
Sky Wilshaw (Jan 08 2023 at 22:17):
using_well_founded
is a way to basically tell Lean a proof that your function doesn't loop infinitely.
Icaro Costa (Jan 09 2023 at 00:33):
Sky Wilshaw said:
To answer your original question, Lean will check every definition you write to make sure that it doesn't infinitely loop. The in-built method for determining this wasn't able to verify that
Dn
doesn't infinitely loop, because it used the comparatively more complicated typeℕ × (ℝ → ℝ)
. If instead you use justℕ
, then pass(ℝ → ℝ)
as another parameter afterwards, it's easier to figure out that it doesn't infinitely loop.
Using your explanation, I managed to write this instead:
def Dn : (ℕ) → (ℝ → ℝ) → (ℝ → ℝ)
| 0 := id
| 1 := D
| a := Dn a-1
The last error is gone, but now I receive a message saying "rec_fn_macro
only allowed in meta definitions". What is that?
Mario Carneiro (Jan 09 2023 at 00:36):
that's an error reporting bug, but that definition is not even well founded, it loops infinitely for n >= 2
Mario Carneiro (Jan 09 2023 at 00:37):
you most likely wanted to write Dn (a-1)
instead of Dn a - 1
, but this won't work either, because we can't prove in that context that a
is nonzero. You can write it with a +1
instead though:
def Dn : (ℕ) → (ℝ → ℝ) → (ℝ → ℝ)
| 0 := id
| 1 := D
| (a+1) := Dn a
Icaro Costa (Jan 09 2023 at 00:39):
Mario Carneiro said:
you most likely wanted to write
Dn (a-1)
instead ofDn a - 1
, but this won't work either, because we can't prove in that context thata
is nonzero. You can write it with a+1
instead though:def Dn : (ℕ) → (ℝ → ℝ) → (ℝ → ℝ) | 0 := id | 1 := D | (a+1) := Dn a
Somehow it still yields the same error
Mario Carneiro (Jan 09 2023 at 00:39):
I think the error message is about a missing noncomputable
Mario Carneiro (Jan 09 2023 at 00:40):
most likely D
is a noncomputable def
Icaro Costa (Jan 09 2023 at 00:40):
Huh, that seems to have worked. What does the noncomputable
does exactly?
Icaro Costa (Jan 09 2023 at 00:41):
Is it that I cannot get a number from it from #eval?
Mario Carneiro (Jan 09 2023 at 00:41):
it says that lean shouldn't attempt to compile it so you can't use it in #eval
Icaro Costa (Jan 09 2023 at 00:41):
Ah got it. Thanks!
Sky Wilshaw (Jan 09 2023 at 01:20):
Note that Dn
is not actually the right definition, you probably want D \circ Dn a
or something in the (a+1)
case.
Junyan Xu (Jan 09 2023 at 06:20):
You can simply write
import analysis.calculus.deriv
noncomputable def Dn (n : ℕ) (f : ℝ → ℝ) : ℝ → ℝ := deriv^[n] f
F^[n]
is notation for docs#nat.iterate
Mark Andrew Gerads (Jan 09 2023 at 06:22):
iterated_deriv
might be what is wanted here.
https://leanprover-community.github.io/mathlib_docs/analysis/calculus/iterated_deriv.html#iterated_deriv
Last updated: Dec 20 2023 at 11:08 UTC