1-- Real analysis: the derivative as a function2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Real.Analysis.Derivative8import Set.Choice9import Differentiation1011-- Section: Derivative12-- The derivative of f at X is the number D with HasDerivativeAt(f, D, X)13-- when f is differentiable there, and zero otherwise.14defchoose derivativeValue (f : Set, X : Real) (D ∈ ℝ) :=15 HasDerivativeAt(f, D, X) ∨ (¬DifferentiableAt(f, X) ∧ D = (0:R))16proof17havesplit : DifferentiableAt(f, X) ∨¬DifferentiableAt(f, X) bytauto18casessplitwith differentiable | nowhere19 . obtain⟨D, realD, hasDerivative⟩:= differentiable20witness D21refine⟨realD, _⟩22left23exact hasDerivative24 . have realZeroMember : (0:R) ∈ ℝ byexact realZero.real25witness (0:R)26refine⟨realZeroMember, _⟩27right28refine⟨nowhere, _⟩29rfl3031defgraph derivative (f : Set) (X ∈ ℝ) : ℝ := derivativeValue(f, X)32proof33obtain⟨realD, property⟩:= derivativeValue.selected at f, X34exact realD3536-- The derivative is written with a prime, f′, and its value f′(X); a37-- doubled prime is the second derivative, f″.38notationpostfix95"′"=> derivative3940theorem derivative.of_has_derivative (f : Set) (D X : Real)41requires hasDerivative : HasDerivativeAt(f, D, X)42shows f′(X) = D43proof44have value := derivative.value at f, X45obtain⟨realD, property⟩:= derivativeValue.selected at f, X46rw value47cases property with chosen | nowhere48 . exact HasDerivativeAt.unique with chosen, hasDerivative49 . obtain⟨notDifferentiable, zero⟩:= nowhere50exfalso51apply notDifferentiable52exact HasDerivativeAt.differentiable_at with hasDerivative5354theorem derivative.has_derivative_at (f : Set) (X : Real)55requires differentiable : DifferentiableAt(f, X)56shows HasDerivativeAt(f, f′(X), X)57proof58have value := derivative.value at f, X59obtain⟨realD, property⟩:= derivativeValue.selected at f, X60rw value61cases property with chosen | nowhere62 . exact chosen63 . obtain⟨notDifferentiable, zero⟩:= nowhere64exfalso65exact notDifferentiable with differentiable6667theorem derivative.real (f : Set) (X : Real)68showsReal(f′(X))69proof70have realX : X ∈ ℝ bysimp [Real]71have function := derivative.function at f72exact FunctionBetween.apply_closed with function, realX7374-- Section: IteratedDerivative75def iteratedDerivative (f : Set, k : Nat) →Set76| f, zero => f77| f, succ(k) => derivative(iteratedDerivative(f, k))7879-- The k-th derivative is written f⁽ᵏ⁾, with the index in superscript, so80-- f⁽ⁿ⁺¹⁾(C) is iteratedDerivative(f, n + 1)(C).81notationpostfix95"⁽_⁾"=> iteratedDerivative8283theorem iteratedDerivative.zero (f : Set)84shows f⁽⁰⁾ = f85proof86simp [iteratedDerivative]8788theorem iteratedDerivative.succ (f : Set, k : Nat)89shows f⁽ᵏ⁺¹⁾ = f⁽ᵏ⁾′90proof91have one : k +1= succ(k) := add.right_one with*92rw one93simp [iteratedDerivative]9495theorem iteratedDerivative.shift (f : Set, k : Nat)96shows f⁽ᵏ⁺¹⁾ = (f′)⁽ᵏ⁾97proof98induction k99| zero =>100rw [iteratedDerivative.succ, iteratedDerivative.zero,101 iteratedDerivative.zero]102rfl103| succ(j) using ih =>104have one : j +1= succ(j) := add.right_one with*105rw← one106rw [iteratedDerivative.succ, ih, iteratedDerivative.succ]107rfl108109theorem iteratedDerivative.function (f : Set, k : Nat)110requires function : f : ℝ → ℝ111shows f⁽ᵏ⁾ : ℝ → ℝ112proof113induction k114| zero =>115rw iteratedDerivative.zero116exact function117| succ(j) using ih =>118have one : j +1= succ(j) := add.right_one with*119rw← one120rw iteratedDerivative.succ121exact derivative.function at iteratedDerivative(f, j)122123-- Section: DerivativeLaws124-- Multiplying by a constant scales the derivative.125theorem HasDerivativeAt.scale (g : Set) (K E C : Real)126requires derivativeG : HasDerivativeAt(g, E, C)127shows HasDerivativeAt(pointwiseMul(constantRealFunction(K), g), K * E, C)128proof129have gFunction := HasDerivativeAt.function with derivativeG130have constantDerivative := constantRealFunction.has_derivative_at at K, C131have raw := HasDerivativeAt.mul with132 realZero.real, constantDerivative, derivativeG133have realC : C ∈ ℝ bysimp [Real]134have gC := FunctionBetween.apply_closed with gFunction, realC135have typedGC : Real(g(C)) byexact gC136have constantValue := constantRealFunction.value at K, C137have result : realZero * g(C) + constantRealFunction(K)(C) * E = K * E138rw constantValue139ring140have view : realAddValue(realMulValue(realZero, g(C)),141 realMulValue(constantRealFunction(K)(C), E)) =142 realZero * g(C) + constantRealFunction(K)(C) * E143unfold realAddValue144unfold realMulValue145unfold call2146rfl147 rwa [view, result] at raw148149theorem derivative.scale (g : Set) (K C : Real)150requires differentiable : DifferentiableAt(g, C)151shows pointwiseMul(constantRealFunction(K), g)′(C) = K * g′(C)152proof153have derivativeG := derivative.has_derivative_at with differentiable154have typedValue := derivative.real at g, C155have scaled := HasDerivativeAt.scale at g, K, derivative(g)(C), C with156 typedValue, derivativeG157exact derivative.of_has_derivative with scaled158159theorem HasDerivativeAt.congr_value (f : Set) (D E A : Real)160requires hasDerivative : HasDerivativeAt(f, D, A)161requires equal : D = E162shows HasDerivativeAt(f, E, A)163proof164 rwa equal at hasDerivative165166-- The product rule with its value written in the usual notation.167theorem HasDerivativeAt.mul_value (f g : Set) (D E A : Real)168requires derivativeF : HasDerivativeAt(f, D, A)169requires derivativeG : HasDerivativeAt(g, E, A)170requires typedFA : Real(f(A))171requires typedGA : Real(g(A))172shows HasDerivativeAt(pointwiseMul(f, g), D * g(A) + f(A) * E, A)173proof174have raw := HasDerivativeAt.mul with derivativeF, derivativeG175have view : realAddValue(realMulValue(D, g(A)), realMulValue(f(A), E)) =176 D * g(A) + f(A) * E177unfold realAddValue178unfold realMulValue179unfold call2180rfl181 rwa view at raw182