Documentation

AgoGiuga.BorweinBound

Borwein-Style Lower Bound #

Any counterexample to the Agoh-Giuga conjecture exceeds 10^13800.

The proof combines three ingredients:

  1. Branch-and-bound verifier: every normal odd-prime set with reciprocal sum > 1 has at least B elements (computational search via native_decide).

  2. Structural transfer: a Carmichael-Giuga number's prime factors form such a set, so B ≤ n.primeFactors.card, hence ∏_{j<B} (j+1)-th prime ≤ n.

  3. Product comparison: the product of the first 4000 odd primes exceeds 10^13800.

The full pipeline is demonstrated at B = 20 (~2s). The main theorem's sorry reduces to running the verifier at B = 4000.

Section 1 — Borwein definitions #

A finite set whose elements are odd primes.

Equations
Instances For

    Reciprocal sum used in the Giuga/Borwein inequalities.

    Equations
    Instances For

      A set of primes is normal if no distinct pair has one prime dividing the other minus one.

      Equations
      Instances For

        Section 2 — Structural bridge #

        For Carmichael numbers, the set of prime factors is normal in the Borwein sense: no distinct prime factor divides another minus one.

        Repackaging the existing reciprocal-sum theorem with the Borwein notation.

        If a Carmichael-Giuga number has at least k prime factors, then it is at least the product of the first k odd primes.

        Section 3 — Branch-and-bound verifier #

        Unnormalized positive fractions #

        Unnormalized positive fraction: represents num / den. No GCD normalization — arithmetic is fast at the cost of growing numerators and denominators. Only used for comparisons (via cross-multiplication).

        Instances For
          def BorweinVerifier.instDecidableEqUFrac.decEq (x✝ x✝¹ : UFrac) :
          Decidable (x✝ = x✝¹)
          Equations
          Instances For

            Zero as a fraction.

            Equations
            Instances For

              Add the reciprocal of p to the fraction: a/b + 1/p = (a*p + b)/(b*p).

              Equations
              Instances For

                Check if a/b + c/d < 1, i.e., a*d + c*b < b*d.

                Equations
                Instances For

                  Check if a/b ≤ 1, i.e., a ≤ b.

                  Equations
                  Instances For

                    UFrac interpretation in ℚ #

                    noncomputable def BorweinVerifier.UFrac.toRat (f : UFrac) :

                    Interpret a UFrac as a rational number.

                    Equations
                    Instances For
                      theorem BorweinVerifier.UFrac.addRecip_den_pos (f : UFrac) (p : ) (hf : 0 < f.den) (hp : 0 < p) :
                      0 < (f.addRecip p).den
                      theorem BorweinVerifier.UFrac.addRecip_sound (f : UFrac) (p : ) (hf : 0 < f.den) (hp : 0 < p) :
                      (f.addRecip p).toRat = f.toRat + 1 / p
                      theorem BorweinVerifier.UFrac.sumLtOne_sound (f g : UFrac) (hf : 0 < f.den) (hg : 0 < g.den) (h : f.sumLtOne g = true) :
                      f.toRat + g.toRat < 1
                      theorem BorweinVerifier.UFrac.leOne_sound (f : UFrac) (hd : 0 < f.den) (h : f.leOne = true) :

                      Prime enumeration utilities #

                      Check primality by trial division.

                      Equations
                      Instances For

                        Find the next odd prime ≥ start, within fuel candidates.

                        Equations
                        Instances For
                          theorem BorweinVerifier.nextOddPrime_sound {start fuel p : } (h : nextOddPrime start fuel = some p) :
                          Nat.Prime p Odd p start p

                          Top-level soundness for nextOddPrime: if it returns some p, then p is prime, odd, and p ≥ start.

                          Check two-way normality: p is admissible to add to the set current.

                          Equations
                          Instances For
                            theorem BorweinVerifier.isAdmissible_sound {current : Array } {p : } (h : isAdmissible current p = true) (q : ) :
                            q current.toList¬q p - 1 ¬p q - 1

                            isAdmissible current p = true means p is two-way normal w.r.t. every element of current.

                            def BorweinVerifier.nextAdmissible (current : Array ) (start probeFuel : ) :

                            Find the next admissible odd prime ≥ start w.r.t. current.

                            Equations
                            Instances For
                              Equations
                              Instances For
                                theorem BorweinVerifier.nextAdmissible_sound {current : Array } {start probeFuel p : } (h : nextAdmissible current start probeFuel = some p) :
                                Nat.Prime p Odd p start p qcurrent.toList, ¬q p - 1 ¬p q - 1

                                If nextAdmissible returns some p, then p is prime, odd, p ≥ start, and admissible w.r.t. current.

                                Tail bound #

                                def BorweinVerifier.tailBound (start count probeFuel : ) :

                                Upper bound on the reciprocal sum achievable by adding at most count primes ≥ start. We sum reciprocals of the next count primes ≥ start (ignoring normality, which makes this a valid over-estimate).

                                Equations
                                Instances For
                                  Equations
                                  Instances For
                                    def BorweinVerifier.tailBoundFound (start count probeFuel : ) :

                                    Count of primes found by tailBound. Returns the number of primes actually summed (may be less than count if fuel runs out).

                                    Equations
                                    Instances For
                                      Equations
                                      Instances For
                                        theorem BorweinVerifier.tailBound_den_pos {start count probeFuel : } :
                                        0 < (tailBound start count probeFuel).den

                                        Branch-and-bound verifier #

                                        def BorweinVerifier.verify (current : Array ) (curSum : UFrac) (target start probeFuel : ) :
                                        Bool

                                        Branch-and-bound verifier.

                                        Returns true if every normal odd-prime set extending current with all additional elements ≥ start, having reciprocal sum > 1, has at least target elements.

                                        Equations
                                        Instances For
                                          def BorweinVerifier.verifyMinNormalSet (target probeFuel depth : ) :

                                          Top-level verifier: checks that every normal odd-prime set with reciprocal sum > 1 has at least target elements.

                                          Equations
                                          Instances For

                                            Fuel check #

                                            def BorweinVerifier.fuelOK (current : Array ) (curSum : UFrac) (target start probeFuel : ) :
                                            Bool

                                            Decidable check that verify's fuel was sufficient at every node. At pruning nodes, checks tailBoundFound = remaining. At terminal nodes (nextAdmissible = none), returns false (conservative).

                                            Equations
                                            Instances For
                                              def BorweinVerifier.fuelOKTop (target probeFuel depth : ) :

                                              Top-level fuel check.

                                              Equations
                                              Instances For

                                                Soundness #

                                                structure BorweinVerifier.IsReachable (current : Array ) (start : ) (T : Finset ) :

                                                A set T is reachable from (current, start) if it contains all elements of current, every element is an odd prime, the set is normal, and all elements not in current are ≥ start.

                                                Instances For
                                                  theorem BorweinVerifier.verifyMinNormalSet_sound (target probeFuel depth : ) (hVerify : verifyMinNormalSet target probeFuel depth = true) (hFuel : fuelOKTop target probeFuel depth = true) (T : Finset ) :

                                                  Top-level soundness: if verifyMinNormalSet succeeds and fuel is sufficient, then every normal odd-prime set with reciprocal sum > 1 has ≥ target elements.

                                                  Verified computations #

                                                  The verifier confirms: every normal odd-prime set with reciprocal sum > 1 has at least 20 elements. Verified by native_decide in ~2 seconds.

                                                  theorem BorweinVerifier.fuelOK_20 :
                                                  fuelOKTop 20 10000 2000 = true

                                                  Fuel check passes for target 20.

                                                  Corollary: any normal odd-prime set with reciprocal sum > 1 has ≥ 20 elements.

                                                  Section 4 — Product comparison #

                                                  theorem Nat.count_prime_le_succ (k : ) :
                                                  count Prime (2 * k + 3) k + 1

                                                  The number of primes less than 2k+3 is at most k+1.

                                                  The (k+1)-th prime (0-indexed) is at least 2k+3.

                                                  Product of the first B odd numbers starting from 3: oddNumProduct B = 3 × 5 × 7 × ⋯ × (2B+1).

                                                  Equations
                                                  Instances For
                                                    theorem oddNumProduct_eq_prod_range (B : ) :
                                                    oddNumProduct B = jFinset.range B, (2 * j + 3)
                                                    theorem prod_odd_le_prod_nth_prime (B : ) :
                                                    jFinset.range B, (2 * j + 3) jFinset.range B, Nat.nth Nat.Prime (j + 1)
                                                    theorem oddNumProduct_4000_gt :
                                                    10 ^ 13800 < oddNumProduct 4000

                                                    The product of the first 4000 odd numbers ≥ 3 exceeds 10^13800.

                                                    theorem borwein_product_comparison :
                                                    10 ^ 13800 < jFinset.range 4000, Nat.nth Nat.Prime (j + 1)

                                                    The product of the first 4000 odd primes exceeds 10^13800.

                                                    Section 5 — Main theorem #

                                                    The Borwein et al. (1996) lower bound: any counterexample to Agoh-Giuga exceeds 10 ^ 13800.

                                                    Equations
                                                    Instances For

                                                      Transfer from verifier to cardinality bound.

                                                      Transfer from verifier to product bound.

                                                      Pipeline demo: any Carmichael-Giuga number has ≥ 20 prime factors.

                                                      Main theorem: any counterexample to Agoh-Giuga exceeds 10^13800.

                                                      The remaining sorry is purely computational: running the verifier at target 4000 via native_decide. The pipeline is demonstrated at target 20.