Encyclopedia Cost Cost Aczel Proof D Alembert To Ode General
ARTICLE 4 claims 4 theorems
Cost Aczel Proof D Alembert To Ode General
A single smoothness assumption turns a functional equation into an ordinary differential equation, and that step is what makes the classical classification of its solutions possible.
From equation to differential equation
The d'Alembert functional equation is a statement about a real-valued function H of a real variable: for all real t and u, H(t+u) + H(t−u) = 2·H(t)·H(u). It is a functional equation because the unknown is a whole function, not a number. The classical problem, studied by Jean le Rond d'Alembert in the 1740s in the context of vibrating strings, is to find every function that satisfies it. The answer, proved by János Aczél and his school in the mid-twentieth century, is that under a mild regularity assumption the only continuous solutions are the constant function 1, the hyperbolic cosine cosh(α·t), and the ordinary cosine cos(α·t), for some real parameter α.
The theorem named dAlembert_to_ODE_general in the framework's machine-checked library of formal theorems establishes the bridge between the functional equation and an ordinary differential equation. It states: if H is infinitely differentiable and satisfies the d'Alembert equation, then for every t, the second derivative H''(t) equals H''(0)·H(t). In other words, the second derivative of H is a constant multiple of H itself. The constant is the second derivative at zero, c = H''(0). This is the key step that turns a problem about all functions into a problem about solutions of a linear second-order ODE, whose solutions are well understood.
The proof of this theorem proceeds in two phases. First, an integration bootstrap shows that a merely continuous solution is automatically infinitely differentiable. The library constructs an antiderivative of H, uses the functional equation to represent H as a quotient of such antiderivatives, and then iterates to conclude that H has derivatives of every order. Second, with smoothness in hand, differentiating the functional equation twice with respect to u and evaluating at u = 0 yields the ODE. The theorem is stated for the general case where the constant c can be any real number; the later classification theorem splits into the three cases c > 0, c = 0, and c < 0, giving cosh, constant, and cos respectively.
In Recognition Science, this theorem is part of the derivation of the cost function J(x) = (x + 1/x)/2 − 1. The framework models recognition events as entries in a discrete ledger, a record of events, and forces the cost of recognition to satisfy a functional equation of d'Alembert type. The smoothness theorem is what allows the framework to pass from the discrete ledger to continuous solutions and then to the explicit formula. But the theorem itself is a general mathematical fact, not a claim about physics. It does not assert that any particular physical quantity satisfies the d'Alembert equation, nor does it identify the constant c with any measured value. It is a lemma in the chain that the framework uses, not a physical prediction.
The theorem also does not claim that every solution of the d'Alembert equation is smooth. It assumes smoothness as a hypothesis, and the integration bootstrap shows that continuity alone is enough to obtain smoothness. But the theorem as stated takes smoothness as given. It does not address discontinuous solutions, which exist in abundance if one drops all regularity assumptions. The classification theorem, which is proved separately, is what states the trichotomy of solutions under the continuity assumption. The ODE derivation is the middle step, and its importance is that it reduces a functional equation to a differential equation, making the classification tractable.
What this theorem changes for the reader is the understanding that a functional equation, which looks global and rigid, can be tamed by a single smoothness assumption. The passage from H(t+u) + H(t−u) = 2·H(t)·H(u) to H'' = c·H is not a trick but a structural fact: the equation forces the second derivative to be proportional to the function itself. That is why the solutions are exactly the exponentials and their real and imaginary parts, the hyperbolic and ordinary cosines. The framework's use of this theorem is one instance of a general pattern: classical functional equations, once solved, become tools for deriving physical structure from minimal assumptions.
THEOREM dAlembert_to_ODE_general · IndisputableMonolith/Cost/AczelProof.lean
private theorem dAlembert_to_ODE_general (H : ℝ → ℝ)
(h_smooth : ContDiff ℝ smooth H)
(h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) :
∀ t, deriv (deriv H) t = deriv (deriv H) 0 * H t := by
have h2 : ContDiff ℝ 2 H := by exact_mod_cast (contDiff_infty.mp h_smooth) 2
have hDiff : Differentiable ℝ H := h2.differentiable (by decide : (2 : WithTop ℕ∞) ≠ 0)
have hCDiff1_H' : ContDiff ℝ 1 (deriv H) := by
rw [show (2 : WithTop ℕ∞) = 1 + 1 from rfl] at h2
rw [contDiff_succ_iff_deriv] at h2; exact h2.2.2
have hDiffDeriv : Differentiable ℝ (deriv H) :=
hCDiff1_H'.differentiable (by decide : (1 : WithTop ℕ∞) ≠ 0)
have hsh_add : ∀ (s v : ℝ), HasDerivAt (fun u => s + u) (1 : ℝ) v := fun s v => by
have h := (hasDerivAt_id v).add_const s; simp only [id] at h
rwa [show (fun u : ℝ => u + s) = fun u => s + u from funext fun u => add_comm u s] at h
have hsh_sub : ∀ (s v : ℝ), HasDerivAt (fun u => s - u) (-1 : ℝ) v := fun s v => by
have h1 : HasDerivAt (fun u : ℝ => -u) (-1 : ℝ) v := by
have := (hasDerivAt_id v).neg; simp only [id] at this; exact this
have h2 := h1.const_add s
rwa [show (fun u : ℝ => s + -u) = fun u => s - u from funext fun u => by ring] at h2
intro t
have h_feq : (fun u => H (t + u) + H (t - u)) = (fun u => 2 * H t * H u) :=
funext (h_dAl t)
have key : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 =
deriv (deriv (fun u => 2 * H t * H u)) 0 :=
congr_arg (fun f => deriv (deriv f) 0) h_feq
have lhs_eq : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 =
2 * deriv (deriv H) t := by
have h_plus : ∀ v, HasDerivAt (fun u => H (t + u)) (deriv H (t + v)) v := fun v => by
have h := ((hDiff (t + v)).hasDerivAt).comp v (hsh_add t v)
simp only [mul_one, Function.comp_def] at h; exact h
have h_minus : ∀ v, HasDerivAt (fun u => H (t - u)) (-deriv H (t - v)) v := fun v => by
have hcomp := ((hDiff (t - v)).hasDerivAt).comp v (hsh_sub t v)
simp only [mul_neg, mul_one, Function.comp_apply] at hcomp; exact hcomp
have hfirst : deriv (fun u => H (t + u) + H (t - u)) =
fun v => deriv H (t + v) - deriv H (t - v) := funext fun v => by
have h12 := ((h_plus v).add (h_minus v)).deriv
rw [show (fun u => H (t + u)) + (fun u => H (t - u)) =
fun u => H (t + u) + H (t - u) from by ext u; rfl] at h12; linarith [h12]
have hd2p : HasDerivAt (fun v => deriv H (t + v)) (deriv (deriv H) t) 0 := by
have := ((hDiffDeriv (t + 0)).hasDerivAt).comp 0 (hsh_add t 0)
simpa using this
have hd2m : HasDerivAt (fun v => deriv H (t - v)) (-deriv (deriv H) t) 0 := by
have := ((hDiffDeriv (t - 0)).hasDerivAt).comp 0 (hsh_sub t 0)
simpa using this
rw [congr_fun (congr_arg deriv hfirst) 0,
show (fun v => deriv H (t + v) - deriv H (t - v)) =
(fun v => deriv H (t + v)) - (fun v => deriv H (t - v)) from rfl]
linarith [(hd2p.sub hd2m).deriv]
have rhs_eq : deriv (deriv (fun u => 2 * H t * H u)) 0 =
2 * H t * deriv (deriv H) 0 := by
have hf : deriv (fun u => 2 * H t * H u) = fun v => 2 * H t * deriv H v :=
funext fun v => ((hDiff v).hasDerivAt.const_mul (2 * H t)).deriv
rw [congr_fun (congr_arg deriv hf) 0, ((hDiffDeriv 0).hasDerivAt.const_mul (2 * H t)).deriv]
rw [lhs_eq, rhs_eq] at key; linarith
THEOREM dAlembert_to_ODE_general · IndisputableMonolith/Cost/AczelProof.lean
private theorem dAlembert_to_ODE_general (H : ℝ → ℝ)
(h_smooth : ContDiff ℝ smooth H)
(h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) :
∀ t, deriv (deriv H) t = deriv (deriv H) 0 * H t := by
have h2 : ContDiff ℝ 2 H := by exact_mod_cast (contDiff_infty.mp h_smooth) 2
have hDiff : Differentiable ℝ H := h2.differentiable (by decide : (2 : WithTop ℕ∞) ≠ 0)
have hCDiff1_H' : ContDiff ℝ 1 (deriv H) := by
rw [show (2 : WithTop ℕ∞) = 1 + 1 from rfl] at h2
rw [contDiff_succ_iff_deriv] at h2; exact h2.2.2
have hDiffDeriv : Differentiable ℝ (deriv H) :=
hCDiff1_H'.differentiable (by decide : (1 : WithTop ℕ∞) ≠ 0)
have hsh_add : ∀ (s v : ℝ), HasDerivAt (fun u => s + u) (1 : ℝ) v := fun s v => by
have h := (hasDerivAt_id v).add_const s; simp only [id] at h
rwa [show (fun u : ℝ => u + s) = fun u => s + u from funext fun u => add_comm u s] at h
have hsh_sub : ∀ (s v : ℝ), HasDerivAt (fun u => s - u) (-1 : ℝ) v := fun s v => by
have h1 : HasDerivAt (fun u : ℝ => -u) (-1 : ℝ) v := by
have := (hasDerivAt_id v).neg; simp only [id] at this; exact this
have h2 := h1.const_add s
rwa [show (fun u : ℝ => s + -u) = fun u => s - u from funext fun u => by ring] at h2
intro t
have h_feq : (fun u => H (t + u) + H (t - u)) = (fun u => 2 * H t * H u) :=
funext (h_dAl t)
have key : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 =
deriv (deriv (fun u => 2 * H t * H u)) 0 :=
congr_arg (fun f => deriv (deriv f) 0) h_feq
have lhs_eq : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 =
2 * deriv (deriv H) t := by
have h_plus : ∀ v, HasDerivAt (fun u => H (t + u)) (deriv H (t + v)) v := fun v => by
have h := ((hDiff (t + v)).hasDerivAt).comp v (hsh_add t v)
simp only [mul_one, Function.comp_def] at h; exact h
have h_minus : ∀ v, HasDerivAt (fun u => H (t - u)) (-deriv H (t - v)) v := fun v => by
have hcomp := ((hDiff (t - v)).hasDerivAt).comp v (hsh_sub t v)
simp only [mul_neg, mul_one, Function.comp_apply] at hcomp; exact hcomp
have hfirst : deriv (fun u => H (t + u) + H (t - u)) =
fun v => deriv H (t + v) - deriv H (t - v) := funext fun v => by
have h12 := ((h_plus v).add (h_minus v)).deriv
rw [show (fun u => H (t + u)) + (fun u => H (t - u)) =
fun u => H (t + u) + H (t - u) from by ext u; rfl] at h12; linarith [h12]
have hd2p : HasDerivAt (fun v => deriv H (t + v)) (deriv (deriv H) t) 0 := by
have := ((hDiffDeriv (t + 0)).hasDerivAt).comp 0 (hsh_add t 0)
simpa using this
have hd2m : HasDerivAt (fun v => deriv H (t - v)) (-deriv (deriv H) t) 0 := by
have := ((hDiffDeriv (t - 0)).hasDerivAt).comp 0 (hsh_sub t 0)
simpa using this
rw [congr_fun (congr_arg deriv hfirst) 0,
show (fun v => deriv H (t + v) - deriv H (t - v)) =
(fun v => deriv H (t + v)) - (fun v => deriv H (t - v)) from rfl]
linarith [(hd2p.sub hd2m).deriv]
have rhs_eq : deriv (deriv (fun u => 2 * H t * H u)) 0 =
2 * H t * deriv (deriv H) 0 := by
have hf : deriv (fun u => 2 * H t * H u) = fun v => 2 * H t * deriv H v :=
funext fun v => ((hDiff v).hasDerivAt.const_mul (2 * H t)).deriv
rw [congr_fun (congr_arg deriv hf) 0, ((hDiffDeriv 0).hasDerivAt.const_mul (2 * H t)).deriv]
rw [lhs_eq, rhs_eq] at key; linarith
THEOREM dAlembert_contDiff_smooth · IndisputableMonolith/Cost/AczelProof.lean
private theorem dAlembert_contDiff_smooth (H : ℝ → ℝ) (h_one : H 0 = 1) (h_cont : Continuous H)
(h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) :
ContDiff ℝ smooth H :=
contDiff_infty.mpr (dAlembert_contDiff_nat H h_one h_cont h_dAl)
THEOREM dAlembert_classification · IndisputableMonolith/Cost/AczelProof.lean
/-- **Aczél–Kannappan classification of the d'Alembert functional equation.**
Any continuous H : ℝ → ℝ with H(0) = 1 satisfying
H(t+u) + H(t−u) = 2·H(t)·H(u)
is exactly one of:
* the constant 1,
* `Real.cosh (α·)` for some α ∈ ℝ, or
* `Real.cos (α·)` for some α ∈ ℝ.
Proof: continuity ⇒ C^∞ via the integration bootstrap (`dAlembert_contDiff_smooth`);
C² + d'Alembert ⇒ H'' = c·H with c = H''(0) (`dAlembert_to_ODE_general`);
ODE uniqueness in each branch of the trichotomy on c gives the explicit formula. -/
theorem dAlembert_classification (H : ℝ → ℝ)
(h_one : H 0 = 1) (h_cont : Continuous H)
(h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) :
(∀ x, H x = 1) ∨
(∃ α : ℝ, ∀ x, H x = Real.cosh (α * x)) ∨
(∃ α : ℝ, ∀ x, H x = Real.cos (α * x)) := by
have h_sm : ContDiff ℝ smooth H := dAlembert_contDiff_smooth H h_one h_cont h_dAl
have h2 : ContDiff ℝ 2 H := by exact_mod_cast (contDiff_infty.mp h_sm) 2
have hDiff : Differentiable ℝ H := h2.differentiable (by decide : (2 : WithTop ℕ∞) ≠ 0)
have h_H'0 : deriv H 0 = 0 :=
even_deriv_at_zero H (dAlembert_even H h_one h_dAl) hDiff.differentiableAt
have h_ode := dAlembert_to_ODE_general H h_sm h_dAl
set c := deriv (deriv H) 0 with hc_def
have hDD : Differentiable ℝ (deriv H) := by
rw [show (2 : WithTop ℕ∞) = 1 + 1 from rfl] at h2
exact (contDiff_succ_iff_deriv.mp h2).2.2.differentiable (by decide : (1 : WithTop ℕ∞) ≠ 0)
by_cases hc_pos : 0 < c
· -- c > 0: H = cosh(√c · t)
right; left; refine ⟨Real.sqrt c, ?_⟩
have hsc_ne : Real.sqrt c ≠ 0 := ne_of_gt (Real.sqrt_pos.mpr hc_pos)
let g : ℝ → ℝ := fun s => H (s / Real.sqrt c)
have h_div : ∀ s, HasDerivAt (fun x => x / Real.sqrt c) (Real.sqrt c)⁻¹ s := fun s => by
have := (hasDerivAt_id s).div_const (Real.sqrt c); simp only [id, one_div] at this; exact this
have hg_d : ∀ s, HasDerivAt g (deriv H (s / Real.sqrt c) * (Real.sqrt c)⁻¹) s :=
fun s => (hDiff _).hasDerivAt.comp s (h_div s)
have hg_ode : ∀ t, deriv (deriv g) t = g t := by
intro s
have hg1 : deriv g = fun s => deriv H (s / Real.sqrt c) * (Real.sqrt c)⁻¹ :=
funext fun s => (hg_d s).deriv
have h_dd_g : HasDerivAt (deriv g)
((deriv (deriv H) (s / Real.sqrt c) * (Real.sqrt c)⁻¹) * (Real.sqrt c)⁻¹) s := by
rw [hg1]
exact ((hDD (s / Real.sqrt c)).hasDerivAt.comp s (h_div s)).mul_const _
rw [h_dd_g.deriv, h_ode (s / Real.sqrt c)]
simp only [g]
rw [show c * H (s / Real.sqrt c) * (Real.sqrt c)⁻¹ * (Real.sqrt c)⁻¹ =
H (s / Real.sqrt c) * (c * ((Real.sqrt c)⁻¹ * (Real.sqrt c)⁻¹)) from by ring,
show (Real.sqrt c)⁻¹ * (Real.sqrt c)⁻¹ = (Real.sqrt c * Real.sqrt c)⁻¹ from
(mul_inv_rev _ _).symm,
Real.mul_self_sqrt (le_of_lt hc_pos),
mul_inv_cancel₀ (ne_of_gt hc_pos), mul_one]
intro t
have := ode_cosh_uniqueness_contdiff g (h2.comp (contDiff_id.div_const _))
hg_ode (by simp [g, h_one]) (by rw [(hg_d 0).deriv]; simp [h_H'0])
(Real.sqrt c * t)
simp only [g, mul_div_cancel_left₀ _ hsc_ne] at this; exact this
· by_cases hc_neg : c < 0
· -- c < 0: H = cos(√(−c) · t)
right; right; refine ⟨Real.sqrt (-c), ?_⟩
set c' := -c
have hsc_ne : Real.sqrt c' ≠ 0 := ne_of_gt (Real.sqrt_pos.mpr (neg_pos.mpr hc_neg))
let g : ℝ → ℝ := fun s => H (s / Real.sqrt c')
have h_div : ∀ s, HasDerivAt (fun x => x / Real.sqrt c') (Real.sqrt c')⁻¹ s := fun s => by
have := (hasDerivAt_id s).div_const (Real.sqrt c'); simp only [id, one_div] at this; exact this
have hg_d : ∀ s, HasDerivAt g (deriv H (s / Real.sqrt c') * (Real.sqrt c')⁻¹) s :=
fun s => (hDiff _).hasDerivAt.comp s (h_div s)
have hg_ode : ∀ t, deriv (deriv g) t = -(g t) := by
intro s
have hg1 : deriv g = fun s => deriv H (s / Real.sqrt c') * (Real.sqrt c')⁻¹ :=
funext fun s => (hg_d s).deriv
have h_dd_g : HasDerivAt (deriv g)
((deriv (deriv H) (s / Real.sqrt c') * (Real.sqrt c')⁻¹) * (Real.sqrt c')⁻¹) s := by
rw [hg1]
exact ((hDD (s / Real.sqrt c')).hasDerivAt.comp s (h_div s)).mul_const _
rw [h_dd_g.deriv, h_ode (s / Real.sqrt c')]
simp only [g, c']
rw [show c * H (s / Real.sqrt (-c)) * (Real.sqrt (-c))⁻¹ * (Real.sqrt (-c))⁻¹ =
H (s / Real.sqrt (-c)) * (c * ((Real.sqrt (-c))⁻¹ * (Real.sqrt (-c))⁻¹)) from by ring,
show (Real.sqrt (-c))⁻¹ * (Real.sqrt (-c))⁻¹ = (Real.sqrt (-c) * Real.sqrt (-c))⁻¹ from
(mul_inv_rev _ _).symm,
Real.mul_self_sqrt (le_of_lt (neg_pos.mpr hc_neg)),
show c * (-c)⁻¹ = -(1 : ℝ) from by
have hc_ne : c ≠ 0 := ne_of_lt hc_neg
field_simp]
ring
intro t
have := ode_cos_uniqueness g (h2.comp (contDiff_id.div_const _))
hg_ode (by simp [g, h_one]) (by rw [(hg_d 0).deriv]; simp [h_H'0])
(Real.sqrt c' * t)
simp only [g, mul_div_cancel_left₀ _ hsc_ne] at this; exact this
· -- c = 0: H ≡ 1
left
have hc0 : c = 0 := le_antisymm (not_lt.mp hc_pos) (not_lt.mp hc_neg)
have h_H'_zero : ∀ t, deriv H t = 0 := by
have := is_const_of_deriv_eq_zero hDD (fun t => by rw [h_ode t, hc0, zero_mul])
intro t; have := this t 0; simp [h_H'0] at this; exact this
intro t
have := is_const_of_deriv_eq_zero hDiff h_H'_zero t 0
simp [h_one] at this; exact this
What this page does not claim
The theorem does not assert that any particular physical quantity satisfies the d'Alembert equation. The theorem does not identify the constant c with any measured value. The theorem does not address discontinuous solutions, which exist without the continuity assumption.
Verify this page
Every tagged claim above names its theorem. To check one yourself rather than trust this page, elaborate the source module with Lean 4 and audit its axiom basis:
$ lake env lean IndisputableMonolith/Cost/AczelProof.lean
expected axiom basis: [propext, Classical.choice, Quot.sound] (the Lean kernel's standard three; no RS-specific axioms)
A page whose claims cannot be reproduced this way does not ship. In production, every anchor links to the exact declaration in the public source release, and this block carries the build receipt for the page itself.
Derived articles
This page is generated by a question-recursion engine: the questions its answers raise become the next pages. The current agenda, with open targets marked red:
- How does the d'Alembert functional equation arise from the discrete ledger of recognition events?
- What is the physical interpretation of the constant c = H''(0) in the framework's cost function?
- Which other functional equations in the framework are solved by the same integration bootstrap technique?
MACHINE LAYER · GROUNDED CLAIM TABLE · CLICK TO EXPAND
THEOREM dAlembert_to_ODE_general · IndisputableMonolith/Cost/AczelProof.lean
private theorem dAlembert_to_ODE_general (H : ℝ → ℝ) (h_smooth : ContDiff ℝ smooth H) (h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) : ∀ t, deriv (deriv H) t = deriv (deriv H) 0 * H t := by have h2 : ContDiff ℝ 2 H := by exact_mod_cast (contDiff_infty.mp h_smooth) 2 have hDiff : Differentiable ℝ H := h2.differentiable (by decide : (2 : WithTop ℕ∞) ≠ 0) have hCDiff1_H' : ContDiff ℝ 1 (deriv H) := by rw [show (2 : WithTop ℕ∞) = 1 + 1 from rfl] at h2 rw [contDiff_succ_iff_deriv] at h2; exact h2.2.2 have hDiffDeriv : Differentiable ℝ (deriv H) := hCDiff1_H'.differentiable (by decide : (1 : WithTop ℕ∞) ≠ 0) have hsh_add : ∀ (s v : ℝ), HasDerivAt (fun u => s + u) (1 : ℝ) v := fun s v => by have h := (hasDerivAt_id v).add_const s; simp only [id] at h rwa [show (fun u : ℝ => u + s) = fun u => s + u from funext fun u => add_comm u s] at h have hsh_sub : ∀ (s v : ℝ), HasDerivAt (fun u => s - u) (-1 : ℝ) v := fun s v => by have h1 : HasDerivAt (fun u : ℝ => -u) (-1 : ℝ) v := by have := (hasDerivAt_id v).neg; simp only [id] at this; exact this have h2 := h1.const_add s rwa [show (fun u : ℝ => s + -u) = fun u => s - u from funext fun u => by ring] at h2 intro t have h_feq : (fun u => H (t + u) + H (t - u)) = (fun u => 2 * H t * H u) := funext (h_dAl t) have key : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 = deriv (deriv (fun u => 2 * H t * H u)) 0 := congr_arg (fun f => deriv (deriv f) 0) h_feq have lhs_eq : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 = 2 * deriv (deriv H) t := by have h_plus : ∀ v, HasDerivAt (fun u => H (t + u)) (deriv H (t + v)) v := fun v => by have h := ((hDiff (t + v)).hasDerivAt).comp v (hsh_add t v) simp only [mul_one, Function.comp_def] at h; exact h have h_minus : ∀ v, HasDerivAt (fun u => H (t - u)) (-deriv H (t - v)) v := fun v => by have hcomp := ((hDiff (t - v)).hasDerivAt).comp v (hsh_sub t v) simp only [mul_neg, mul_one, Function.comp_apply] at hcomp; exact hcomp have hfirst : deriv (fun u => H (t + u) + H (t - u)) = fun v => deriv H (t + v) - deriv H (t - v) := funext fun v => by have h12 := ((h_plus v).add (h_minus v)).deriv rw [show (fun u => H (t + u)) + (fun u => H (t - u)) = fun u => H (t + u) + H (t - u) from by ext u; rfl] at h12; linarith [h12] have hd2p : HasDerivAt (fun v => deriv H (t + v)) (deriv (deriv H) t) 0 := by have := ((hDiffDeriv (t + 0)).hasDerivAt).comp 0 (hsh_add t 0) simpa using this have hd2m : HasDerivAt (fun v => deriv H (t - v)) (-deriv (deriv H) t) 0 := by have := ((hDiffDeriv (t - 0)).hasDerivAt).comp 0 (hsh_sub t 0) simpa using this rw [congr_fun (congr_arg deriv hfirst) 0, show (fun v => deriv H (t + v) - deriv H (t - v)) = (fun v => deriv H (t + v)) - (fun v => deriv H (t - v)) from rfl] linarith [(hd2p.sub hd2m).deriv] have rhs_eq : deriv (deriv (fun u => 2 * H t * H u)) 0 = 2 * H t * deriv (deriv H) 0 := by have hf : deriv (fun u => 2 * H t * H u) = fun v => 2 * H t * deriv H v := funext fun v => ((hDiff v).hasDerivAt.const_mul (2 * H t)).deriv rw [congr_fun (congr_arg deriv hf) 0, ((hDiffDeriv 0).hasDerivAt.const_mul (2 * H t)).deriv] rw [lhs_eq, rhs_eq] at key; linarithThe theorem named dAlembert_to_ODE_general in the framework's machine-checked library of formal theorems establishes the bridge between the functional equation and an ordinary differential equation. dAlembert_to_ODE_general · IndisputableMonolith/Cost/AczelProof.leanTHEOREM dAlembert_to_ODE_general · IndisputableMonolith/Cost/AczelProof.lean
private theorem dAlembert_to_ODE_general (H : ℝ → ℝ) (h_smooth : ContDiff ℝ smooth H) (h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) : ∀ t, deriv (deriv H) t = deriv (deriv H) 0 * H t := by have h2 : ContDiff ℝ 2 H := by exact_mod_cast (contDiff_infty.mp h_smooth) 2 have hDiff : Differentiable ℝ H := h2.differentiable (by decide : (2 : WithTop ℕ∞) ≠ 0) have hCDiff1_H' : ContDiff ℝ 1 (deriv H) := by rw [show (2 : WithTop ℕ∞) = 1 + 1 from rfl] at h2 rw [contDiff_succ_iff_deriv] at h2; exact h2.2.2 have hDiffDeriv : Differentiable ℝ (deriv H) := hCDiff1_H'.differentiable (by decide : (1 : WithTop ℕ∞) ≠ 0) have hsh_add : ∀ (s v : ℝ), HasDerivAt (fun u => s + u) (1 : ℝ) v := fun s v => by have h := (hasDerivAt_id v).add_const s; simp only [id] at h rwa [show (fun u : ℝ => u + s) = fun u => s + u from funext fun u => add_comm u s] at h have hsh_sub : ∀ (s v : ℝ), HasDerivAt (fun u => s - u) (-1 : ℝ) v := fun s v => by have h1 : HasDerivAt (fun u : ℝ => -u) (-1 : ℝ) v := by have := (hasDerivAt_id v).neg; simp only [id] at this; exact this have h2 := h1.const_add s rwa [show (fun u : ℝ => s + -u) = fun u => s - u from funext fun u => by ring] at h2 intro t have h_feq : (fun u => H (t + u) + H (t - u)) = (fun u => 2 * H t * H u) := funext (h_dAl t) have key : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 = deriv (deriv (fun u => 2 * H t * H u)) 0 := congr_arg (fun f => deriv (deriv f) 0) h_feq have lhs_eq : deriv (deriv (fun u => H (t + u) + H (t - u))) 0 = 2 * deriv (deriv H) t := by have h_plus : ∀ v, HasDerivAt (fun u => H (t + u)) (deriv H (t + v)) v := fun v => by have h := ((hDiff (t + v)).hasDerivAt).comp v (hsh_add t v) simp only [mul_one, Function.comp_def] at h; exact h have h_minus : ∀ v, HasDerivAt (fun u => H (t - u)) (-deriv H (t - v)) v := fun v => by have hcomp := ((hDiff (t - v)).hasDerivAt).comp v (hsh_sub t v) simp only [mul_neg, mul_one, Function.comp_apply] at hcomp; exact hcomp have hfirst : deriv (fun u => H (t + u) + H (t - u)) = fun v => deriv H (t + v) - deriv H (t - v) := funext fun v => by have h12 := ((h_plus v).add (h_minus v)).deriv rw [show (fun u => H (t + u)) + (fun u => H (t - u)) = fun u => H (t + u) + H (t - u) from by ext u; rfl] at h12; linarith [h12] have hd2p : HasDerivAt (fun v => deriv H (t + v)) (deriv (deriv H) t) 0 := by have := ((hDiffDeriv (t + 0)).hasDerivAt).comp 0 (hsh_add t 0) simpa using this have hd2m : HasDerivAt (fun v => deriv H (t - v)) (-deriv (deriv H) t) 0 := by have := ((hDiffDeriv (t - 0)).hasDerivAt).comp 0 (hsh_sub t 0) simpa using this rw [congr_fun (congr_arg deriv hfirst) 0, show (fun v => deriv H (t + v) - deriv H (t - v)) = (fun v => deriv H (t + v)) - (fun v => deriv H (t - v)) from rfl] linarith [(hd2p.sub hd2m).deriv] have rhs_eq : deriv (deriv (fun u => 2 * H t * H u)) 0 = 2 * H t * deriv (deriv H) 0 := by have hf : deriv (fun u => 2 * H t * H u) = fun v => 2 * H t * deriv H v := funext fun v => ((hDiff v).hasDerivAt.const_mul (2 * H t)).deriv rw [congr_fun (congr_arg deriv hf) 0, ((hDiffDeriv 0).hasDerivAt.const_mul (2 * H t)).deriv] rw [lhs_eq, rhs_eq] at key; linarithIt states: if H is infinitely differentiable and satisfies the d'Alembert equation, then for every t, the second derivative H''(t) equals H''(0)·H(t). dAlembert_to_ODE_general · IndisputableMonolith/Cost/AczelProof.leanTHEOREM dAlembert_contDiff_smooth · IndisputableMonolith/Cost/AczelProof.lean
private theorem dAlembert_contDiff_smooth (H : ℝ → ℝ) (h_one : H 0 = 1) (h_cont : Continuous H) (h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) : ContDiff ℝ smooth H := contDiff_infty.mpr (dAlembert_contDiff_nat H h_one h_cont h_dAl)The integration bootstrap shows that a merely continuous solution is automatically infinitely differentiable. dAlembert_contDiff_smooth · IndisputableMonolith/Cost/AczelProof.leanTHEOREM dAlembert_classification · IndisputableMonolith/Cost/AczelProof.lean
/-- **Aczél–Kannappan classification of the d'Alembert functional equation.** Any continuous H : ℝ → ℝ with H(0) = 1 satisfying H(t+u) + H(t−u) = 2·H(t)·H(u) is exactly one of: * the constant 1, * `Real.cosh (α·)` for some α ∈ ℝ, or * `Real.cos (α·)` for some α ∈ ℝ. Proof: continuity ⇒ C^∞ via the integration bootstrap (`dAlembert_contDiff_smooth`); C² + d'Alembert ⇒ H'' = c·H with c = H''(0) (`dAlembert_to_ODE_general`); ODE uniqueness in each branch of the trichotomy on c gives the explicit formula. -/ theorem dAlembert_classification (H : ℝ → ℝ) (h_one : H 0 = 1) (h_cont : Continuous H) (h_dAl : ∀ t u, H (t + u) + H (t - u) = 2 * H t * H u) : (∀ x, H x = 1) ∨ (∃ α : ℝ, ∀ x, H x = Real.cosh (α * x)) ∨ (∃ α : ℝ, ∀ x, H x = Real.cos (α * x)) := by have h_sm : ContDiff ℝ smooth H := dAlembert_contDiff_smooth H h_one h_cont h_dAl have h2 : ContDiff ℝ 2 H := by exact_mod_cast (contDiff_infty.mp h_sm) 2 have hDiff : Differentiable ℝ H := h2.differentiable (by decide : (2 : WithTop ℕ∞) ≠ 0) have h_H'0 : deriv H 0 = 0 := even_deriv_at_zero H (dAlembert_even H h_one h_dAl) hDiff.differentiableAt have h_ode := dAlembert_to_ODE_general H h_sm h_dAl set c := deriv (deriv H) 0 with hc_def have hDD : Differentiable ℝ (deriv H) := by rw [show (2 : WithTop ℕ∞) = 1 + 1 from rfl] at h2 exact (contDiff_succ_iff_deriv.mp h2).2.2.differentiable (by decide : (1 : WithTop ℕ∞) ≠ 0) by_cases hc_pos : 0 < c · -- c > 0: H = cosh(√c · t) right; left; refine ⟨Real.sqrt c, ?_⟩ have hsc_ne : Real.sqrt c ≠ 0 := ne_of_gt (Real.sqrt_pos.mpr hc_pos) let g : ℝ → ℝ := fun s => H (s / Real.sqrt c) have h_div : ∀ s, HasDerivAt (fun x => x / Real.sqrt c) (Real.sqrt c)⁻¹ s := fun s => by have := (hasDerivAt_id s).div_const (Real.sqrt c); simp only [id, one_div] at this; exact this have hg_d : ∀ s, HasDerivAt g (deriv H (s / Real.sqrt c) * (Real.sqrt c)⁻¹) s := fun s => (hDiff _).hasDerivAt.comp s (h_div s) have hg_ode : ∀ t, deriv (deriv g) t = g t := by intro s have hg1 : deriv g = fun s => deriv H (s / Real.sqrt c) * (Real.sqrt c)⁻¹ := funext fun s => (hg_d s).deriv have h_dd_g : HasDerivAt (deriv g) ((deriv (deriv H) (s / Real.sqrt c) * (Real.sqrt c)⁻¹) * (Real.sqrt c)⁻¹) s := by rw [hg1] exact ((hDD (s / Real.sqrt c)).hasDerivAt.comp s (h_div s)).mul_const _ rw [h_dd_g.deriv, h_ode (s / Real.sqrt c)] simp only [g] rw [show c * H (s / Real.sqrt c) * (Real.sqrt c)⁻¹ * (Real.sqrt c)⁻¹ = H (s / Real.sqrt c) * (c * ((Real.sqrt c)⁻¹ * (Real.sqrt c)⁻¹)) from by ring, show (Real.sqrt c)⁻¹ * (Real.sqrt c)⁻¹ = (Real.sqrt c * Real.sqrt c)⁻¹ from (mul_inv_rev _ _).symm, Real.mul_self_sqrt (le_of_lt hc_pos), mul_inv_cancel₀ (ne_of_gt hc_pos), mul_one] intro t have := ode_cosh_uniqueness_contdiff g (h2.comp (contDiff_id.div_const _)) hg_ode (by simp [g, h_one]) (by rw [(hg_d 0).deriv]; simp [h_H'0]) (Real.sqrt c * t) simp only [g, mul_div_cancel_left₀ _ hsc_ne] at this; exact this · by_cases hc_neg : c < 0 · -- c < 0: H = cos(√(−c) · t) right; right; refine ⟨Real.sqrt (-c), ?_⟩ set c' := -c have hsc_ne : Real.sqrt c' ≠ 0 := ne_of_gt (Real.sqrt_pos.mpr (neg_pos.mpr hc_neg)) let g : ℝ → ℝ := fun s => H (s / Real.sqrt c') have h_div : ∀ s, HasDerivAt (fun x => x / Real.sqrt c') (Real.sqrt c')⁻¹ s := fun s => by have := (hasDerivAt_id s).div_const (Real.sqrt c'); simp only [id, one_div] at this; exact this have hg_d : ∀ s, HasDerivAt g (deriv H (s / Real.sqrt c') * (Real.sqrt c')⁻¹) s := fun s => (hDiff _).hasDerivAt.comp s (h_div s) have hg_ode : ∀ t, deriv (deriv g) t = -(g t) := by intro s have hg1 : deriv g = fun s => deriv H (s / Real.sqrt c') * (Real.sqrt c')⁻¹ := funext fun s => (hg_d s).deriv have h_dd_g : HasDerivAt (deriv g) ((deriv (deriv H) (s / Real.sqrt c') * (Real.sqrt c')⁻¹) * (Real.sqrt c')⁻¹) s := by rw [hg1] exact ((hDD (s / Real.sqrt c')).hasDerivAt.comp s (h_div s)).mul_const _ rw [h_dd_g.deriv, h_ode (s / Real.sqrt c')] simp only [g, c'] rw [show c * H (s / Real.sqrt (-c)) * (Real.sqrt (-c))⁻¹ * (Real.sqrt (-c))⁻¹ = H (s / Real.sqrt (-c)) * (c * ((Real.sqrt (-c))⁻¹ * (Real.sqrt (-c))⁻¹)) from by ring, show (Real.sqrt (-c))⁻¹ * (Real.sqrt (-c))⁻¹ = (Real.sqrt (-c) * Real.sqrt (-c))⁻¹ from (mul_inv_rev _ _).symm, Real.mul_self_sqrt (le_of_lt (neg_pos.mpr hc_neg)), show c * (-c)⁻¹ = -(1 : ℝ) from by have hc_ne : c ≠ 0 := ne_of_lt hc_neg field_simp] ring intro t have := ode_cos_uniqueness g (h2.comp (contDiff_id.div_const _)) hg_ode (by simp [g, h_one]) (by rw [(hg_d 0).deriv]; simp [h_H'0]) (Real.sqrt c' * t) simp only [g, mul_div_cancel_left₀ _ hsc_ne] at this; exact this · -- c = 0: H ≡ 1 left have hc0 : c = 0 := le_antisymm (not_lt.mp hc_pos) (not_lt.mp hc_neg) have h_H'_zero : ∀ t, deriv H t = 0 := by have := is_const_of_deriv_eq_zero hDD (fun t => by rw [h_ode t, hc0, zero_mul]) intro t; have := this t 0; simp [h_H'0] at this; exact this intro t have := is_const_of_deriv_eq_zero hDiff h_H'_zero t 0 simp [h_one] at this; exact thisThe classification theorem, which is proved separately, is what states the trichotomy of solutions under the continuity assumption. dAlembert_classification · IndisputableMonolith/Cost/AczelProof.lean