Documentation

MIPRE.Foundations.Halting.Arith

Arithmetic in the ambient model: increment, unary conversion, multiplication, polynomials #

The arithmetic the wrapper decider (Halting/Wrapper.lean) and the compressor's decider (Halting/Compressor.lean) need, each with its cost:

Costs are polynomial in the values (the unary numerals are as long as the values); the polynomial evaluation is bounded by an explicit Polynomial ℕ in the argument (Prog.polyProg_runs), which is what the time accounting downstream composes.

The successor of a binary numeral #

The successor of a binary numeral, least significant bit first.

Equations
Instances For
    theorem MIPRE.Cost.Data.inc_bits (n : ℕ) :
    inc n.bits = (n + 1).bits

    The successor on canonical binary numerals is the successor.

    The first phase of the increment: (rest, acc) ↦ (acc', rest') with acc'.reverse ++ rest' = acc.reverse ++ inc rest.

    Equations
    Instances For
      theorem MIPRE.Cost.Data.size_encode_append (l₁ l₂ : BitStr) :
      (encode (l₁ ++ l₂)).size + 1 = (encode l₁).size + (encode l₂).size

      Binary to unary #

      The fold k ↦ 2k + b over bits, most significant first.

      Equations
      Instances For

        Polynomials by their coefficients #

        Horner evaluation of a coefficient list: polyEval [c₀, c₁, …] m = c₀ + m (c₁ + m (…)).

        Equations
        Instances For
          theorem MIPRE.Cost.Data.polyEval_range_map (f : ℕ → ℕ) (k m : ℕ) :
          polyEval (List.map f (List.range k)) m = ∑ i ∈ Finset.range k, f i * m ^ i
          noncomputable def MIPRE.Cost.hornerCoeffs (p : Polynomial ℕ) :

          The coefficient list of a polynomial over ℕ, least significant first and padded to natDegree + 1 entries: the form Horner evaluation consumes (Data.polyEval). Mathlib's Polynomial.coeffList is the big-endian list without the padding.

          Equations
          Instances For

            Close a cost bound after the run has been built: unfold the sizes of the small constants and of unary numerals, and let omega finish.

            Equations
            Instances For

              The increment program #

              Body of the first phase of incProg, on the state cons rest acc: at the end or at a false bit, stop with (true :: acc, rest); at a true bit, move a false onto acc.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                theorem MIPRE.Cost.Prog.incBody_nil (acc : BitStr) :
                ∃ t ≤ (encode acc).size + 20, Eval [(encode []).cons (encode acc)] incBody (Data.nil.cons ((encode (true :: acc)).cons (encode []))) t
                theorem MIPRE.Cost.Prog.incBody_false (r acc : BitStr) :
                ∃ t ≤ (encode r).size + (encode acc).size + 20, Eval [(encode (false :: r)).cons (encode acc)] incBody (Data.nil.cons ((encode (true :: acc)).cons (encode r))) t
                theorem MIPRE.Cost.Prog.incBody_true (r acc : BitStr) :
                ∃ t ≤ (encode r).size + (encode acc).size + 20, Eval [(encode (true :: r)).cons (encode acc)] incBody ((Data.nil.cons Data.nil).cons ((encode r).cons (encode (false :: acc)))) t
                theorem MIPRE.Cost.Prog.incLoop_runs (l acc : BitStr) (env : Env) (S : ℕ) (hS : (encode l).size + (encode acc).size + 3 * List.length l ≤ S) :
                ∃ t ≤ (List.length l + 1) * (S + 21), Eval ((encode l).cons (encode acc) :: env) incBody.loop ((encode (Data.incAcc l acc).1).cons (encode (Data.incAcc l acc).2)) t

                The first phase of the increment, on (rest, acc).

                theorem MIPRE.Cost.Prog.incProg_runs (l : BitStr) :
                ∃ t ≤ (List.length l + 2) * (8 * (encode l).size + 8 * List.length l + 60), incProg.Runs (encode l) (encode (Data.inc l)) t

                incProg computes the successor of a binary numeral.

                theorem MIPRE.Cost.Prog.incProg_runs_nat (n : ℕ) :
                ∃ t ≤ (n.size + 2) * (8 * esize n + 8 * n.size + 60), incProg.Runs (encode n) (encode (n + 1)) t

                The successor on canonical numerals, as a run on encode n.

                Binary to unary #

                Body of toUnaryProg, on the state cons rest acc (rest the remaining bits, most significant first; acc a unary numeral): double acc and add the next bit.

                Equations
                • One or more equations did not get rendered due to their size.
                Instances For
                  theorem MIPRE.Cost.Prog.double_runs (k : ℕ) (env : Env) :
                  ∃ t ≤ (k + 1) * (4 * k + 14), Eval ((Data.ofNat k).cons (Data.ofNat k) :: env) revOntoProg (Data.ofNat (2 * k)) t

                  The doubling of a unary numeral by revOntoProg.

                  theorem MIPRE.Cost.Prog.toUnaryBody_step (b : Bool) (r : BitStr) (k : ℕ) :
                  ∃ t ≤ (k + 1) * (4 * k + 14) + (encode r).size + 8 * k + 64, Eval [(encode (b :: r)).cons (Data.ofNat k)] toUnaryBody ((Data.nil.cons Data.nil).cons ((encode r).cons (Data.ofNat (2 * k + b.toNat)))) t
                  theorem MIPRE.Cost.Prog.toUnaryLoop_runs (l : List Bool) (k : ℕ) (env : Env) (N : ℕ) (hN : Data.msbFold l k = N) (S : ℕ) (hS : (encode l).size ≤ S) :
                  ∃ t ≤ (l.length + 1) * ((N + 1) * (4 * N + 14) + S + 8 * N + 65), Eval ((encode l).cons (Data.ofNat k) :: env) toUnaryBody.loop (Data.ofNat N) t

                  The unary fold over the bits, most significant first: from (rest, ofNat k) to ofNat (msbFold rest k), in time (|rest| + 1) · B for B a bound depending on the final value N = msbFold rest k.

                  theorem MIPRE.Cost.Prog.toUnaryProg_runs (n : ℕ) :
                  ∃ t ≤ (n.size + 2) * ((n + 1) * (4 * n + 14) + 7 * esize n + 8 * n + 90), toUnaryProg.Runs (encode n) (Data.ofNat n) t

                  toUnaryProg converts a binary numeral to unary.

                  Multiplication of unary numerals #

                  Body of the multiplication loop, on the state cons bRest acc, with the first factor a one variable further out: at the end stop with acc, otherwise add a to acc.

                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For
                    theorem MIPRE.Cost.Prog.mulBody_nil (a acc : ℕ) (rest : Env) :
                    ∃ t ≤ 2 * acc + 20, Eval ((Data.ofNat 0).cons (Data.ofNat acc) :: Data.ofNat a :: rest) mulBody (Data.nil.cons (Data.ofNat acc)) t
                    theorem MIPRE.Cost.Prog.mulBody_step (a b' acc : ℕ) (rest : Env) :
                    ∃ t ≤ (a + 1) * (4 * a + 2 * acc + 15) + 4 * a + 4 * acc + 2 * b' + 40, Eval ((Data.ofNat (b' + 1)).cons (Data.ofNat acc) :: Data.ofNat a :: rest) mulBody ((Data.nil.cons Data.nil).cons ((Data.ofNat b').cons (Data.ofNat (a + acc)))) t
                    theorem MIPRE.Cost.Prog.mulLoop_runs (a b acc : ℕ) (rest : Env) (P : ℕ) (hP : acc + a * b ≤ P) :
                    ∃ t ≤ (b + 1) * ((a + 1) * (4 * a + 2 * P + 15) + 4 * a + 4 * P + 2 * b + 41), Eval ((Data.ofNat b).cons (Data.ofNat acc) :: Data.ofNat a :: rest) mulBody.loop (Data.ofNat (acc + a * b)) t

                    The multiplication loop: from (ofNat b, ofNat acc) with a one variable out, to ofNat (acc + a b).

                    theorem MIPRE.Cost.Prog.mulProg_runs (a b : ℕ) :
                    ∃ t ≤ (b + 1) * ((a + 1) * (4 * a + 2 * (a * b) + 15) + 4 * a + 4 * (a * b) + 2 * b + 41) + 2 * b + 10, mulProg.Runs ((Data.ofNat a).cons (Data.ofNat b)) (Data.ofNat (a * b)) t

                    mulProg multiplies unary numerals.

                    Polynomials, by Horner's rule #

                    Horner evaluation of the coefficient list cs on a unary input m: polyProg (c :: cs) computes c + m · polyProg cs.

                    Equations
                    Instances For
                      theorem MIPRE.Cost.Prog.polyProg_runs (cs : List ℕ) :
                      ∃ (Q : Polynomial ℕ), ∀ (m : ℕ) (env : Env), ∃ t ≤ Polynomial.eval m Q, Eval (Data.ofNat m :: env) (polyProg cs) (Data.ofNat (Data.polyEval cs m)) t

                      polyProg cs evaluates the polynomial, within a cost polynomial in the argument.

                      Evaluating a fixed polynomial, primitively recursively #

                      The answer-length budget of the tabulation is bound.eval (n + λ) for the fixed polynomial bound of MIPRE.GapCompression, so MIPRE.Halting.tab_computable needs a polynomial's evaluation to be primitive recursive in its argument. It goes through this file's own Data.polyEval and hornerCoeffs rather than Mathlib's Polynomial API: the coefficient list is fixed data, and Horner's rule on a fixed list is a fixed composition of + and *.