APSP in : definitions, part 1 of 5
DefinitionAPSP299791_Defs1Definitions for the formal proof that all-pairs shortest paths can be solved deterministically in time on a word RAM, part 1 of 5. It imports the definition bundles APSPSource_* and TrulySubcubicAPSP_SourceSpecification of the foundation development, which hold the unmodified library.
This part contains the base layer: paper-level objects from PaperStatements, the program logic of the light language (Logic, Regions, Rules), the step semantics of the machine and the asymptotic notion of domination, as needed by the later bundles.
Source modules (in this order): PaperStatements, ThreeSumApsp.Util.Asymptotics.Dominated, ThreeSumApsp.Machine.Steps, ThreeSumApsp.Lang.Frames, ThreeSumApsp.Util.Log, ThreeSumApsp.Util.CountingSort, ThreeSumApsp.Util.Digits, ThreeSumApsp.Spec.Sec2.Theorem5.Alphabets, ThreeSumApsp.Sec2.Lemma10, ThreeSumApsp.Sec2.Orders, ThreeSumApsp.Util.Choose.
Across the six parts, the development changes the construction of Alman and Vassilevska Williams in three ways:
- pruned encodings in the data structure of Theorem 30: only the leaves whose decimal digits contain at most nines are computed and stored, since a query reads no other leaf, and the shared stage costs per band instead of ;
- the thin regime with the parameters , ;
- an all-edges Exact Triangle host for Theorem 17 that calls its oracle at the middle dimension , , followed by the chain all-edges Exact Triangle → pairs → (min,+)-product → APSP.
Formalization Note The bundle is generated from the library by deleting the theorems that are not needed ("skeleton subtraction"); it keeps definitions, structures, instances, notations and tactic macros, and the few lemmas that the definitions themselves need, with proofs. Section 4 declarations whose meaning changed with pruning carry the suffix P (for example Specs40P, base58P, QueryAtSpecP), so that they do not clash with the declarations of the foundation bundles.
/-
Copyright (c) 2026 Anthropic, PBC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
SPDX-License-Identifier: Apache-2.0
-/
-- Generated by skeleton subtraction from the ThreeSumApsp library at commit 27a2fa4bab32.
import Definitions.Def_APSPSource_PaperStatements
import Definitions.Def_APSPSource_RemainingDefinitions
import Definitions.Def_APSPSource_ThreeSumApsp_Lang_Logic
import Definitions.Def_APSPSource_ThreeSumApsp_Lang_Regions
import Definitions.Def_APSPSource_ThreeSumApsp_Lang_Syntax
import Definitions.Def_APSPSource_ThreeSumApsp_Lang_WordSize
import Definitions.Def_APSPSource_ThreeSumApsp_Machine_Realized
import Definitions.Def_APSPSource_ThreeSumApsp_Machine_Solving
import Definitions.Def_APSPSource_ThreeSumApsp_Machine_Steps
import Definitions.Def_APSPSource_ThreeSumApsp_Programs_Sec2_Theorem5_Places
import Definitions.Def_APSPSource_ThreeSumApsp_Sec2_Lemma10
import Definitions.Def_APSPSource_ThreeSumApsp_Sec2_Lemma6
import Definitions.Def_APSPSource_ThreeSumApsp_Sec2_Lemma7_8
import Definitions.Def_APSPSource_ThreeSumApsp_Sec2_Levels
import Definitions.Def_APSPSource_ThreeSumApsp_Sec2_Tiling_Definitions
import Definitions.Def_APSPSource_ThreeSumApsp_Sec3_Parameters
import Definitions.Def_APSPSource_ThreeSumApsp_Sec3_Theorem17_Instances
import Definitions.Def_APSPSource_ThreeSumApsp_Sec3_Theorem21b_NegativeTriangle
import Definitions.Def_APSPSource_ThreeSumApsp_Sec4_Boxes
import Definitions.Def_APSPSource_ThreeSumApsp_Sec4_BoxesFromLeaves
import Definitions.Def_APSPSource_ThreeSumApsp_Sec4_Lemma27_28
import Definitions.Def_APSPSource_ThreeSumApsp_Sec4_ParameterSteps
import Definitions.Def_APSPSource_ThreeSumApsp_Sec4_Table2_LogBounds
import Definitions.Def_APSPSource_ThreeSumApsp_Sec4_Theorem30
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec2_Theorem5_Alphabets
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec2_Theorem5_Arrays
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec2_Theorem5_Layout
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec2_Theorem5_Subsets
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Problems
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Theorem17_Chunks
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Theorem17_Hashing
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Theorem17_Instances
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Theorem17_Parameters
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Theorem17_ZOrder
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Theorem21b_BitSearch
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec3_Theorem21b_NegativeTriangle
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec4_Theorem30_Cubes
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec4_Theorem30_NineScan
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec4_Theorem30_NineStrings
import Definitions.Def_APSPSource_ThreeSumApsp_Spec_Sec4_Theorem30_Trie
import Definitions.Def_APSPSource_ThreeSumApsp_TimeClaims_Sec3_Definitions
import Definitions.Def_APSPSource_ThreeSumApsp_TimeClaims_Sec3_Theorem19
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Asymptotics_Dominated
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Asymptotics_Scale
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Asymptotics_UpperBounds
import Definitions.Def_APSPSource_ThreeSumApsp_Util_BinaryPrefixes
import Definitions.Def_APSPSource_ThreeSumApsp_Util_CountingSort
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Digits
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Flag
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Index
import Definitions.Def_APSPSource_ThreeSumApsp_Util_List
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Log
import Definitions.Def_APSPSource_ThreeSumApsp_Util_PrimesInWindow
import Definitions.Def_APSPSource_ThreeSumApsp_Util_Weave
import Definitions.Def_TrulySubcubicAPSP_SourceSpecification
import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Algebra.BigOperators.Group.Finset.Basic
import Mathlib.Algebra.BigOperators.GroupWithZero.Finset
import Mathlib.Algebra.BigOperators.Intervals
import Mathlib.Algebra.BigOperators.Ring.Finset
import Mathlib.Algebra.Field.GeomSum
import Mathlib.Algebra.Group.Action.Defs
import Mathlib.Algebra.Group.Int.Defs
import Mathlib.Algebra.GroupWithZero.Nat
import Mathlib.Algebra.MvPolynomial.Basic
import Mathlib.Algebra.MvPolynomial.CommRing
import Mathlib.Algebra.Order.BigOperators.Group.Finset
import Mathlib.Algebra.Order.BigOperators.Group.List
import Mathlib.Algebra.Order.BigOperators.Group.Multiset
import Mathlib.Algebra.Order.BigOperators.GroupWithZero.List
import Mathlib.Algebra.Order.BigOperators.Ring.Finset
import Mathlib.Algebra.Order.Field.Basic
import Mathlib.Algebra.Order.Field.GeomSum
import Mathlib.Algebra.Order.Floor.Div
import Mathlib.Algebra.Order.Floor.Semifield
import Mathlib.Algebra.Order.Floor.Semiring
import Mathlib.Algebra.Order.Group.Abs
import Mathlib.Algebra.Order.Group.Int
import Mathlib.Algebra.Order.Group.Nat
import Mathlib.Algebra.Order.Group.Unbundled.Abs
import Mathlib.Algebra.Order.Ring.Abs
import Mathlib.Algebra.Order.Ring.Int
import Mathlib.Algebra.Order.Ring.Nat
import Mathlib.Algebra.Order.Ring.Rat
import Mathlib.Analysis.Asymptotics.Lemmas
import Mathlib.Analysis.Complex.Exponential
import Mathlib.Analysis.Complex.ExponentialBounds
import Mathlib.Analysis.Convex.SpecificFunctions.Basic
import Mathlib.Analysis.Normed.Field.Basic
import Mathlib.Analysis.SpecialFunctions.BinaryEntropy
import Mathlib.Analysis.SpecialFunctions.Log.Base
import Mathlib.Analysis.SpecialFunctions.Log.Basic
import Mathlib.Analysis.SpecialFunctions.Pow.Asymptotics
import Mathlib.Analysis.SpecialFunctions.Pow.Real
import Mathlib.Combinatorics.Enumerative.DoubleCounting
import Mathlib.Combinatorics.SimpleGraph.Basic
import Mathlib.Data.Bool.Count
import Mathlib.Data.Fin.VecNotation
import Mathlib.Data.Finset.Powerset
import Mathlib.Data.Finset.Sort
import Mathlib.Data.Fintype.BigOperators
import Mathlib.Data.Fintype.Fin
import Mathlib.Data.Int.Cast.Lemmas
import Mathlib.Data.Int.Notation
import Mathlib.Data.Int.SuccPred
import Mathlib.Data.List.GetD
import Mathlib.Data.List.Induction
import Mathlib.Data.List.Iterate
import Mathlib.Data.List.MinMax
import Mathlib.Data.List.OfFn
import Mathlib.Data.List.Range
import Mathlib.Data.List.TakeWhile
import Mathlib.Data.Nat.Bitwise
import Mathlib.Data.Nat.Cast.Order.Ring
import Mathlib.Data.Nat.Choose.Basic
import Mathlib.Data.Nat.Choose.Bounds
import Mathlib.Data.Nat.Choose.Sum
import Mathlib.Data.Nat.Count
import Mathlib.Data.Nat.Digits.Defs
import Mathlib.Data.Nat.Digits.Lemmas
import Mathlib.Data.Nat.Log
import Mathlib.Data.Nat.Notation
import Mathlib.Data.Nat.Prime.Factorial
import Mathlib.Data.Nat.Size
import Mathlib.Data.Nat.SuccPred
import Mathlib.Data.Real.Basic
import Mathlib.Data.Set.Function
import Mathlib.LinearAlgebra.Finsupp.LinearCombination
import Mathlib.LinearAlgebra.Matrix.Defs
import Mathlib.LinearAlgebra.Matrix.Notation
import Mathlib.Logic.Equiv.Basic
import Mathlib.Logic.Function.Basic
import Mathlib.Logic.Function.Iterate
import Mathlib.MeasureTheory.Integral.Bochner.Basic
import Mathlib.NumberTheory.Bertrand
import Mathlib.NumberTheory.Chebyshev
import Mathlib.NumberTheory.PrimeCounting
import Mathlib.Order.ConditionallyCompleteLattice.Basic
import Mathlib.Order.Filter.AtTopBot.Basic
import Mathlib.Order.Interval.Finset.Fin
import Mathlib.Order.Interval.Finset.Nat
import Mathlib.Probability.Independence.Basic
import Mathlib.RingTheory.AdjoinRoot
import Mathlib.Tactic.Common
import Mathlib.Tactic.DeriveFintype
import Mathlib.Tactic.GCongr
import Mathlib.Tactic.Linarith
import Mathlib.Tactic.LinearCombination
import Mathlib.Tactic.NoncommRing
import Mathlib.Tactic.NormNum
import Mathlib.Tactic.Positivity
import Mathlib.Tactic.Ring
import Mathlib.Tactic.SplitIfs
set_option autoImplicit false
set_option relaxedAutoImplicit false
section
-- Source module: PaperStatements
/-!
# Further statements of the paper
Statements of the paper «Truly Subquadratic 3SUM and Truly Subcubic APSP via Triangles in Sparse
Lopsided Graphs» (Josh Alman, Virginia Vassilevska Williams) beyond the five claims of
`EndStatement.lean`, each as a proposition, with the definitions that they use; and statements that
the notions which this file and `EndStatement.lean` both define agree. The file imports
`EndStatement.lean` and Mathlib. It proves none of the statements: the proofs are in the library,
the folder `ThreeSumApsp/`. The five claims do not depend on this file: it is for a reader who wants
to believe a further lemma, equation, table or theorem of the paper.
`Challenge/PaperStatements.lean` states that the propositions hold: `PaperStatements.lemma_6` says
that `PaperStatements.Lemma_6` holds, and `ThreeSumApsp.wordRam_theorem_5` that the running-time
sentence `ThreeSumApsp.WordRam.Items.Theorem_5` holds.
The parts, in this order:
* Section 2: definitions
* Section 2: statements
* Section 3: definitions
* The reduction of Chan and He: definitions
* Section 3: statements
* Section 4: definitions
* Section 4: statements
* Section 5: definitions
* Section 5: statements
* The word RAM: problems
* Agreement with the definitions of EndStatement.lean
* The word RAM: running times
In a comment, "this part" means the part in which the comment stands.
-/
@[expose] public section
/-!
## Section 2: definitions
Definitions used by the statements of Section 2, "Quickly computing certain entries of a thin matrix
product". They follow the paper's order and names. Only what the statements need, directly or
through another definition, is defined here; the other notions of the section, among them the tiling
of Section 2.3.4, are defined with the proofs.
Conventions used throughout.
* The paper numbers indices from 1; Lean's `Fin n` starts at 0. So the paper's `x₁, x₂, x₃` are
`LeftVar.x 0, LeftVar.x 1, LeftVar.x 2`, the paper's `p₂₁` is `LeftVar.p 1 0`, and so on.
* A string of length `L` over an alphabet `α` is a function `Fin L → α`. The paper's level
`ℓ ∈ {1, …, L}` is the element `ℓ - 1` of `Fin L`; the order of the levels is the order of
`Fin L`.
* The string `s u'` (the variable `s` followed by the string `u'`) is `Fin.cons s u'`; the first
variable of `u` is `u 0` and the rest of it is `Fin.tail u`. The empty string is `Fin.elim0`.
* A linear form is given by the vector of its coefficients: a linear form in the left variables is a
function `LeftVar → ℤ`. `Pi.single s 1` is the form consisting of the single variable `s`.
-/
section Sec2Definitions
open Finset
namespace ThreeSumApsp
/-! ### 2.2 Schönhage's identity for an inner product and an outer product -/
/-! ### 2.3.1 The recursion -/
/-! ### 2.3.2 Unraveling the recursion computation -/
/-! ### 2.3.3 Batch computation of multiple matrix products -/
/-! ### 2.3.4 Tiling the N × D × N product by products of shape N₀ × D × N₀: the number `M` -/
/-! ### 2.4.1 Sharing the encoding -/
/-! ### 2.4.2 Skipping the calls that are not needed -/
/-- Section 2.4.2: "an array on S assigns an integer to each string of S". We write such an array
as a function on all output strings that is 0 outside `S`; this restricts an array to `S`. -/
def restrictTo {n : ℕ} (S : Finset (OutStr n)) (c : OutStr n → ℤ) : OutStr n → ℤ :=
fun w => if w ∈ S then c w else 0
/-! ### 2.4.3 Few leaves contribute to a sparse set of entries -/
end ThreeSumApsp
end Sec2Definitions
/-!
## Section 2: statements
The numbered lemmas and equations of Section 2 of the paper, and the figures that
assert something of their own.
* Equation (1) is `Eq_1`. Equations (2) and (3) are the definitions `Mult` and `gamma`. Equation (4)
is the display of `Lemma_9`. Equation (5) is stated in three pieces: `Eq_5_ratio`, `Eq_5_bound`,
`Eq_5`. Equation (6) is `Eq_6`.
* Lemmas 6 to 11 are `Lemma_6` to `Lemma_11`, each as one statement.
* Of Figure 3 the two worked examples of the caption are stated: `Figure_3`. Of Figure 4 the worked
example is stated: `Figure_4`. Figure 6 is `Figure_6`; the two counts
`Sec2_card_contributing_of_order` and `Sec2_card_outStr_of_leaf` say what its numbers count.
* Theorem 5 is a sentence about a machine. It is `Items.Theorem_5`. So of the tiling (Section 2.3.4)
and of the proof of Theorem 5 (Section 2.4.4) nothing is stated here but the number `M` and
equation (6): the statements of this part are about a single run of the recursion.
* Remark 12 makes no mathematical claim. Figure 2 recalls Strassen's recursion for intuition; only
identity (1) is stated. Figure 5 makes no claim of its own. Figure 7 draws the count of Lemma 11;
two remarks of its caption, that "the bound |U|α_d grows with d up to d ≈ 0.9m" and that the proof
splits at a point "which is not necessarily where the two bounds cross", are not stated.
`docs/INDEX.md` says for each item of the paper what is stated and what is not.
A hypothesis that is not in the printed text is marked NOTE in the docstring. A hypothesis of the
printed text that is not needed (such as m ≥ 1, Section 2.3.3) is left out without a mark.
-/
section Sec2Statements
open Finset
namespace PaperStatements
open ThreeSumApsp
/-! ### 2.1 Strassen's recursive algorithm -/
/-! ### 2.2 Schönhage's identity for an inner product and an outer product -/
/-! ### 2.3.1 The recursion -/
/-! ### 2.3.2 Unraveling the recursion computation -/
/-! ### 2.3.3 Batch computation of multiple matrix products -/
/-! ### 2.4.2 Skipping the calls that are not needed -/
/-! ### 2.4.3 Few leaves contribute to a sparse set of entries -/
/-! ### 2.4.4 Proof of Theorem 5 -/
end PaperStatements
end Sec2Statements
/-!
## Section 3: definitions
Definitions used by the statements of Section 3, "Exact Triangle reduces to computing certain
entries of a thin matrix product". They follow the paper's order and names. Only what the
statements need, directly or through another definition, is defined here; some of the definitions
are used by the statements about programs and not by those of Section 3.
Conventions used throughout.
* A part of `n` vertices is the type `Fin n`. A pair `(a, b) ∈ A × B` is an element of
`Fin n × Fin n`, a triple `(a, b, c) ∈ A × B × C` an element of `Fin n × Fin n × Fin n`.
* The paper numbers the pieces from 1; here pieces and chunks are numbered from 0.
* `√D` is the real square root `Real.sqrt D`, `⌊·⌋` and `⌈·⌉` are `Nat.floor` and `Nat.ceil` of real
numbers, and `log` is the natural logarithm `Real.log` unless a base is written.
* `x ≡ y (mod p)` is `Int.ModEq`, written `x ≡ y [ZMOD p]`. A residue or label in `ℤ_p` is an
element of `Fin p`.
* No definition of this part mentions time. For the sentences of the paper about running time see
`docs/REMARKS.md`, "Section 3: running times". -/
section Sec3Definitions
namespace ThreeSumApsp
/-! ### 3.1 The Lopsided All-Edges Sparse Triangle problem -/
/-! #### Cutting a set of pairs into sets of bounded size
Corollary 15 ("splitting W into sets of at most n²/√D query pairs") and the proof of Theorem 17
("cut it into chunks of at most n²/√D query pairs") cut a set of pairs into smaller sets. The paper
does not say how; we cut along the row-major order of the pairs. -/
/-! ### 3.2 A deterministic reduction from Exact Triangle to Lop-AE-SparseTri -/
namespace TriangleInstance
end TriangleInstance
/-! #### Hashing modulo a prime (proof of Theorem 17) -/
namespace TriangleInstance
end TriangleInstance
/-! #### The instances (proof of Theorem 17) -/
namespace TriangleInstance
/-! #### Witnesses (proof of Theorem 17) -/
end TriangleInstance
/-! ### 3.4 3SUM and APSP reduce to Exact Triangle: the problems -/
/-! A directed graph on the vertices `Fin n` with edge weights in `R` is a function
`w : Fin n → Fin n → WithTop R`: `w i j` is the weight of the edge from `i` to `j`, and `⊤` (that
is, `+∞`) if there is no such edge. A walk that starts at `i` is given by the list of the vertices
it visits after `i`. -/
/-! #### The shape of the two reductions of [VW13] that Theorem 21 cites -/
/-! #### Asymptotic notation of Section 3 -/
end ThreeSumApsp
end Sec3Definitions
/-!
## The reduction of Chan and He: definitions
[CH20] is Timothy M. Chan and Qizheng He, *Reducing 3SUM to Convolution-3SUM*, Proc. 3rd SIAM
Symposium on Simplicity in Algorithms (SOSA 2020). Theorem 21(a) of the paper cites [CH20]. What
is used is the reduction in the proof of its Theorem 5.1, a deterministic reduction from 3SUM to
polylogarithmically many instances of Convolution-3SUM. The theorem itself is a statement about
running times, for 3SUM on three sets and Convolution-3SUM on three arrays.
This part defines such a reduction, as a function from inputs to lists of instances. What is proved
about it is stated by `Theorem_21a_threeSum_to_convolution` and `Theorem_21a_threeSum_to_exact`.
The construction follows the proof of Theorem 5.1. Where it differs from [CH20], and what it adds,
is listed in `docs/REMARKS.md`, "Section 3: cited results".
### Why all these definitions are trusted
The list of instances depends on the input. A statement of the form "there is a list of instances
such that the input has a solution iff one of them has" would be true for trivial reasons. So the
statements are about the explicitly defined function `instances`, which is built from `reduction`,
and their worth rests on the definitions of this part.
* `reduction` takes three sets of at most n integers. It returns the nodes of a recursion tree, and
each node stands for one instance of Convolution-3SUM on three arrays. 3SUM on three sets (are
there a, b, c, one from each set, with a + b + c = 0?) and Convolution-3SUM on three arrays (are
there i, j with X i + Y j = Z (i + j)?) are the problems of Definitions 2.1 and 2.2 of [CH20], for
which Theorem 5.1 is stated.
* `instances` takes n numbers, for the problem whether three of them, at three different positions,
sum to 0. It returns instances of Convolution-3SUM on one array. These are the problems of the
paper, 3SUM in the reading fixed at `ThreeSum`.
Evaluated literally, `coll` and `heavy` compare all pairs of elements, and each search tests all its
candidates, so the definitions are a specification and not the algorithm. Nothing in this part is
about a machine.
Every choice that the two functions make depends only on which elements collide and how many pairs
do, on which sets are empty, on binary digits of the numbers and on how often a number occurs. None
depends on whether a solution exists, with one exception: the solution 0, 0, 0 exists exactly when 0
occurs at three positions. So it is detected by counting, and it is reported through the three-set
input (`zeroSet x`, {0}, {0}), which has a solution exactly in that case.
In this part `ν` is a node of the recursion tree. It is not the exponent ν of Theorem 21, which
the statements call `κ`.
-/
section ChanHeDefinitions
namespace ThreeSumApsp
namespace ChanHe
open Finset
/-! ### Collisions and heavy elements -/
/-! ### The arrays of one node -/
/-! ### The choice of the modulus -/
/-! ### The recursion tree -/
/-! ### The parameters -/
/-! ### The reduction for three sets -/
/-! ### From n numbers to three sets -/
/-! ### Three arrays in one -/
/-! ### The whole reduction -/
/-! ### Sizes for inputs of absolute value at most n ^ κ -/
end ChanHe
end ThreeSumApsp
end ChanHeDefinitions
/-!
## Section 3: statements
The claims of Section 3 of the paper, proved or cited there, that are
mathematics and not sentences about a machine.
* Theorem 17, everything but the running time: `Theorem_17`, with `Theorem_17_scanOrder_exists` (its
hypothesis on the order of the scans can be met) and two pieces of arithmetic behind two terms of
the additional time, `Theorem_17_hashing_sum_sq_le` and `Theorem_17_write_cost`.
* Remark 18 compares the instances of Theorem 17 with graphs of [VX20]. Stated is what the
comparison says about the paper's own instance, namely which residues its edges and query pairs
have: `Remark_18_block`.
* Remark 20: `Remark_20_balance`, `Remark_20_brute_force`.
* Theorem 21, which the paper cites from the literature without a proof: the correctness, the
numbers and the sizes of the instances of the reductions, and the arithmetic behind the printed
forms (stated for arbitrary functions, and not applied to the bounds of the reductions). Part (b):
`Theorem_21b_repeated_squaring`, `Theorem_21b_entries_bounded`, `Theorem_21b_negative_to_exact`,
`Theorem_21b_log_factors`. Part (a): `Theorem_21a_convolution_to_exact`, `Theorem_21a_compose`,
and, for the reduction that the paper cites from Chan and He,
`Theorem_21a_threeSum_to_convolution` and `Theorem_21a_threeSum_to_exact`.
* Definitions 13 and 14 are rendered by definitions. Corollaries 15 and 16 and Theorems 19 and 22
are sentences about running time; they are stated about programs (`Items.Corollary_15` to
`Items.Theorem_22_threeSum`).
Not stated here:
* The running time of the reduction of Theorem 17, the time bound of Theorem 21(a), and Theorem
21(b) in its printed form ("If a deterministic algorithm solves Exact Triangle [...] in time T(s)
[...], then [...]") have no statement.
* [VW18, Theorem 4.2] has no mathematical statement.
* Remark 23, where the paper indicates the method in one sentence and gives no proof, and
footnote 9.
* The other sentences inside proofs, and unnumbered claims, are lemmas of the library or are not
formalized.
`docs/INDEX.md` says for each item of the paper what is stated and what is not. `docs/REMARKS.md`,
"Section 3: running times" and "Section 3: cited results", has the details.
Hypotheses that are added or changed are marked NOTE and listed in `docs/REMARKS.md`, "Section 3:
differences". Lower bounds that only exclude empty or degenerate cases (`1 ≤ N`, `1 ≤ U`, `0 ≤ U`,
`2 ≤ n`, `0 ≤ κ`, `0 ≤ τ` in the statements for Theorem 21) carry no NOTE.
-/
section Sec3Statements
namespace PaperStatements
open ThreeSumApsp
/-! ### 3.2 A deterministic reduction from Exact Triangle to Lop-AE-SparseTri -/
/-! #### Theorem 17, first step: hashing modulo a prime -/
/-! #### Theorem 17, second step: the instances -/
/-! #### Theorem 17, third step: witnesses -/
/-! ### 3.3 Exact Triangle in truly subcubic time
Theorem 19 is a statement about running time: `Items.Theorem_19`.
Stated here: Remark 20. -/
/-! ### 3.4 3SUM and APSP reduce to Exact Triangle
Theorem 22 is a statement about running time (`Items.Theorem_22_first`, `Items.Theorem_22_second`,
`Items.Theorem_22_threeSum`). Theorem 21 is cited from the literature, part (a) from [CH20, VW13]
and part (b) from [VW10, VW18, VW13], and the paper gives no proof. The route taken here:
* for (a), from 3SUM to Convolution-3SUM [CH20, Theorem 5.1], and from there to Exact Triangle
[VW13, Theorem 4.3];
* for (b), from Negative Triangle to Exact Triangle [VW13, Theorem 3.3], from the (min,+)-product to
Negative Triangle [VW18, Theorem 4.2], and from APSP to the (min,+)-product by repeated squaring.
Stated here: the parts of this route that are mathematics, among them the combinatorial content of
the two reductions of [VW13]. -/
/-! #### Theorem 21(a): the reduction from 3SUM to Convolution-3SUM, after Chan and He
The first step towards Theorem 21(a), after [CH20, Theorem 5.1]: from n integers bounded by a power
of n, a deterministic reduction computes polylogarithmically many arrays of length Õ(n), whose
entries are again bounded by a power of n, in Õ(n^{3/2}) time; three of the integers sum to 0
exactly if one of the arrays is a yes-instance of Convolution-3SUM.
The namespace `ChanHe` defines a reduction of this kind, as a function from inputs to lists of
instances, in two versions: `ChanHe.reduction` for three sets and three arrays, and
`ChanHe.instances` for n numbers and one array. Nothing is stated here about `ChanHe.reduction`.
Nothing here is about a machine. That the functions can be evaluated deterministically in n^(3/2)
polylog n time on a word RAM is not stated. Theorem 5.1 of [CH20] as printed is a statement about
running times, so it is not stated here. The easy converse reduction, from Convolution-3SUM to
3SUM, is not treated. -/
section ChanHe
open Finset
end ChanHe
end PaperStatements
end Sec3Statements
/-!
## Section 4: definitions
Definitions used by the statements of Section 4, "The matrix theorem in general: a data structure".
They follow the paper's order and names, with three exceptions: `Cube.starsToP0`, from the proof of
Lemma 29, stands with the cubes of Section 4.2; `epsStar`, from Section 4.1, stands with `Rc`; and
the definitions for Table 2, which is printed in Section 4.1, come last. Every notion of Section 2
(terms, leaves, output strings, inner sets, private leaf, order, `α_d`, `β_d`, `Φ_τ`, `Ψ_τ`) is the
one defined for Section 2 and is not redefined.
Conventions, in addition to those of the definitions of Section 2.
* Table 1: `m` and `L` are natural-number variables, and `D = 4^m`, `N₀ = 3^{L-m}`,
`K = binom(L, m)`, `M = K N₀²`, `α_d`, `β_d` are `D m`, `N0 L m`, `K L m`, `M L m`, `alpha m d`,
`beta L m d` of Section 2. The remaining rows of Table 1: `ρ` is `rho L m`, and `γ`, `q`, `R_c(γ)`
are `gammaOf c θ`, `qOf θ`, `Rc c γ`, all defined below; the switching order is a natural number
`t`, and the ratio `c`, `ε` and `κ` are real numbers.
* "we say that level ℓ is lower than level ℓ' if ℓ < ℓ'" (Section 4): levels are compared in the
order of `Fin L`.
* An output string is `η` in the Lean text; the paper writes w.
* The paper fixes `0 ≤ t ≤ m` (Section 4.2) and `L ≥ 10m` (Section 4). The definitions below make
sense for all natural numbers; the statements carry `t ≤ m` and `10 * m ≤ L` as explicit
hypotheses where they are needed. `m - t` is subtraction of natural numbers, which is the ordinary
difference because `t ≤ m`.
-/
section Sec4Definitions
open Finset
namespace ThreeSumApsp
/-! ### Notions from Section 2 -/
/-! ### 4.2 Boxes -/
/-! ### 4.3 The data structure, in terms of the parameters -/
/-! ### 4.4 Choosing the parameters -/
/-- Table 1: "L and t are cm and θm rounded up to integers"; the proof of Corollary 31: "L := ⌈cm⌉".
(Only `L` gets a name here.) -/
noncomputable def levelsOf (c : ℝ) (m : ℕ) : ℕ := ⌈c * (m : ℝ)⌉₊
/-! #### Table 2 -/
end ThreeSumApsp
end Sec4Definitions
/-!
## Section 4: statements
The claims of Section 4 of the paper, "The matrix theorem in general: a data structure", that are
mathematics and not sentences about a machine. `docs/INDEX.md` says for each item of the paper what
is stated and what is not. The places where the Lean text differs from the wording of the paper are
collected in `docs/REMARKS.md`, "Section 4: differences".
The order is the paper's, with these exceptions. Figure 10 and `Lemma_28_boxes` come after Lemma 28.
`Eq_10`, from the proof of Corollary 31, stands with equation (10). `Sec4_epsStar_numeric` (Section
4.1) and `Sec4_Rc_lt_epsStar` (Table 1) stand with the clauses of Corollary 31 on ε*. The statements
on Table 2, `Table_1_section_2_column` and `Corollary_26_W` come at the end.
* Sentences about running time and space are sentences about a machine. Those of Theorems 24, 25 and
30 and of Corollaries 26, 31 and 32 are stated about programs: `Items.Theorem_24` to
`Items.Corollary_32`. The bound of the second sentence of Lemma 29 ("in O(L) time and space per
box") has no statement; Theorem 30 about programs has its consequence, the first term of (8).
* Expressions (8) and (9) are the definitions `cost8` and `cost9`. Equation (11) is the definition
`Rc`.
* Figure 9 draws the cube and the boxes of one output string in a small example (L = 3, t = 1).
Nothing is stated for it.
* No statement says that q increases with θ on (0, 0.9), or that there is only one θ with
γ = κ - q. So "the θ that gives the q of the column" and "the θ at which γ = κ - q" (Section 4.4)
are rendered by "some θ with ..." in `Table2Query`, `Table2Density` and the field `eps` of
`Table2Row`.
* The standing assumptions of the section, `0 ≤ t ≤ m` (Section 4.2) and `L ≥ 10m` (Section 4),
appear as the explicit hypotheses `t ≤ m` and `10 * m ≤ L` in the statements that need them. "As
in Section 2.4.3, all output strings in this section have inner sets of exactly m elements"
(Section 4) is the hypothesis `(innerSetO η).card = m`.
* An output string is `η` in the Lean text; the paper writes w.
* `D m = 4 ^ m` is the paper's `D` after "from now on D = 4^m" (the proof of Corollary 26). The
inner dimension of the given matrices, before it is padded to a power of four, is written `D₀`.
* Where a statement renders an `O(·)`, it has an explicit constant and an explicit order of
quantifiers, and the docstring says how the sentence was read.
-/
section Sec4Statements
open Finset
namespace PaperStatements
open ThreeSumApsp
/-! ### 4.2 Boxes -/
/-! ### 4.3 The data structure, in terms of the parameters -/
/-! #### The decay rate ρ and equation (7) -/
/-! ### 4.4 Choosing the parameters -/
/-! #### Corollary 31: the clauses that are not about time -/
/-! #### Corollary 32 -/
/-! #### Table 2, and the column of Table 1 on Section 2 -/
/-! ##### The six rows of Table 2
Each statement has the numbers of a row in the order in which the paper prints them: the first line
has `c`, `ε` and the left half, the second line the right half. It says that every entry is computed
as Section 4.4 prescribes and is rounded down to four decimals, and that the `ε` of the row is below
`R_c(γ)` at every entry and is rounded down to three decimals. By `Table_2_query_valid`,
`Table_2_ninth_valid` and `Table_2_density_valid`, Corollary 31 or 32 then gives what the caption
claims for the entry. -/
/-! #### Corollary 26 -/
end PaperStatements
end Sec4Statements
/-!
## Section 5: definitions
Definitions used by the statements about Section 5, in the paper's order. Only what the statements
need is defined: blocks of matrices (5.1, 5.2, 5.4), comparison counts, the two counting
problems, and the construction of Lemma 37 (5.2), and the three hinted matrix-vector problems with
the conjectures about them (5.4). The definitions of 5.4 are used by the statements about programs.
The weighted `k`-Clique problems of 5.3 are `EndStatement.ZeroWeightKClique`,
`WordRam.MinKClique` and `WordRam.MaxKClique`.
Conventions.
* The paper numbers indices from 1; Lean's `Fin n` starts at 0.
* The paper treats n^μ, n/d, n/t₂ as integers. Here a matrix that is cut into `b` blocks of `m`
consecutive rows has `b * m` rows, and row `i` of block `p` is row `p * m + i`, which is
`finProdFinEquiv (p, i)`. The arithmetic of Theorem 35 has `d = ⌊n^{1/40}⌋` and the real quotient
`n/d`; nothing is stated about cutting into blocks of `d` when `d` does not divide `n`.
* Definitions shared with Section 3 (`TriangleInstance`, `IsMinPlusProduct`, ...) and Section 4
(`epsStar`, `padInnerCols`, `padInnerRows`) stand with the definitions of these sections.
-/
section Sec5Definitions
open Finset
namespace ThreeSumApsp
/-! ### Blocks of consecutive rows and columns (used in 5.1, 5.2 and 5.4) -/
/-! ### 5.2 Comparison counts -/
namespace ComparisonCounts
/-! #### The objects in the proof of Lemma 36 -/
/-! #### The construction of Lemma 37 -/
/-! #### The parameters of Corollary 38 and of the proof of Theorem 35 -/
end ComparisonCounts
/-! ### 5.4 Three conjectures of van den Brand, Nanongkai, and Saranurak -/
namespace HintedMv
end HintedMv
end ThreeSumApsp
end Sec5Definitions
/-!
## Section 5: statements
The pieces of Sections 5.1 and 5.2 that the paper itself argues and that are mathematics:
correctness of the constructions, counts, and the arithmetic of the exponents, with the paper's
constants. `docs/INDEX.md` says for each item of the paper what is stated and what is not. Where a
statement differs from the printed sentence, `docs/REMARKS.md`, "Section 5 and the introduction:
differences", says why.
* The sentences of the form "can be solved in O(...) time" are not stated here. Those of Corollaries
39 and 40 are stated about programs of the word RAM (`Items.Corollary_39_zero` to
`Items.Corollary_40_fail`), and nothing else of Sections 5.3 and 5.4 is stated. Those of Theorem
35 and of Corollary 38 are about randomized algorithms or real numbers, and the machine has
neither random bits nor real numbers. That of Theorem 34 rests on Theorem 33, which the paper
proves and which is not proved here, and on μ, which is defined through ω(1, μ, 1). Three lemmas
of the library (the files that hold the proofs), `conditional_theorem_34`,
`conditional_corollary_38` and `conditional_theorem_35`, say how each follows from the results
that its proof uses, which are taken as hypotheses. The running time of Lemma 37 and Lemma 36 as a
whole occur only as hypotheses of these lemmas. The list is in `docs/REMARKS.md`, "Section 5 and
the introduction: running times".
* The theorems of other papers that Section 5 uses as black boxes are not stated (`docs/REMARKS.md`,
"Section 5: cited results"). In particular the randomized reductions behind Lemma 36 are cited.
Nothing of Theorem 33 and of its proof is stated.
* Of Lemma 36, the size O(n²/d) of the pair set of part (b) is not stated;
`Theorem_35_three_sum_count` puts n²/d in its place. The last sentence of the lemma, on the
operations applied to real numbers, is not stated.
* The other sentences inside proofs are lemmas of the library or are not formalized.
* The statements on blocks have n = b * d; the paper's proof treats n/d as an integer.
* "Õ(f)" is read as "O(f · (log n)^c) for some constant c".
-/
section Sec5Statements
open Finset Asymptotics Filter
namespace PaperStatements
open ThreeSumApsp
/-! ### 5.1 Directed APSP with small integer weights -/
/-! ### 5.2 3SUM, APSP, and Exact Triangle with real inputs -/
section ComparisonCounts
open ComparisonCounts
/-! #### Lemma 36(a): the parts argued in the paper -/
/-! Proof of Lemma 36(a): "APSP with real weights and no negative cycles can be computed by
successive squaring of the weight matrix, performing ⌈log₂ n⌉ such products." This is
`Theorem_21b_repeated_squaring` (Theorem 21(b)), which is stated for weights in any linearly ordered
commutative group, in particular for real weights. -/
/-! #### Lemma 36(b): the parts argued in the paper -/
/-! #### Lemma 37
The lemma says "we can build matrices X [...] and Y [...] and compute integers γ₂(r,c), (r,c) ∈ P,
with" γ(r,c) = (XY)[r,c] + γ₂(r,c). Read as a bare existence statement this would be trivial (take
X = Y = 0), so the statements below are about the matrices and the integers that the proof
constructs: `matX`, `matY`, `sameBlockCount`, for an arbitrary outcome `o` of the sort and an
arbitrary indexing `idx` of the pairs (color, block). The running time of the lemma is a hypothesis
of the library's lemma `conditional_corollary_38`. -/
/-! #### Corollary 38: correctness and parameter arithmetic -/
/-! #### Proof of Theorem 35: the arithmetic, with d := ⌊n^{1/40}⌋ -/
end ComparisonCounts
end PaperStatements
end Sec5Statements
/-!
## The word RAM: problems
First comes what it means that a program of the machine of `EndStatement.lean` solves a problem
within a time bound. Then come the problems: which number lies in which cell at the start, and
what a right answer is. No sentence of the paper is stated here; the sentences are the item
statements `Items.Theorem_5`, …, in the terms that are defined here. `docs/MACHINE.md`, Part 1,
goes through the definitions at length and compares the machine with the standard word RAM point by
point.
**What a reader of the statements about programs can skip.** Of the definitions of Sections 2 to 5
the statements `wordRam_theorem_5`, … use only these 28:
* Section 2: `N0`, `K`, `alpha`;
* Section 3: `LopInstance`, `LopInstance.commonNeighbors`, `LopInstance.InTriangle`,
`LopInstance.numTriangles`, `LopInstance.ofMatrices`, `GraphHasZeroTriangle`;
* Section 4: `rho`, `cost8`, `costQuery`, `cost9`, `entropy`, `rhoC`, `gammaOf`, `qOf`, `lnΛ`, `Rc`,
`epsStar`;
* Section 5, namespace `HintedMv`: `boolMul`, `toInt`, `vHintedOutput`, `MvHintedOutput`,
`uMvHintedOutput`, `Conjecture52`, `Conjecture57`, `Conjecture512`.
NOTE. Eight notions are defined twice: in `EndStatement.lean`, and with Mathlib for the statements
on the reductions and about programs. For each of them a statement, named in brackets, says that
the two definitions agree (a further form of `O(n^a)`, the bound `Within` on the steps of a phase,
is not compared):
* "a program solves a problem": there `Problem`, `Problem.SolvedBy` and the word sizes of
`Problem.SolvedInTime`, for one size `n`; here `Problem`, `Admissible`, `output` and `Solves`, for
several sizes (`Agreement_solves`);
* `O(n^r)`: there `BigO`, for a rational exponent and from `n = 2` on; in Section 3 `IsBigOPow`, for
a real exponent and all large `n` (`Agreement_bigO`, for `r ≥ 0`);
* "solved in time": there `Problem.SolvedInTime` and `BigO`, with a rational exponent and a bound
`T(n)` that is `O(n^r)` from `n = 2` on; here `SolvesWithin`, `SolvedInTimeAt` and `SolvedInTime`,
with a real exponent and the bound `C (n^a (log n)^e + 1)` at every size
(`Agreement_solvedInTime`, for a rational exponent `r ≥ 0` and `e = 0`); both are stated through
`Problem.SolvedBy`;
* Exact Triangle: `EndStatement.ExactTriangle` and `TriangleInstance.HasZeroTriangle`
(`Agreement_exactTriangle`);
* the (min,+)-product: `EndStatement.MinPlusProduct` and `IsMinPlusProduct`
(`Agreement_minPlusProduct`);
* APSP: `EndStatement.Path` and `EndStatement.APSP`, where a missing edge is `none`, and
`walkWeight`, `NoNegativeCycle` and `IsDistanceMatrix`, where it is `⊤`
(`Agreement_apsp_noNegativeCycle`, `Agreement_apsp_output`);
* a matrix written row by row: `EndStatement.rowByRow` and `rowMajor` (`Agreement_rowByRow`);
* the weight of a `k`-clique: the sum in `EndStatement.ZeroWeightKClique` and `cliqueWeight`
(`Agreement_cliqueWeight`).
**The machine** is defined in `EndStatement.lean` and nowhere else: `Instr`, `exec` and
`loadWords`. The paper works "in the standard word RAM model with O(log N)-bit words", and so
counts "operations on O(log N)-bit integers" (Section 2). There is no division, no shift, no
bitwise operation and no constant but 1: in its instructions the machine is weaker than the standard
word RAM.
NOTE. On four points the machine is generous; none of them changes an exponent:
* Every cell outside the input, with a positive or a negative name, holds 0 at the start, and
`Solves`, `SolvesWithin` and `RunsPhases` charge no space, so a table that is addressed directly
by a number costs nothing to set up (on a machine without this, lazy initialisation costs a
constant factor).
* The finitely many cells that a program names in its text need not be addressable by a word.
* The slope `b` of the word size is chosen after the exponent `κ` of the magnitude of the numbers.
* The inputs of phases and the queries arrive at no cost. -/
section WordRamProblems
namespace ThreeSumApsp.WordRam
open EndStatement (Instr exec loadWords)
/-! ### What it means to solve a problem
**The order of the choices.** In every statement the order is: the constants of the problem (the
exponent `κ` of the magnitude of the numbers, the `k` of `k`-Clique); then the program, the slope
`b` of the word size and the constant `C` of the time bound; then the instance; then the word size,
any number of bits that is admissible for the slope. So the program cannot depend on the instance
or on its size, and it cannot rely on long words. -/
/-! #### The word size and the output cells -/
/-! #### Problems, and solving a problem within a time bound -/
/-! #### Time bounds in one size `n`, for the problems of `EndStatement.lean` -/
/-! #### A query program that serves one query after the other -/
/-! #### Programs that receive their input in phases
A problem in phases has one program for each phase. The inputs of the phases are laid
out one after the other in the cells 0, 1, 2, …, but the input of a phase is written into its cells
only when the phase starts. Each program starts at its first instruction on the memory that the
previous phase has left; the first one starts on a memory of zeros. So a phase cannot see the input
of a later phase, and nothing is reset between phases. The output is read from the cells after the
last input. Receiving an input takes no steps, and the inputs of earlier phases stay in memory
unless a program overwrites them. What an earlier phase has left in the cells of a later input is
lost; the earlier phase knows which cells these are, since all sizes are given in Phase 1. (In the
running times of Corollary 40 the bound of a phase is at least the length of its input, if the
exponent `γ` of `Items.Corollary_40_general_times` is at most 1; so they do not depend on inputs
being free.) -/
/-! ### The problems of the paper, their inputs and their answers
**Layout.** Matrices are written row by row, one number per cell, as signed words. Booleans are
written as 0 and 1, and indices and vertices count from 0. The first cells hold the sizes. The
bound on the absolute values of the numbers is not written into memory. For the matrix problems it
is a number `U` that is part of the instance as a mathematical object (`ThinPair`); for the problems
in the form of `EndStatement.Problem` it is a hypothesis of `SolvesWithin`. In the statements it is
a fixed power of the size, with an exponent that is fixed before the program (and 1 for the 0/1
matrices of the lopsided triangle problems). A program for a problem with an output has to accept,
and to leave the output in the cells right after the input. -/
/-! #### How matrices and Booleans are written -/
/-! #### The wanted entries of a thin matrix product (Theorems 1, 5, 25 and 30, Corollaries 26 and
32) -/
/-! #### The two-stage data structure for a thin matrix product (Section 4) -/
/-! #### The lopsided triangle problems (Definitions 13 and 14) -/
/-! #### Exact Triangle, 3SUM, the (min,+)-product and APSP
These four are the problems `ExactTriangle`, `ThreeSum`, `MinPlusProduct` and `APSP` of
`EndStatement.lean`. -/
/-! #### Exact Triangle on `n`-vertex graphs -/
/-! #### Zero-Weight, Min-Weight and Max-Weight `k`-Clique (Corollary 39)
Zero-Weight `k`-Clique is the problem `ZeroWeightKClique k` of `EndStatement.lean`. The other two
have its input: for each ordered pair of parts `(p, q)`, in row-major order, an `n × n` block of
numbers, where `w p q u v` is the weight between vertex `u` of part `p` and vertex `v` of part `q`.
NOTE. All `k²` blocks are input, but only the blocks with `p < q` count; the others may hold
anything within the bound on the numbers of the input. The paper does not fix a layout. -/
/-! #### The three hinted matrix-vector problems of [vdBNS19] (Corollary 40) -/
end ThreeSumApsp.WordRam
end WordRamProblems
/-!
## Agreement with the definitions of EndStatement.lean
Eight notions have two definitions each. `EndStatement.lean` defines them for the five claims, with
Lean's core library only, for integers and square matrices. The statements on the reductions and
the statements about programs use definitions with Mathlib: the paper needs Exact Triangle and the
(min,+)-product also over the real numbers, matrices that are not square, problems with several
sizes, and time bounds with real exponents and logarithmic factors. The statements below say that
the two definitions of each notion agree. APSP has two statements, one for the promise and one for
the output.
-/
section AgreementStatements
open ThreeSumApsp.WordRam
namespace PaperStatements
open ThreeSumApsp
end PaperStatements
end AgreementStatements
/-!
## The word RAM: running times
An item statement is a running-time sentence of the paper, written as a proposition about programs
of the machine of `EndStatement.lean` and named after its item, such as `Items.Theorem_5` or
`Items.Corollary_26`. Its docstring quotes the sentence. The notions of solving are `Solves`,
`IsDataStructure`, `SolvesWithin` and `RunsPhases`, and the forms derived from them (`SolvedInTime`,
`AchievesVHinted`, …); the layouts of the inputs and the order of the choices are explained with
them. The definitions only say what the sentences mean. That they hold is stated by the theorems
`wordRam_theorem_5`, `wordRam_corollary_26`, …. The five claims of `EndStatement.lean` are five of
the bounds of `Theorem_19`, `Theorem_22_second` and `Corollary_39_zero`.
* **Order.** Sections 2 to 5 in the paper's order, then the introduction. Its Theorems 1 to 4
restate and combine the later items (here Theorem 3 is stated through Corollary 26, and Theorem 4
through Corollary 40), so they stand last.
* **Items and propositions.** Some items have several propositions, for instance `Corollary_26` for
the data structure and `Corollary_26_wanted` for the entries at a given set of positions; and some
propositions hold several bounds of their item, joined by "and", for instance `Theorem_19`.
* **Definitions that are not items.** `thinDom`, `HasDataStructure` and `theorem30Dom` abbreviate
hypotheses or sentences that occur in more than one proposition. `DataStructureBelow` and
`WantedBelow` state the last sentences of Theorems 3 and 1 ("More generally, …") with a bound `ε₀`
in the place of 0.1204.
* **Departures.** Where a proposition departs from the printed sentence, for instance by a lower
bound `D ≥ 1` that the paper leaves out, its docstring, or that of the definition through which it
is stated, says so, mostly in a paragraph that begins with NOTE.
* **Real parameters.** Corollaries 31 and 32 have real parameters `c` and `θ`. The statements do
not mention the numbers `⌈cm⌉` and `⌈θm⌉` of the proof; they only say that programs with certain
time bounds exist. So they make sense, and are stated, for all real `c` and `θ`, although a
program is a finite text: a proof may use rational parameters close to `c` and `θ`, which the
strict inequality `ε < R_c(γ)` leaves room for.
* **Not stated about programs.** The other sentences of the paper about running time are not stated
about programs. The machine has neither random bits nor real numbers: Theorem 35 (with the half
of Theorem 2 on real inputs) needs both, and Corollary 38 needs real numbers. Theorem 34 rests on
Theorem 33, which the paper proves and which is not proved here, and on μ, which is defined
through ω(1, μ, 1). For these three items see the library's lemmas `conditional_theorem_34`,
`conditional_corollary_38` and `conditional_theorem_35`, where Theorem 33 and Lemmas 36 and 37 are
hypotheses. Theorems 17 and 21 speak of an arbitrary solver, while each item statement is about
one fixed program. The time bound of Lemma 29 enters the bound (8) of Theorem 30. -/
section WordRamItems
namespace ThreeSumApsp.WordRam
open EndStatement (Instr)
namespace Items
/-! ### Section 2: Theorem 5 -/
/-! ### Section 3: Corollaries 15 and 16, Theorems 19 and 22 -/
/-! ### Section 4: Theorems 24 and 25, Corollary 26, Theorem 30, Corollaries 31 and 32 -/
/-! ### Section 5: Corollaries 39 and 40 -/
/-! ### Section 1, the introduction: Theorems 1 to 4 -/
end Items
end ThreeSumApsp.WordRam
end WordRamItems
end
end
section
-- Source module: ThreeSumApsp.Util.Asymptotics.Dominated
/-!
# Bounds up to a constant factor, in several parameters
The paper writes `f = O(g)` for functions of several parameters that are tied by side conditions,
such as `D ^ 18 ≤ n` for the parameters `n`, `D`, `w`. `Dominated dom f g` says this: there is a
constant `C ≥ 0` with `f x ≤ C * g x` for every tuple `x` of parameters that satisfies `dom x`. If
there is no side condition, `dom` is `fun _ => True`. The type `α` of the parameters is best a
structure with one named field for each of them, so that a bound reads
`Dominated (fun p => p.D ^ 18 ≤ p.n) (fun p => cost p) fun p => p.n ^ 2 / p.D`.
The lemmas of this file are the steps that the paper takes without comment: such bounds can be
chained (`Dominated.trans`), added (`Dominated.add`, `Dominated.add_add`), multiplied and divided
(`Dominated.mul`, `Dominated.mul_left`, `Dominated.const_mul`, `Dominated.pow`,
`Dominated.div_right`), joined by a case distinction (`Dominated.ite`), restricted to a smaller
domain (`Dominated.mono_dom`) and specialized (`Dominated.comp`). With them no proof has to name a
constant. A bound enters the calculus by `Dominated.of_le`, `Dominated.of_le_const_mul` or
`Dominated.of_exists_const`, and leaves it by `obtain ⟨C, hC, hle⟩` or `Dominated.exists_const_and`.
For functions of one natural number, `Dominated.of_eventually` takes a bound for all large `n`,
`Dominated.isBigO` gives Mathlib's `f =O[atTop] g`, and `isBigO_comp_add_one` substitutes a size
that need not tend to infinity.
In every closure lemma the bound comes first and the side conditions follow.
For nonnegative `f` and `g` the notion is Mathlib's `f =O[𝓟 {x | dom x}] g`, big-O along the
principal filter of the domain (`dominated_iff_isBigO_principal`). The one-sided form is taken
because a running time is bounded from above only.
## The notions of "bounded up to a constant" in this library
* `f =O[atTop] g` of Mathlib bounds `|f|` for large `n`. In this sense `IsBigOPow f a` is `O(n^a)`,
`IsPowPolylog f a` is `O(n^a (log n)^e)` for some `e`, and `IsPowLittleO f a` is `n^{a+o(1)}`.
The exponents of the theorems are stated with them.
* `UpperBigOPow`, `UpperPowPolylog` and `UpperPowLittleO` are the same three classes as bounds on
`f` and not on `|f|`, for running times. A two-sided bound gives the one-sided one
(`IsBigOPow.upperBigOPow`, `IsPowPolylog.upperPowPolylog`, `IsPowLittleO.upperPowLittleO`).
* `Dominated dom f g` bounds `f` on the whole domain, for several parameters. It comes from a bound
for large `n` by `Dominated.of_eventually` and gives one by `Dominated.isBigO`.
* `Scale.SoftO t e` says that a count `t` with values in `ℕ` is `Dominated` by a monomial with the
exponents `e`, up to powers of one more quantity; the tactic `growth` reads the exponents off an
explicit expression. It gives a `Dominated` bound by `Scale.SoftO.dominated`. Its instance
`SoftOSqrtPow` gives `IsPowPolylog` by `SoftOSqrtPow.isPowPolylog`.
-/
@[expose] public section
open Filter Asymptotics
namespace ThreeSumApsp
namespace Dominated
variable {α β : Type*} {dom dom' : α → Prop} {f f' g g' h k f₁ f₂ g₁ g₂ : α → ℝ}
/-! ### Entering the calculus -/
/-- A bound with an explicit nonnegative constant. -/
theorem of_le_const_mul {C : ℝ} (hC : 0 ≤ C) (hfg : ∀ x, dom x → f x ≤ C * g x) :
Dominated dom f g :=
⟨C, hC, hfg⟩
/-- A bound with constant one. -/
theorem of_le (hfg : ∀ x, dom x → f x ≤ g x) : Dominated dom f g :=
⟨1, zero_le_one, fun x hx => by simpa only [one_mul] using hfg x hx⟩
/-! ### Leaving the calculus -/
/-! ### Chaining, restricting, substituting -/
/-- `f = O(g)` and `g = O(h)` give `f = O(h)`. -/
protected theorem trans (hfg : Dominated dom f g) (hgh : Dominated dom g h) :
Dominated dom f h := by
obtain ⟨C, hC, hf⟩ := hfg
obtain ⟨D, hD, hg⟩ := hgh
refine ⟨C * D, mul_nonneg hC hD, fun x hx => (hf x hx).trans ?_⟩
rw [mul_assoc]
exact mul_le_mul_of_nonneg_left (hg x hx) hC
/-- The left side may be replaced by a smaller function. -/
theorem mono_left (hfg : Dominated dom f g) (hle : ∀ x, dom x → f' x ≤ f x) : Dominated dom f' g :=
(ThreeSumApsp.Dominated.of_le hle).trans hfg
/-- The right side may be replaced by a larger function. -/
theorem mono_right (hfg : Dominated dom f g) (hle : ∀ x, dom x → g x ≤ g' x) : Dominated dom f g' :=
hfg.trans (ThreeSumApsp.Dominated.of_le hle)
/-- Both sides may be replaced by functions that agree with them on the domain. -/
protected theorem congr (hfg : Dominated dom f g) (hf : ∀ x, dom x → f x = f' x)
(hg : ∀ x, dom x → g x = g' x) : Dominated dom f' g' :=
(hfg.mono_left fun x hx => (hf x hx).ge).mono_right fun x hx => (hg x hx).le
/-- Substituting the parameters: a bound in `x` gives a bound in `y` at `x = φ y`, on every domain
that `φ` maps into `dom`. -/
protected theorem comp (hfg : Dominated dom f g) (φ : β → α) {dom' : β → Prop}
(hφ : ∀ y, dom' y → dom (φ y)) : Dominated dom' (fun y => f (φ y)) fun y => g (φ y) := by
obtain ⟨C, hC, hf⟩ := hfg
exact ⟨C, hC, fun y hy => hf (φ y) (hφ y hy)⟩
/-! ### Sums and case distinctions -/
/-! ### Products and quotients -/
/-- `O(g₁) · O(g₂) = O(g₁ g₂)` for nonnegative `f₁`, `f₂`. -/
protected theorem mul (h₁ : Dominated dom f₁ g₁) (h₂ : Dominated dom f₂ g₂)
(hf₁ : ∀ x, dom x → 0 ≤ f₁ x) (hf₂ : ∀ x, dom x → 0 ≤ f₂ x) :
Dominated dom (fun x => f₁ x * f₂ x) fun x => g₁ x * g₂ x := by
obtain ⟨C, hC, h₁⟩ := h₁
obtain ⟨D, hD, h₂⟩ := h₂
refine ⟨C * D, mul_nonneg hC hD, fun x hx => ?_⟩
rw [mul_mul_mul_comm]
exact mul_le_mul (h₁ x hx) (h₂ x hx) (hf₂ x hx) ((hf₁ x hx).trans (h₁ x hx))
/-! ### Functions of one natural number -/
end Dominated
end ThreeSumApsp
end
end
section
-- Source module: ThreeSumApsp.Machine.Steps
/-!
# Running the word RAM: words, steps, pieces of code, straight-line code, branches
What the proofs about compiled code need to know about the word RAM in which the paper's claims are
stated.
* **Words.** `wd W v` is the word of the integer v. If v is in the range of signed words
(`InRange`), the word gives back v (`toInt_wd`).
* **Steps.** The end statement defines only whole runs (`exec`). A configuration (`Cfg`) and a
single step (`step`) are defined here; `exec_succ_of_step` and `exec_succ_of_verdict` say that
`exec` takes one step at a time.
* **Runs.** `Steps P n c c'`: exactly n steps lead from c to c', none of them a verdict.
Runs are composed by `Steps.trans`; a run that ends before a verdict gives the value of `exec`
(`exec_of_steps`), and more time does not change that value (`exec_mono`).
* **Code.** `CodeAt P pos l`: the program P has the instructions of the list l from position pos
on.
* **Straight-line code.** Six instructions only change the memory (`Straight`, `effect`); a list
of them runs through in its length (`steps_straight`).
* **Known numbers.** On cells that hold the words of known numbers, an instruction writes the word
of a known number: `effect_add`, …, `effect_store` for the memory; `steps_add`, `steps_sub`,
`steps_load`, `steps_store` for the step.
* **Branches and verdicts.** A branch on a cell that holds a known number is `steps_bltz`;
`Steps.branch` turns its two outcomes into the two outcomes of a test. The verdicts are
`step_accept` and `step_reject`.
* **Framing.** `AgreeOutside s m m'`: the memories m and m' are equal outside the set s of cells.
For code without stores such a set can be read off the text (`WritesIn`, `agreeOutside_effects`).
-/
@[expose] public section
namespace ThreeSumApsp.WordRam
open EndStatement (Instr exec loadWords)
variable {W : ℕ} {P : List Instr}
/-! ## Words -/
/-! ## Configurations and single steps -/
/-! ## Runs -/
/-! ## Pieces of code -/
/-! ## Straight-line code -/
@[simp] theorem effects_nil (m : ℤ → BitVec W) : effects [] m = m := rfl
@[simp] theorem effects_cons (i : EndStatement.Instr) (l : List EndStatement.Instr) (m : ℤ → BitVec W) :
effects (i :: l) m = effects l (effect i m) := rfl
/-! ## Single instructions on cells that hold known numbers -/
section known
variable {m : ℤ → BitVec W} {i j k a b : ℤ}
end known
/-! ## Branches and verdicts -/
/-! ## Framing -/
section framing
variable {s t : Set ℤ} {m m' m₁ m₂ m₃ : ℤ → BitVec W} {a : ℤ}
end framing
end ThreeSumApsp.WordRam
end
end
section
-- Source module: ThreeSumApsp.Lang.Frames
/-!
# Local variables as a list
In the proof of a procedure body the state is written out as ⟨frame [a, b, …], μ⟩: the list
holds the local variables 0, 1, …, and all further ones are 0. An assignment to local x replaces
entry x of the list (setLocal). The rules of this file treat one statement each. They are told the
value that is assigned or stored, and they ask for one fact about each expression: that its
evaluation stays within the limits and gives this value (Expr.Gives). This fact and the comparison
of the costs are proved by default from the hypotheses in the context. Ends.forFrame and
Ends.forShape are the rules for counting loops in this form. In the names of the rules, To says
that the state is ⟨frame l, μ⟩.
Locals by name, and locals whose values do not matter:
* `setLocals l [(x, a), (y, b), …]` is the list `l` after the assignments `x := a`, `y := b`, ….
With the names of the locals for `x`, `y`, … it describes the locals of a procedure by name:
`setLocals [] [(Size, n), (Bound, U), …]`.
* `updateLocals loc [(x, a), (y, b), …]` is the same for locals that are not given as a list. A
lemma about a piece of text that several procedures share is stated for arbitrary locals `loc`.
* `refreshLocals l loc xs` is the list `l` with the entries `xs` read from `loc`.
* `LocalsBut xs l loc` says that `loc` agrees with `frame l` except perhaps at the locals `xs`. In
an invariant, `xs` are the scratch variables. `Ends.asFrame` goes from such locals to a list, and
`LocalsBut.of_eq` comes back.
* `Ends.pieceTo` and `Ends.pieceToThen` use a lemma about a piece of text that assigns only the
locals `xs`: afterwards the locals are `refreshLocals l loc' xs`, where `loc'` are the locals of
which the lemma speaks. The lemma need not mention the locals that the piece does not assign.
* `Ends.forScratch` is the rule for a counting loop whose body may change the scratch variables
`xs`: the round says nothing about the locals.
-/
@[expose] public section
namespace Light
variable {lim : Limits} {P : Program} {d : ℕ}
/-! ## The list of the locals -/
/-! ## The value of an expression -/
/-! ## One statement -/
section rules
variable {l : List ℤ} {μ : ℕ → ℤ} {T : ℕ} {Q : State → Prop}
end rules
/-! ## Locals by name, and locals whose values do not matter -/
/-- Two lists give the same local variables: they are equal up to zeros at the end. -/
def SameFrame (l m : List ℤ) : Prop := Light.frame l = Light.frame m
/-- The empty list gives the same locals as itself. -/
@[simp] theorem sameFrame_nil : SameFrame [] [] := rfl
section
variable {xs : List ℕ} {l l' : List ℤ} {loc μ : ℕ → ℤ}
/-! ## A piece of program text with a lemma of its own -/
variable {T T₁ : ℕ} {s s₁ s₂ : Stmt} {Q R : State → Prop}
/-! ## Counting loops with scratch variables -/
end
end Light
end
end
section
-- Source module: ThreeSumApsp.Util.Log
/-!
# Logarithms and real powers
Small facts on `Real.log`, `Real.logb`, `Nat.clog`, `Real.sqrt` and real powers that the estimates
of the paper use silently.
* Values, in the namespace `Real` and named by Mathlib's convention: `1 / 2 < log 2 < 1`,
`log 4 = 2 log 2`, `log 9 = 2 log 3`, `1 ≤ log 4`, `1 / 2 ≤ log x` for `x ≥ 2`, `1 ≤ log x` for
`x ≥ 3`, `log₂ 7 < 2.81`, `4 ≤ √D` for `D ≥ 16`.
* The rounded logarithm: `⌈log_b n⌉ < log_b n + 1` (`Real.natCast_clog_lt_logb_add_one`),
`c ^ ⌈log_b n⌉ ≤ c * n ^ (log_b c)` (`Real.pow_clog_le_mul_rpow_logb`).
* The definition `logU u = log (max u 2)`, the paper's `log U`.
-/
@[expose] public section
namespace Real
/-! ### Values -/
/-- `1 / 2 < log 2`. -/
theorem one_half_lt_log_two : 1 / 2 < log 2 :=
lt_trans (by norm_num) log_two_gt_d9
/-- `log 4 = 2 log 2`. -/
theorem log_four : log 4 = 2 * log 2 := by
rw [show (4 : ℝ) = 2 ^ 2 by norm_num, log_pow, Nat.cast_ofNat]
/-- `1 ≤ log 4`. -/
theorem one_le_log_four : 1 ≤ log 4 := by
linarith [log_four, one_half_lt_log_two]
/-! ### The rounded logarithm `Nat.clog` -/
end Real
namespace ThreeSumApsp
end ThreeSumApsp
end
end
section
-- Source module: ThreeSumApsp.Util.CountingSort
/-!
# The pure side of counting sort
`N` items `0, …, N - 1` have keys `kf 0, …, kf (N - 1)`. A stable sort by key puts item `j` at the
place `sortPos kf N j`: the number of items with a smaller key plus the number of earlier items with
the same key.
This is a bijection of `{0, …, N - 1}` (`eq_of_sortPos_eq`, `exists_sortPos_eq`) that is increasing
for the order "smaller key, or same key and earlier" (`sortPos_lt_sortPos_iff`).
-/
@[expose] public section
namespace ThreeSumApsp
section
variable (kf : ℕ → ℕ)
@[simp] theorem cntEq_zero (t : ℕ) : cntEq kf t 0 = 0 := rfl
@[simp] theorem cntLt_zero_right (t : ℕ) : cntLt kf t 0 = 0 := rfl
end
variable {kf : ℕ → ℕ} {N K : ℕ}
end ThreeSumApsp
end
end
section
-- Source module: ThreeSumApsp.Util.Digits
/-!
# Strings of digits as numbers
The paper indexes its arrays by strings (Section 2.3.1). A program indexes them by numbers: the
string `d₁ d₂ ⋯ d_n` of digits in base `b` is coded by the number `d₁ b^{n-1} + ⋯ + d_n`. The first
digit (the paper's level 1) is the most significant one, so the strings that begin with a given
digit have consecutive codes, and a slice of an array is a contiguous part of it.
* `code` is the number of a string, `digit` reads one digit of a number, `digitList` all of them,
and `ofDigitList` is Horner's rule.
* `code` and `digit` undo each other (`digit_code`, `code_digit`), so the strings of length `n`
correspond to the numbers below `b^n` (`codeEquiv`).
* For lists of digits, `digitList` undoes `ofDigitList` (`digitList_ofDigitList`). A list of `n`
digits has a value below `b^n` (`ofDigitList_lt`), which determines it (`eq_of_ofDigitList_eq`).
One more digit at the end is one more step of Horner's rule (`ofDigitList_append_singleton`,
`ofDigitList_take_succ`).
* For an alphabet `α` whose letters are numbered by `e : α ≃ Fin b`, `codeStr e` and `decodeStr e`
go from strings over `α` to numbers and back, so these strings, too, correspond to the numbers
below `b^n` (`strEquiv`). `digitsStr e` is the list of the digits of such a string; Horner's rule
computes the code from it (`ofDigitList_digitsStr`).
Mathlib's `Nat.ofDigits` and `finFunctionFinEquiv` put the least significant digit first, so they
would make a slice a scattered part of an array; this is why the codes are defined here.
-/
@[expose] public section
namespace ThreeSumApsp
/-! ## Strings of numbers below `b` -/
/-! ## Lists of digits -/
/-- The empty list of digits has the value `0`. -/
@[simp]
theorem ofDigitList_nil (b : ℕ) : ofDigitList b [] = 0 :=
rfl
/-! ## Strings over a numbered alphabet -/
variable {α : Type} {b : ℕ} (e : α ≃ Fin b)
/-! ## The list of the digits of a string -/
section
variable {α : Type} {b : ℕ} (e : α ≃ Fin b) {n : ℕ}
end
end ThreeSumApsp
end
end
section
-- Source module: ThreeSumApsp.Spec.Sec2.Theorem5.Alphabets
/-!
# The alphabets of Schönhage's identity as digits
Section 2.2 names seven left variables, seven right variables, ten output variables and
ten terms; Section 2.3.1 indexes arrays by strings over these alphabets. Here every
letter gets a digit, so that a string becomes a number (`codeStr`).
* The left variables `x₁ x₂ x₃ p₁₁ p₁₂ p₂₁ p₂₂` are the digits `0, …, 6`; likewise the right
variables.
* The output variables `z₁₁ z₁₂ … z₃₃ z₀` are the digits `0, …, 9`, and the terms `P₁₁ … P₃₃ P₀`
likewise, so that `z_ij` and `P_ij` have the same digit `3(i-1) + (j-1)`, and `z₀` and `P₀` have
the digit 9.
* Left and right strings are numbers in base 7 (`codeL`, `codeR`), output strings, vertices and
leaves in base 10 (`codeO`, `codeT`), strings of indices of outer variables in base 3
(`codeOuter`) and of inner variables in base 4 (`codeInner`), always with level 1 most
significant.
* Which output variables are inner, and which term contributes to which output variable (Section
2.2), is read off the digits (`outVar_isInner_iff`, `contributes_iff`).
* The coefficients of the linear forms `φ_λ` and `ψ_λ` (Section 2.2) are written out as the rows of
two 10 × 7 tables, `phiTable` and `psiTable`, which the programs store row after row
(`phiFlat_spec`, `psiFlat_spec`).
-/
@[expose] public section
namespace ThreeSumApsp.Spec
/-! ## Digits -/
/-! Applying one of the five bijections gives the digit. -/
@[simp] theorem leftEquiv_apply (s : LeftVar) : leftEquiv s = leftIdx s := rfl
@[simp] theorem rightEquiv_apply (t : RightVar) : rightEquiv t = rightIdx t := rfl
@[simp] theorem outEquiv_apply (z : OutVar) : outEquiv z = outIdx z := rfl
@[simp] theorem termEquiv_apply (lam : Term) : termEquiv lam = termIdx lam := rfl
@[simp] theorem pairEquiv_apply (p : Fin 2 × Fin 2) : pairEquiv p = pairIdx p := rfl
/-! ## Codes of strings -/
/-! ### Codes of output strings and of vertices
The general facts about `codeStr`, under names of their own for the two codes that occur most. -/
/-! ## The structure of the identity, in digits -/
/-! ## The coefficients of the linear forms, as tables -/
/-- The table of the `φ_λ(s)` has 70 entries. -/
@[simp] theorem length_phiFlat : phiFlat.length = 70 := rfl
/-- The table of the `ψ_λ(t)` has 70 entries. -/
@[simp] theorem length_psiFlat : psiFlat.length = 70 := rfl
end ThreeSumApsp.Spec
end
end
section
-- Source module: ThreeSumApsp.Sec2.Lemma10
/-!
# Sections 2.4.1 and 2.4.2: the encodings, the recursion `Pruned`, and Lemma 10
The encoding of an array is computed by `Full` with the other array left out (`computeEncoding_phi`,
`computeEncoding_psi`). `Pruned(S)` is `Full` without that phase, and each call computes only the
outputs in the set `S` that is passed to it. Lemma 10 (`lemma_10`) has three claims.
* Values. One induction gives a closed form (`Pruned_eq_restrictTo_sum`): at a string of `S`,
`Pruned` returns the sum, over the leaves contributing to the string, of the product of the two
numbers looked up at the leaf. With the encodings of `a` and `b` this sum is `Mult(a, b)` by
definition (`Lemma10.values`), which is what `Full` returns by Lemma 7
(`Pruned_eq_restrictTo_Full`). The paper compares `Pruned` with `Full` level by level instead.
* Leaves visited. A vertex below the root is called exactly if it contributes to a string of `U`
(`Pruned.called_iff_root_or`, `Pruned.called_iff`; the step of the induction is
`Pruned.called_succ`). For leaves this is `Lemma10.leaves_visited`. The set passed to a vertex
consists of the suffixes of these strings (`Pruned.mem_passed_iff`; no later proof uses this).
* Total size. A set of strings is no larger than its set of leaves, because a string is determined
by its private leaf (`card_le_card_Leaves`), and the leaves of `Leaves(S)` that begin with
`λ` are the leaves of `Leaves(S_λ)` with `λ` put in front (`card_Leaves_succ`). So the
sets passed at one depth have total size at most `|Leaves(U)|` (`Pruned.sum_card_passed_le`), and
there are `L + 1` depths (`Lemma10.total_size`).
Which calls `Pruned` makes depends only on the set passed to it, so the second and the third claim
are proved for any two arrays in place of the two encodings.
-/
@[expose] public section
open Finset
namespace ThreeSumApsp
/-! ### Section 2.4.1: the encodings -/
/-! ### Section 2.4.2: the sets `S_λ` of step (2) -/
/-! ### Lemma 10, first claim: the values -/
/-- An array restricted to the empty set is the zero array. -/
@[simp]
theorem restrictTo_empty {n : ℕ} (c : OutStr n → ℤ) : restrictTo ∅ c = 0 :=
rfl
/-! ### Lemma 10, second claim: the calls that are made and the sets passed to them -/
/-! ### Lemma 10, third claim: the total size of the sets passed -/
end ThreeSumApsp
end
end
section
-- Source module: ThreeSumApsp.Sec2.Orders
/-!
# Section 2.4.3, first half: the orders of the leaves and equation (5)
A leaf that contributes to an output string with inner set `Q` is free at the `m` levels of `Q` and
fixed at the other levels. Its order is `m` minus the number of levels at which it chooses `P₀`.
* One level. A term contributes to `z` exactly if `z = z₀` or the term is the private term of `z`
(`Term.contributes_iff`), so a leaf contributing to a string chooses `P₀` only at levels of the
inner set (`P0Levels_subset`). The numbers of terms of each kind that contribute to a variable,
and of variables of each kind to which a term contributes, are read off the ten terms.
* Counts. `10^m` leaves contribute to a string: ten terms for each level of `Q`
(`card_filter_contributes`). The other counts sort strings by the set of levels at which they
have a letter of a given kind (`Finset.card_pi_places_card`, `Finset.card_places_card`): `α_d` of
the leaves contributing to a string have order `d` (`sec2_card_contributing_of_order`), the whole
tree has `β_d` leaves of order `d` (`card_filter_order_eq`), with `β₀ = M` (`beta_zero_eq_M`), and
a leaf of order `d` contributes to `binom(L-m+d, d)` strings (`sec2_card_outStr_of_leaf`). Figure
6 shows these numbers for `L = 6` and `m = 2` (`figure_6`).
* Equation (5): the quotient `β_d / β_{d-1}` comes from the recurrence of the binomial coefficients
(`Equation5.ratio_nat`, `eq_5_ratio`); for `L = 19m` it is less than `1/2` (`eq_5_bound`); so
`β_d ≤ 2^{-d} M` by induction on `d` (`eq_5`).
-/
public section
open Finset
namespace ThreeSumApsp
/-! ### One level: which terms contribute to which variables -/
/-! ### The order of a leaf -/
/-! ### The counts -/
/-- Section 2.4.3: "In particular, β₀ = binom(L, m) 9^{L-m}". -/
theorem beta_zero (L m : ℕ) : beta L m 0 = L.choose m * 9 ^ (L - m) := by
simp [beta]
/-- Section 2.4.3: "β₀ = binom(L, m) 9^{L-m} = M". -/
theorem beta_zero_eq_M (L m : ℕ) : beta L m 0 = ThreeSumApsp.M L m := by
rw [beta_zero, ThreeSumApsp.M, ThreeSumApsp.K, ThreeSumApsp.N0, ← pow_mul, mul_comm (L - m) 2, pow_mul]
norm_num
/-- `β_d` is positive when `m ≤ L`. -/
theorem beta_pos {L m : ℕ} (hmL : m ≤ L) (d : ℕ) : 0 < beta L m d :=
Nat.mul_pos (Nat.choose_pos (by omega)) (by positivity)
/-- The equality in equation (5) without division: `β_d (L-m+d) = 9 (m-d+1) β_{d-1}` for
`1 ≤ d ≤ m ≤ L`. -/
theorem Equation5.ratio_nat {L m : ℕ} (hmL : m ≤ L) (d : ℕ) (hd1 : 1 ≤ d) (hd : d ≤ m) :
beta L m d * (L - m + d) = 9 * (m - d + 1) * beta L m (d - 1) := by
-- With `k = m - d` this is `binom(L, k) (L - k) = binom(L, k + 1) (k + 1)`, times a power of 9.
have hchoose : L.choose (m - d + 1) * (m - d + 1) = L.choose (m - d) * (L - m + d) := by
rw [Nat.choose_succ_right_eq, show L - (m - d) = L - m + d by omega]
have hpow : 9 ^ (L - m + d) = 9 * 9 ^ (L - m + (d - 1)) := by
rw [show L - m + d = L - m + (d - 1) + 1 by omega, pow_succ, mul_comm]
rw [beta, beta, show m - (d - 1) = m - d + 1 by omega, hpow]
calc L.choose (m - d) * (9 * 9 ^ (L - m + (d - 1))) * (L - m + d)
= 9 * 9 ^ (L - m + (d - 1)) * (L.choose (m - d) * (L - m + d)) := by ring
_ = 9 * 9 ^ (L - m + (d - 1)) * (L.choose (m - d + 1) * (m - d + 1)) := by rw [hchoose]
_ = 9 * (m - d + 1) * (L.choose (m - d + 1) * 9 ^ (L - m + (d - 1))) := by ring
/-- Section 2.4.3, the equality in equation (5), for every `L ≥ m` (it is used again as equation (7)
in Section 4.3): "β_d / β_{d-1} = 9(m-d+1) / (L-m+d)" for `1 ≤ d ≤ m`.
NOTE. The paper prints the equality under `L = 19m` in (5) and under `L ≥ 10m` in (7); here it is
stated for every `L ≥ m`. -/
theorem eq_5_ratio {L m : ℕ} (hmL : m ≤ L) (d : ℕ) (hd1 : 1 ≤ d) (hd : d ≤ m) :
(beta L m d : ℚ) / (beta L m (d - 1) : ℚ)
= 9 * ((m : ℚ) - (d : ℚ) + 1) / ((L : ℚ) - (m : ℚ) + (d : ℚ)) := by
have hm : (m : ℚ) ≤ L := by exact_mod_cast hmL
have hd0 : (1 : ℚ) ≤ d := by exact_mod_cast hd1
have hbeta : (0 : ℚ) < beta L m (d - 1) := by exact_mod_cast beta_pos hmL (d - 1)
have hnat := congrArg (Nat.cast : ℕ → ℚ) (Equation5.ratio_nat hmL d hd1 hd)
push_cast [Nat.cast_sub hmL, Nat.cast_sub hd] at hnat
rw [div_eq_div_iff hbeta.ne' (by linarith), hnat]
end ThreeSumApsp
end
end
section
-- Source module: ThreeSumApsp.Util.Choose
/-!
# Binomial coefficients
Upper bounds. A single summand of the binomial expansion of `(a + b) ^ n` is at most the whole sum
(`Nat.choose_mul_pow_mul_pow_le`); with `a = 1` this is `binom(n, k) * b ^ (n - k) ≤ (b + 1) ^ n`
(`Nat.choose_mul_pow_le`), which the paper uses with `b = 9`. And `binom(n, k) ≤ (e n / k) ^ k`
(`Nat.choose_le_exp_mul_div_pow`).
A lower bound. For `k ≤ n`, the largest of the `n + 1` terms `binom(n, j) k^j (n-k)^{n-j}` of the
expansion of `n^n = (k + (n-k))^n` is the one with `j = k`: the terms increase up to `j = k` and
decrease from there on. This gives the standard lower bound on a binomial coefficient
(`Nat.pow_self_le_mul_choose_mul_pow_mul_pow`), which Section 4.4 uses in the proof of Corollary 26
and, written with the entropy function as `e^{n H(k/n)}/(n+1) ≤ binom(n, k)`, in the proof of
Corollary 31.
-/
public section
namespace Nat
/-! ## Upper bounds -/
/-- One summand of the binomial expansion of `(a + b) ^ n` is at most `(a + b) ^ n`. -/
theorem choose_mul_pow_mul_pow_le (a b n k : ℕ) :
n.choose k * a ^ k * b ^ (n - k) ≤ (a + b) ^ n := by
obtain hk | hk := le_or_gt k n
· rw [add_pow]
calc n.choose k * a ^ k * b ^ (n - k) = a ^ k * b ^ (n - k) * n.choose k := by ring
_ ≤ _ := Finset.single_le_sum (f := fun k => a ^ k * b ^ (n - k) * n.choose k)
(fun _ _ => Nat.zero_le _) (Finset.mem_range.2 (Nat.lt_succ_of_le hk))
· rw [Nat.choose_eq_zero_of_lt hk, zero_mul, zero_mul]
exact Nat.zero_le _
/-! ## The largest term of a binomial expansion -/
end Nat
end
end