introvoyz041/TaoAnalysisBench huggingface dataset:
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter
open scoped BigOperators

namespace TaoBench

namespace PiecewiseConstantWith

/--
Mathlib-style reformulation of Tao's Proposition 11.2.13:

Let `f : ℝ → ℝ` and let `[a, b]` be a closed, bounded interval.
Suppose we have two finite partitions `P` and `P'` of `[a, b]` into
(sub)intervals `[J.1, J.2]` (encoded as pairs `J : ℝ × ℝ`), such that:

* every point of `[a, b]` lies in a unique subinterval of `P`, and likewise for `P'`;
* on each subinterval of `P` (resp. `P'`), the function `f` is constant with
  value `cP J` (resp. `cP' J`).

Then the sum over the partition of “(constant value on the piece) × (length of the
piece)” is independent of the chosen partition.
-/
theorem integ_eq
  {f : ℝ → ℝ} {a b : ℝ} (h_ab : a ≤ b)
  (P P' : Finset (ℝ × ℝ))
  (cP cP' : (ℝ × ℝ) → ℝ)
  (hPcov :
    ∀ x, x ∈ Set.Icc a b →
      ∃! J : ℝ × ℝ, J ∈ P ∧ x ∈ Set.Icc J.1 J.2)
  (hP'cov :
    ∀ x, x ∈ Set.Icc a b →
      ∃! J : ℝ × ℝ, J ∈ P' ∧ x ∈ Set.Icc J.1 J.2)
  (hPconst :
    ∀ J ∈ P, ∀ x ∈ Set.Icc J.1 J.2, f x = cP J)
  (hP'const :
    ∀ J ∈ P', ∀ x ∈ Set.Icc J.1 J.2, f x = cP' J) :
  ∑ J ∈ P, cP J * max (J.2 - J.1) 0 =
  ∑ J ∈ P', cP' J * max (J.2 - J.1) 0 := by
end PiecewiseConstantWith

end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
theorem Chapter11.PiecewiseConstantWith.mono
  {f : ℝ → ℝ} {I : Set ℝ} {P P' : Set (Set ℝ)}
  (hPP' : ∀ J ∈ P', ∃ K ∈ P, J ⊆ K)
  (hP   : ∀ K ∈ P, ∃ c : ℝ, ∀ x ∈ K, f x = c) :
  ∀ J ∈ P', ∃ c : ℝ, ∀ x ∈ J, f x = c := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
theorem RS_integ_of_uniform_cts
  {a b : ℝ} {f : ℝ → ℝ} (hf : UniformContinuousOn f (Set.Icc a b))
  {α : ℝ → ℝ} (hα : Monotone α) :
  ∃ (β : StieltjesFunction),
    (∀ x : ℝ, (β x : ℝ) = lim ((nhdsWithin x (Set.Ioi x)).map α)) ∧
    IntervalIntegrable f β.measure a b := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
theorem RS_integ_with_sign
  (f : ℝ → ℝ)
  (hf : ContinuousOn f (Set.Icc (-1 : ℝ) 1)) :
  MeasureTheory.IntegrableOn f (Set.Icc (-1 : ℝ) 1)
    (2 • (MeasureTheory.Measure.dirac (0 : ℝ))) ∧
  ∫ x in Set.Icc (-1 : ℝ) 1, f x ∂(2 • (MeasureTheory.Measure.dirac (0 : ℝ))) = 2 * f 0 := by
end TaoBench
import Mathlib.Data.Real.Basic
import Mathlib.Analysis.Calculus.Deriv.Basic

/-!
Self-contained slice for Chapter11 Section 11.9 target lemma.
-/

namespace Chapter11

inductive BoundedInterval where
  | Ioo (a b:ℝ) : BoundedInterval
  | Icc (a b:ℝ) : BoundedInterval
  | Ioc (a b:ℝ) : BoundedInterval
  | Ico (a b:ℝ) : BoundedInterval

/-- There is a technical issue in that this coercion is not injective: the empty set is represented by multiple bounded intervals.  This causes some of the statements in this section to be a little uglier than necessary.-/
@[coe]
def BoundedInterval.toSet (I: BoundedInterval) : Set ℝ := match I with
  | Ioo a b => .Ioo a b
  | Icc a b => .Icc a b
  | Ioc a b => .Ioc a b
  | Ico a b => .Ico a b

instance BoundedInterval.inst_coeSet : Coe BoundedInterval (Set ℝ) where
  coe := toSet

instance BoundedInterval.instMembership : Membership ℝ BoundedInterval where
  mem I x := x ∈ (I:Set ℝ)

/-- Definition 11.9.3.  We drop the requirement that x be a limit point as this makes
    the Lean arguments slightly cleaner -/
abbrev AntiderivOn (F f: ℝ → ℝ) (I: BoundedInterval) :=
  DifferentiableOn ℝ F I ∧ ∀ x ∈ I, HasDerivWithinAt F (f x) I x

/-- Lemma 11.9.5 / Exercise 11.9.2 -/
theorem antideriv_eq_antideriv_add_const {I:BoundedInterval} {f F G : ℝ → ℝ}
  (hfF: AntiderivOn F f I) (hfG: AntiderivOn G f I) :
   ∃ C, ∀ x ∈ (I:Set ℝ), F x = G x + C := by
end Chapter11
import Mathlib
import Analysis.Section_7_3
import Analysis.Tags.Section_7_3
import Analysis.Section_9_4
import Analysis.Tags.Section_9_4
import Analysis.Section_9_8
import Analysis.Tags.Section_9_8
import Analysis.Section_10_1
import Analysis.Tags.Section_10_1
import Analysis.Section_10_2
import Analysis.Tags.Section_10_2
import Analysis.Section_11_6
import Analysis.Tags.Section_11_6
import Analysis.Section_11_8
import Analysis.Tags.Section_11_8

namespace Chapter11

-- <CONTEXT>
inductive BoundedInterval where
  | Ioo (a b:ℝ) : BoundedInterval
  | Icc (a b:ℝ) : BoundedInterval
  | Ioc (a b:ℝ) : BoundedInterval
  | Ico (a b:ℝ) : BoundedInterval

@[coe]
def BoundedInterval.toSet (I: BoundedInterval) : Set ℝ := match I with
  | Ioo a b => .Ioo a b
  | Icc a b => .Icc a b
  | Ioc a b => .Ioc a b
  | Ico a b => .Ico a b

instance BoundedInterval.inst_coeSet : Coe BoundedInterval (Set ℝ) where
  coe := toSet

instance BoundedInterval.instMembership : Membership ℝ BoundedInterval where
  mem I x := x ∈ (I:Set ℝ)

instance BoundedInterval.instSubset : HasSubset BoundedInterval where
  Subset I J := ∀ x, x ∈ I → x ∈ J

abbrev AntiderivOn (F f: ℝ → ℝ) (I: BoundedInterval) :=
  DifferentiableOn ℝ F I ∧ ∀ x ∈ I, HasDerivWithinAt F (f x) I x

theorem AntiderivOn.mono {F f: ℝ → ℝ} {I J: BoundedInterval}
  (h: AntiderivOn F f I) (hIJ: J ⊆ I) : AntiderivOn F f J := by
  sorry

open Real

noncomputable abbrev F_11_9 : ℝ → ℝ := fun x ↦ if x = 0 then 0 else x^2 * sin (1 / x^3)
-- </CONTEXT>
-- <TARGET_THEOREM>
theorem antideriv_eq_antideriv_add_const {I:BoundedInterval} {f F G : ℝ → ℝ}
  (hfF: AntiderivOn F f I) (hfG: AntiderivOn G f I) :
   ∃ C, ∀ x ∈ (I:Set ℝ), F x = G x + C := by
-- </TARGET_THEOREM>

end Chapter11
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
theorem antideriv_eq_antideriv_add_const
  {s : Set ℝ} {f F G : ℝ → ℝ}
  (hs : ∃ a b : ℝ, s = Ioo a b ∨ s = Icc a b ∨ s = Ioc a b ∨ s = Ico a b)
  (hfF : DifferentiableOn ℝ F s ∧ ∀ x ∈ s, HasDerivWithinAt F (f x) s x)
  (hfG : DifferentiableOn ℝ G s ∧ ∀ x ∈ s, HasDerivWithinAt G (f x) s x) :
  ∃ C, ∀ x ∈ s, F x = G x + C := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench

/-- If a real function is bounded and monotone on a bounded interval (open, closed,
or half-open), then it is (Lebesgue) integrable on that interval. -/
theorem integ_of_bdd_monotone
  {s : Set ℝ} {f : ℝ → ℝ}
  (hs : ∃ a b : ℝ,
    s = Icc a b ∨ s = Ioc a b ∨ s = Ico a b ∨ s = Ioo a b)
  (hbound : ∃ M : ℝ, ∀ x ∈ s, |f x| ≤ M)
  (hf : MonotoneOn f s) :
  MeasureTheory.IntegrableOn f s := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench

/--
Tao's Proposition 11.5.6 / Exercise 11.5.1, translated to Mathlib:

A bounded, piecewise continuous real-valued function on a bounded real interval
is integrable (here: Lebesgue–Bochner interval integrable on `[a, b]`).

- `hbound` says `f` is bounded on the closed interval `Icc a b`.
- `hf` says there is a finite, strictly increasing sequence of points from `a`
  to `b` such that `f` is continuous on each closed subinterval between
  consecutive partition points.
- The conclusion is that `f` is `IntervalIntegrable` on `[a, b]` with respect
  to Lebesgue measure.
-/
theorem integ_of_bdd_piecewise_cts {a b : ℝ} {f : ℝ → ℝ}
  (hbound : ∃ M : ℝ, ∀ x ∈ Icc a b, |f x| ≤ M)
  (hf :
    ∃ (n : ℕ) (x : Fin (n + 1) → ℝ),
      x 0 = a ∧
      x (Fin.last n) = b ∧
      StrictMono x ∧
      ∀ (i : Fin n),
        ContinuousOn f (Icc (x (Fin.castSucc i)) (x i.succ)))
  : IntervalIntegrable f MeasureTheory.volume a b := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench

/-- Proposition 11.10.1 (Integration by parts formula), Mathlib version. -/
theorem integ_of_mul_deriv
  {a b : ℝ} (hab : a ≤ b) {F G : ℝ → ℝ}
  (hF : DifferentiableOn ℝ F (Icc a b))
  (hG : DifferentiableOn ℝ G (Icc a b))
  (hF' : MeasureTheory.IntegrableOn (derivWithin F (Icc a b)) (Icc a b))
  (hG' : MeasureTheory.IntegrableOn (derivWithin G (Icc a b)) (Icc a b)) :
  ∫ x in a..b, F x * derivWithin G (Icc a b) x =
    F b * G b - F a * G a -
      ∫ x in a..b, G x * derivWithin F (Icc a b) x := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
theorem integ_of_piecewise_const
  {f : ℝ → ℝ} {n : ℕ} {x c : ℕ → ℝ}
  (hmono : Monotone x)
  (hf : ∀ j < n, ∀ y ∈ Icc (x j) (x (j+1)), f y = c j) :
  MeasureTheory.IntegrableOn f (Icc (x 0) (x n)) MeasureTheory.volume ∧
  (∫ y in Icc (x 0) (x n), f y ∂MeasureTheory.volume) =
    Finset.sum (Finset.range n) (fun j => c j * (x (j+1) - x j)) := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
theorem integ_zero {a b : ℝ} (hab : a ≤ b) (f : ℝ → ℝ)
  (hf : ContinuousOn f (Icc a b))
  (hnonneg : ∀ x ∈ Icc a b, 0 ≤ f x)
  (hinteg : ∫ x in a..b, f x = 0) :
  ∀ x ∈ Icc a b, f x = 0 := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
 theorem upper_integ_le_upper_sum
    {f : ℝ → ℝ} {I : Set ℝ}
    (hf : ∃ M : ℝ, ∀ x ∈ I, |f x| ≤ M)
    (hI : ∃ a b : ℝ,
      I = Set.Icc a b ∨ I = Set.Ioc a b ∨ I = Set.Ico a b ∨ I = Set.Ioo a b)
    (P : Finset (Set ℝ))
    (hP_exists_unique : ∀ x ∈ I, ∃! J : Set ℝ, J ∈ P ∧ x ∈ J)
    (hP_subset : ∀ J ∈ P, J ⊆ I)
    (hP_intervals : ∀ J ∈ P, ∃ a b : ℝ,
      J = Set.Icc a b ∨ J = Set.Ioc a b ∨ J = Set.Ico a b ∨ J = Set.Ioo a b) :
    sInf
        ((fun g : ℝ → ℝ =>
            MeasureTheory.integral (MeasureTheory.volume.restrict I) g) ''
          {g : ℝ → ℝ |
            (∀ x ∈ I, f x ≤ g x) ∧
              (∃ Q : Finset (Set ℝ),
                (∀ x ∈ I, ∃! J : Set ℝ, J ∈ Q ∧ x ∈ J) ∧
                  (∀ J ∈ Q, J ⊆ I) ∧
                    (∀ J ∈ Q, ∃ c : ℝ, ∀ x ∈ J, g x = c) ∧
                    (∀ J ∈ Q, ∃ a b : ℝ,
                      J = Set.Icc a b ∨ J = Set.Ioc a b ∨ J = Set.Ico a b ∨
                        J = Set.Ioo a b))})
      ≤
      Finset.sum P (fun J => (sSup (f '' J)) * (MeasureTheory.volume J).toReal) := by
end TaoBench
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench
theorem upper_riemann_sum_le
  {f g : ℝ → ℝ} {a b : ℝ}
  (n : ℕ)
  (pts : ℕ → ℝ)
  (h_mono : StrictMono pts)
  (h0 : pts 0 = a)
  (hn : pts n = b)
  (hf : ∃ M : ℝ, ∀ x ∈ Icc a b, |f x| ≤ M)
  (hgf : ∀ x ∈ Icc a b, f x ≤ g x)
  (hg : ∃ (m : ℕ) (q : ℕ → ℝ)
            (hq_mono : StrictMono q)
            (hq0 : q 0 = a)
            (hqm : q m = b)
            (c : ℕ → ℝ),
          ∀ (k : ℕ), k < m → ∀ x, x ∈ Icc (q k) (q (k+1)) → g x = c k)
  :
  Finset.sum (Finset.range n)
    (fun k =>
      (sSup (f '' Icc (pts k) (pts (k+1)))) *
        ((pts (k+1)) - (pts k)))
  ≤
  MeasureTheory.integral
    (MeasureTheory.Measure.restrict MeasureTheory.volume (Icc a b)) g := by
end TaoBench
import Mathlib.Tactic
import Mathlib.Data.Real.Basic
import Mathlib.Topology.Instances.Irrational

/-!
Self-contained extraction for the target theorem from Section 11.8.
-*/

namespace Chapter11

/-- Bounded intervals (from Section 11.1) -/
inductive BoundedInterval where
  | Ioo (a b:ℝ) : BoundedInterval
  | Icc (a b:ℝ) : BoundedInterval
  | Ioc (a b:ℝ) : BoundedInterval
  | Ico (a b:ℝ) : BoundedInterval

open BoundedInterval

/-- Coercion to sets (from Section 11.1). -/
@[coe]
def BoundedInterval.toSet (I: BoundedInterval) : Set ℝ := match I with
  | Ioo a b => .Ioo a b
  | Icc a b => .Icc a b
  | Ioc a b => .Ioc a b
  | Ico a b => .Ico a b

instance BoundedInterval.inst_coeSet : Coe BoundedInterval (Set ℝ) where
  coe := toSet

instance BoundedInterval.instEmpty : EmptyCollection BoundedInterval where
  emptyCollection := Ioo 0 0

@[simp]
theorem BoundedInterval.coe_empty : ((∅ : BoundedInterval):Set ℝ) = ∅ := by
  simp [toSet]

/-- Endpoints (from Section 11.1). -/
abbrev BoundedInterval.a (I: BoundedInterval) : ℝ := match I with
  | Ioo a _ => a
  | Icc a _ => a
  | Ioc a _ => a
  | Ico a _ => a

abbrev BoundedInterval.b (I: BoundedInterval) : ℝ := match I with
  | Ioo _ b => b
  | Icc _ b => b
  | Ioc _ b => b
  | Ico _ b => b

/-- Length (from Section 11.1). -/
abbrev BoundedInterval.length (I: BoundedInterval) : ℝ := max (I.b - I.a) 0

/-- Using ||ₗ subscript here to not override || (from Section 11.1). -/
macro:max atomic("|" noWs) a:term noWs "|ₗ" : term => `(BoundedInterval.length $a)

/-- Left and right limits (from Section 11.8). A junk value is assigned if the limit does not exist. -/
noncomputable abbrev right_lim (f: ℝ → ℝ) (x₀:ℝ) : ℝ := lim ((nhdsWithin x₀ (.Ioi x₀)).map f)

noncomputable abbrev left_lim (f: ℝ → ℝ) (x₀:ℝ) : ℝ := lim ((nhdsWithin x₀ (.Iio x₀)).map f)

/-- Definition 11.8.1: α-length. -/
noncomputable abbrev α_length (α: ℝ → ℝ) (I: BoundedInterval) : ℝ := match I with
| Icc a b => if a ≤ b then (right_lim α b) - (left_lim α a) else 0
| Ico a b => if a ≤ b then (left_lim α b) - (left_lim α a) else 0
| Ioc a b => if a ≤ b then (right_lim α b) - (right_lim α a) else 0
| Ioo a b => if a < b then (left_lim α b) - (right_lim α a) else 0

notation3:max α"["I"]ₗ" => α_length α I

/-- Example 11.8.3 - target theorem. -/
@[simp]
theorem α_len_of_id (I: BoundedInterval) : (fun x ↦ x)[I]ₗ = |I|ₗ := by
end Chapter11
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench

namespace Chapter11
@[simp]
theorem α_len_of_id (a b : ℝ) :
    (if a ≤ b then
        lim ((nhdsWithin b (Ioi b)).map (fun x : ℝ => x)) -
          lim ((nhdsWithin a (Iio a)).map (fun x : ℝ => x))
      else 0) = max (b - a) 0 ∧
    (if a ≤ b then
        lim ((nhdsWithin b (Iio b)).map (fun x : ℝ => x)) -
          lim ((nhdsWithin a (Iio a)).map (fun x : ℝ => x))
      else 0) = max (b - a) 0 ∧
    (if a ≤ b then
        lim ((nhdsWithin b (Ioi b)).map (fun x : ℝ => x)) -
          lim ((nhdsWithin a (Ioi a)).map (fun x : ℝ => x))
      else 0) = max (b - a) 0 ∧
    (if a < b then
        lim ((nhdsWithin b (Iio b)).map (fun x : ℝ => x)) -
          lim ((nhdsWithin a (Ioi a)).map (fun x : ℝ => x))
      else 0) = max (b - a) 0 := by
end Chapter11

end TaoBench
namespace Chapter2

/--
  Assumption 2.6 (Existence of natural numbers).  Here we use an explicit construction of the
  natural numbers (using an inductive type).  For a more axiomatic approach, see the epilogue to
  this chapter.
-/
inductive Nat where
| zero : Nat
| succ : Nat → Nat
deriving Repr, DecidableEq  -- this allows `decide` to work on `Nat`

/-- Axiom 2.1 (0 is a natural number) -/
instance Nat.instZero : Zero Nat := ⟨ zero ⟩

/-- Axiom 2.2 (Successor of a natural number is a natural number) -/
postfix:100 "++" => Nat.succ

/--
  Recursion. Analogous to the inbuilt Mathlib method `Nat.rec` associated to
  the Mathlib natural numbers
-/
abbrev Nat.recurse (f: Nat → Nat → Nat) (c: Nat) : Nat → Nat := fun n ↦ match n with
| 0 => c
| n++ => f n (recurse f c n)

/-- Definition 2.2.1. (Addition of natural numbers).
    Compare with Mathlib's `Nat.add` -/
abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum ↦ sum++) m n

/-- This instance allows for the `+` notation to be used for natural number addition. -/
instance Nat.instAdd : Add Nat where
  add := add

/-- Proposition 2.2.5 (Addition is associative) / Exercise 2.2.1
    Compare with Mathlib's `Nat.add_assoc`. -/
theorem Nat.add_assoc (a b c:Nat) : (a + b) + c = a + (b + c) := by
end Chapter2
import Mathlib
import Analysis.Section_2_1
import Analysis.Tags.Section_2_1

namespace Chapter2

-- <CONTEXT>
inductive Nat where
| zero : Nat
| succ : Nat → Nat
deriving Repr, DecidableEq

instance Nat.instZero : Zero Nat := ⟨ zero ⟩

postfix:100 "++" => Nat.succ

instance Nat.instOfNat {n:_root_.Nat} : OfNat Nat n where
  ofNat := _root_.Nat.rec 0 (fun _ n ↦ n++) n

instance Nat.instOne : One Nat := ⟨ 1 ⟩

abbrev Nat.recurse (f: Nat → Nat → Nat) (c: Nat) : Nat → Nat := fun n ↦ match n with
| 0 => c
| n++ => f n (recurse f c n)

abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum ↦ sum++) m n

instance Nat.instAdd : Add Nat where
  add := add

@[simp]
theorem Nat.zero_add (m: Nat) : 0 + m = m := by
  sorry

theorem Nat.succ_add (n m: Nat) : n++ + m = (n+m)++ := by
  sorry

theorem Nat.one_add (m:Nat) : 1 + m = m++ := by
  sorry

theorem Nat.two_add (m:Nat) : 2 + m = (m++)++ := by
  sorry

@[simp]
lemma Nat.add_zero (n:Nat) : n + 0 = n := by
  sorry

lemma Nat.add_succ (n m:Nat) : n + (m++) = (n + m)++ := by
  sorry

theorem Nat.succ_eq_add_one (n:Nat) : n++ = n + 1 := by
  sorry

theorem Nat.add_comm (n m:Nat) : n + m = m + n := by
  sorry
-- </CONTEXT>
-- <TARGET_THEOREM>
theorem Nat.add_assoc (a b c:Nat) : (a + b) + c = a + (b + c) := by
-- </TARGET_THEOREM>

end Chapter2
namespace Chapter2

/--
  Assumption 2.6 (Existence of natural numbers).  Here we use an explicit construction of the
  natural numbers (using an inductive type).  For a more axiomatic approach, see the epilogue to
  this chapter.
-/
inductive Nat where
| zero : Nat
| succ : Nat → Nat
deriving Repr, DecidableEq  -- this allows `decide` to work on `Nat`

/-- Axiom 2.1 (0 is a natural number) -/
instance Nat.instZero : Zero Nat := ⟨ zero ⟩

/-- Axiom 2.2 (Successor of a natural number is a natural number) -/
postfix:100 "++" => Nat.succ

/--
  Recursion. Analogous to the inbuilt Mathlib method `Nat.rec` associated to
  the Mathlib natural numbers
-/
abbrev Nat.recurse (f: Nat → Nat → Nat) (c: Nat) : Nat → Nat := fun n ↦ match n with
| 0 => c
| n++ => f n (recurse f c n)

/-- Definition 2.2.1. (Addition of natural numbers).
    Compare with Mathlib's `Nat.add` -/
abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum ↦ sum++) m n

/-- This instance allows for the `+` notation to be used for natural number addition. -/
instance Nat.instAdd : Add Nat where
  add := add

/-- Definition 2.2.11 (Ordering of the natural numbers).
    This defines the `≤` notation on the natural numbers. -/
instance Nat.instLE : LE Nat where
  le n m := ∃ a:Nat, m = n + a

/-- Exercise 2.2.6 (backwards induction)
    Compare with Mathlib's `Nat.decreasingInduction`. -/
theorem Nat.backwards_induction {n:Nat} {P: Nat → Prop}
  (hind: ∀ m, P (m++) → P m) (hn: P n) :
    ∀ m, m ≤ n → P m := by
end Chapter2
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench

/-- Exercise 2.2.6 (backwards induction). -/
theorem Nat.backwards_induction {n : ℕ} {P : ℕ → Prop}
  (hind : ∀ m, P m.succ → P m) (hn : P n) :
    ∀ m, m ≤ n → P m := by
end TaoBench
namespace Chapter2

/--
  Assumption 2.6 (Existence of natural numbers).  Here we use an explicit construction of the
  natural numbers (using an inductive type).  For a more axiomatic approach, see the epilogue to
  this chapter.
-/
inductive Nat where
| zero : Nat
| succ : Nat → Nat
deriving Repr, DecidableEq  -- this allows `decide` to work on `Nat`

/-- Axiom 2.1 (0 is a natural number) -/
instance Nat.instZero : Zero Nat := ⟨ zero ⟩
#check (0:Nat)

/-- Axiom 2.2 (Successor of a natural number is a natural number) -/
postfix:100 "++" => Nat.succ
#check (fun n ↦ n++)

/--
  Recursion. Analogous to the inbuilt Mathlib method `Nat.rec` associated to
  the Mathlib natural numbers
-/
abbrev Nat.recurse (f: Nat → Nat → Nat) (c: Nat) : Nat → Nat := fun n ↦ match n with
| 0 => c
| n++ => f n (recurse f c n)

/-- Definition 2.2.1. (Addition of natural numbers).
    Compare with Mathlib's `Nat.add` -/
abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum ↦ sum++) m n

/-- This instance allows for the `+` notation to be used for natural number addition. -/
instance Nat.instAdd : Add Nat where
  add := add

/-- Definition 2.2.11 (Ordering of the natural numbers).
    This defines the `≤` notation on the natural numbers. -/
instance Nat.instLE : LE Nat where
  le n m := ∃ a:Nat, m = n + a

/-- Definition 2.2.11 (Ordering of the natural numbers).
    This defines the `<` notation on the natural numbers. -/
instance Nat.instLT : LT Nat where
  lt n m := n ≤ m ∧ n ≠ m

/-- Definition 2.2.7 (Positive natural numbers).-/
def Nat.IsPos (n:Nat) : Prop := n ≠ 0

/-- Definition 2.3.1 (Multiplication of natural numbers) -/
abbrev Nat.mul (n m : Nat) : Nat := Nat.recurse (fun _ prod ↦ prod + m) 0 n

/-- This instance allows for the `*` notation to be used for natural number multiplication. -/
instance Nat.instMul : Mul Nat where
  mul := mul

/-- Proposition 2.3.9 (Euclid's division lemma) / Exercise 2.3.5
Compare with Mathlib's `Nat.mod_eq_iff` -/
theorem Nat.exists_div_mod (n:Nat) {q: Nat} (hq: q.IsPos) :
    ∃ m r: Nat, 0 ≤ r ∧ r < q ∧ n = m * q + r := by
end Chapter2
import Mathlib
import Aesop
set_option maxHeartbeats 0
open BigOperators Real Nat Topology Rat Set Filter

namespace TaoBench

namespace Chapter2
namespace Nat

/-- Proposition 2.3.9 (Euclid's division lemma) / Exercise 2.3.5,
translated to Mathlib's natural numbers and operations. -/
theorem exists_div_mod (n : Nat) {q : Nat} (hq : q ≠ 0) :
    ∃ m r : Nat, 0 ≤ r ∧ r < q ∧ n = m * q + r := by
end Nat
end Chapter2

end TaoBench
namespace Chapter2

/--
  Assumption 2.6 (Existence of natural numbers).  Here we use an explicit construction of the
  natural numbers (using an inductive type).  For a more axiomatic approach, see the epilogue to
  this chapter.
-/
inductive Nat where
| zero : Nat
| succ : Nat → Nat
deriving Repr, DecidableEq

/-- Axiom 2.1 (0 is a natural number) -/
instance Nat.instZero : Zero Nat := ⟨ zero ⟩

/-- Axiom 2.2 (Successor of a natural number is a natural number) -/
postfix:100 "++" => Nat.succ

/--
  Recursion. Analogous to the inbuilt Mathlib method `Nat.rec` associated to
  the Mathlib natural numbers
-/
abbrev Nat.recurse (f: Nat → Nat → Nat) (c: Nat) : Nat → Nat := fun n ↦ match n with
| 0 => c
| n++ => f n (recurse f c n)

/-- Definition 2.2.1. (Addition of natural numbers).
    Compare with Mathlib's `Nat.add` -/
abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum ↦ sum++) m n

/-- This instance allows for the `+` notation to be used for natural number addition. -/
instance Nat.instAdd : Add Nat where
  add := add

/-- Definition 2.2.11 (Ordering of the natural numbers).
    This defines the `≤` notation on the natural numbers. -/
instance Nat.instLE : LE Nat where
  le n m := ∃ a:Nat, m = n + a

/-- Proposition 2.2.12 (Basic properties of order for natural numbers) / Exercise 2.2.3

(a) (Order is reflexive). Compare with Mathlib's `Nat.le_refl`.-/
theorem Nat.ge_refl (a:Nat) : a ≥ a := by
end Chapter2
namespace Chapter2

/--
  Assumption 2.6 (Existence of natural numbers).  Here we use an explicit construction of the
  natural numbers (using an inductive type).  For a more axiomatic approach, see the epilogue to
  this chapter.
-/
inductive Nat where
| zero : Nat
| succ : Nat → Nat
deriving Repr, DecidableEq  -- this allows `decide` to work on `Nat`

/-- Axiom 2.1 (0 is a natural number) -/
instance Nat.instZero : Zero Nat := ⟨ zero ⟩
#check (0:Nat)

/-- Axiom 2.2 (Successor of a natural number is a natural number) -/
postfix:100 "++" => Nat.succ
#check (fun n ↦ n++)

/--
  Recursion. Analogous to the inbuilt Mathlib method `Nat.rec` associated to
  the Mathlib natural numbers
-/
abbrev Nat.recurse (f: Nat → Nat → Nat) (c: Nat) : Nat → Nat := fun n ↦ match n with
| 0 => c
| n++ => f n (recurse f c n)

/-- Definition 2.2.1. (Addition of natural numbers).
    Compare with Mathlib's `Nat.add` -/
abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum ↦ sum++) m n

/-- This instance allows for the `+` notation to be used for natural number addition. -/
instance Nat.instAdd : Add Nat where
  add := add

/-- Definition 2.2.11 (Ordering of the natural numbers).
    This defines the `≤` notation on the natural numbers. -/
instance Nat.instLE : LE Nat where
  le n m := ∃ a:Nat, m = n + a

/-- Exercise 2.2.7 (induction from a starting point)
    Compare with Mathlib's `Nat.le_induction`. -/
theorem Nat.induction_from {n:Nat} {P: Nat → Prop} (hind: ∀ m, P m → P (m++)) :
    P n → ∀ m, m ≥ n → P m := by
end Chapter2