Documentation

LeanCert.Engine.RootFinding.Bisection

Root Finding: Bisection Algorithm #

This file implements the bisection method for root isolation.

Main definitions #

Main theorems #

All bisection theorems are FULLY PROVED with no sorry.

Bisection result structure #

Result of bisection root finding

Instances For

    Bisection algorithm #

    noncomputable def LeanCert.Engine.bisectRootGo (e : Core.Expr) (tol : ) (maxIter : ) (work : List (Core.IntervalRat × RootStatus)) (iter : ) (done : List (Core.IntervalRat × RootStatus)) :

    Worker function for bisection root finding.

    Processes a worklist, discarding intervals that provably contain no roots, bisecting intervals that may contain roots until they are small enough.

    Lifted to top-level so we can state correctness lemmas about it.

    Equations
    Instances For
      noncomputable def LeanCert.Engine.bisectRoot (e : Core.Expr) (I : Core.IntervalRat) (maxIter : ) (tol : ) (_htol : 0 < tol) :

      Bisection root finding.

      Repeatedly bisects the interval, discarding subintervals that provably contain no roots.

      Equations
      Instances For

        Bisection correctness #

        Key lemma: checkRootStatus returns noRoot only when excludesZero is true

        Key lemma: checkRootStatus returns hasRoot only when signChange is true

        Invariants for bisection proofs #

        Invariant for bisection: every interval with hasRoot status has signChange = true. Note: noRoot intervals are discarded by the algorithm, so they never appear in output.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For

          Invariant for tracking sub-intervals: all intervals in the list are sub-intervals of I

          Equations
          Instances For

            The invariant holds for the initial work list

            BisectInv is preserved when adding a hasRoot interval with signChange = true

            BisectInv is preserved when adding non-hasRoot intervals

            theorem LeanCert.Engine.bisect_inv_append (e : Core.Expr) (l₁ l₂ : List (Core.IntervalRat × RootStatus)) (h₁ : BisectInv e l₁) (h₂ : BisectInv e l₂) :
            BisectInv e (l₁ ++ l₂)

            BisectInv holds for list append

            SubIntervalInv holds for list append

            theorem LeanCert.Engine.subinterval_inv_cons (I J : Core.IntervalRat) (s : RootStatus) (pairs : List (Core.IntervalRat × RootStatus)) (hInv : SubIntervalInv I pairs) (hJ : I.lo J.lo J.hi I.hi) :
            SubIntervalInv I ((J, s) :: pairs)

            SubIntervalInv is preserved when adding a sub-interval

            theorem LeanCert.Engine.bisect_subinterval (I J : Core.IntervalRat) (hJ : I.lo J.lo J.hi I.hi) :
            match J.bisect with | (J₁, J₂) => (I.lo J₁.lo J₁.hi I.hi) I.lo J₂.lo J₂.hi I.hi

            Bisecting preserves the sub-interval property

            Main correctness proofs #

            theorem LeanCert.Engine.go_noRoot_not_in_output (e : Core.Expr) (tol : ) (maxIter : ) (work : List (Core.IntervalRat × RootStatus)) (iter : ) (done : List (Core.IntervalRat × RootStatus)) (hDone : ∀ (J : Core.IntervalRat) (s : RootStatus), (J, s) dones RootStatus.noRoot) (hWork : ∀ (J : Core.IntervalRat) (s : RootStatus), (J, s) works RootStatus.noRoot) (J : Core.IntervalRat) (s : RootStatus) :
            (J, s) (bisectRootGo e tol maxIter work iter done).intervalss RootStatus.noRoot

            noRoot never appears in output - the algorithm discards such intervals. We prove this by induction on iter.

            theorem LeanCert.Engine.go_hasRoot_has_signChange (e : Core.Expr) (tol : ) (maxIter : ) (work : List (Core.IntervalRat × RootStatus)) (iter : ) (done : List (Core.IntervalRat × RootStatus)) (hWork : BisectInv e work) (hDone : BisectInv e done) :
            BisectInv e (bisectRootGo e tol maxIter work iter done).intervals

            Every hasRoot interval in output has signChange = true. We prove this by induction on iter. Note: We need BisectInv for work too, since at iter=0 we output work as-is.

            theorem LeanCert.Engine.go_subinterval (e : Core.Expr) (tol : ) (maxIter : ) (I : Core.IntervalRat) (work : List (Core.IntervalRat × RootStatus)) (iter : ) (done : List (Core.IntervalRat × RootStatus)) (hWork : SubIntervalInv I work) (hDone : SubIntervalInv I done) :
            SubIntervalInv I (bisectRootGo e tol maxIter work iter done).intervals

            Every interval in output is a sub-interval of the original. We prove this by induction on iter.

            theorem LeanCert.Engine.bisectRoot_hasRoot_correct (e : Core.Expr) (hsupp : ExprSupported e) (I : Core.IntervalRat) (maxIter : ) (tol : ) (htol : 0 < tol) (hCont : ContinuousOn (fun (x : ) => Core.Expr.eval (fun (x_1 : ) => x) e) (Set.Icc I.lo I.hi)) :
            have result := bisectRoot e I maxIter tol htol; ∀ (J : Core.IntervalRat) (s : RootStatus), (J, s) result.intervalss = RootStatus.hasRootxJ, Core.Expr.eval (fun (x_1 : ) => x) e = 0

            If bisection returns hasRoot for an interval, there exists a root (by IVT).

            The proof works by showing that every (J, hasRoot) pair in the output has signChange e J = true, then applying signChange_correct.

            Note about noRoot: The algorithm discards noRoot intervals, so they never appear in the output. Thus bisectRoot_noRoot_correct is vacuously true.

            theorem LeanCert.Engine.bisectRoot_noRoot_correct (e : Core.Expr) (_hsupp : ExprSupported e) (I : Core.IntervalRat) (maxIter : ) (tol : ) (htol : 0 < tol) :
            have result := bisectRoot e I maxIter tol htol; ∀ (J : Core.IntervalRat) (s : RootStatus), (J, s) result.intervalss = RootStatus.noRootxJ, Core.Expr.eval (fun (x_1 : ) => x) e 0

            If bisection returns noRoot for an interval, there really is no root.

            Note: The bisection algorithm discards noRoot intervals - when checkRootStatus returns noRoot, we call go rest n done without adding J to done. So noRoot never appears in the output intervals list.

            This means the theorem is vacuously true: there are no (J, noRoot) pairs in the output.