Documentation

MIPRE.Foundations.Cost.Loops

The closure library, part II: loops #

The generic reasoning principle for loop (Eval.loop_of_invariant: an invariant, a strictly decreasing measure and a uniform bound on the body's cost give a run of the loop with cost ≤ (μ + 1) · (B + 1)), and the list and unary-numeral primitives of the library proved by direct induction: reversal onto an accumulator (revOntoProg, revProg) and length in unary (lenProg). Lists are cons-chains (Data.list); unary numerals are lists of nils (Data.ofNat).

Conventions: every program is closed and takes its input in variable 0; a loop's state is the input itself or a pair assembled by let_ in front of the loop; the body stops with cons nil result and continues with cons (cons nil nil) state'. Costs are stated as bounds of the form (iterations + 1) · (S + c) where S is any number dominating the sizes involved, so that the bound is one atom for omega throughout an induction.

Lists as data #

Lists of data as cons-chains.

Equations
Instances For
    @[simp]
    theorem MIPRE.Cost.Data.list_cons (a : Data) (l : List Data) :
    list (a :: l) = a.cons (list l)
    theorem MIPRE.Cost.Data.ofList_eq_list {α : Type u_1} (f : αData) (l : List α) :
    ofList f l = list (List.map f l)
    @[simp]
    theorem MIPRE.Cost.Data.size_list_cons (a : Data) (l : List Data) :
    (list (a :: l)).size = a.size + (list l).size + 1

    The loop principle #

    theorem MIPRE.Cost.Eval.loop_of_invariant {b : Prog} (hb : Prog.WellScoped 1 b) (env : Env) (I : DataProp) (μ : Data) (Q : DataProp) (B : ) (hbody : ∀ (s : Data), I s(∃ (r : Data), tB, Eval [s] b (Data.nil.cons r) t Q r) ∃ (x : Data) (y : Data) (s' : Data), tB, Eval [s] b ((x.cons y).cons s') t I s' μ s' < μ s) (s : Data) :
    I s∃ (r : Data), t ≤ (μ s + 1) * (B + 1), Q r Eval (s :: env) b.loop r t

    Loop with an invariant and a measure. If from every state s satisfying I the body either stops (with a result satisfying Q) or continues to a state s' satisfying I with μ s' < μ s, at cost at most B in both cases, then loop b from any state satisfying I stops with a result satisfying Q, at cost at most (μ s + 1) · (B + 1).

    Reversal onto an accumulator #

    Body of revOntoProg: on state cons xs acc, stop with acc if xs is empty, otherwise move the head of xs onto acc.

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

      revOntoProg on cons xs acc computes reverse xs ++ acc.

      Equations
      Instances For

        One iteration of revOntoBody on a non-empty list.

        The stopping iteration of revOntoBody on the empty list.

        theorem MIPRE.Cost.Prog.revOntoProg_runs (l acc : List Data) (env : Env) (S : ) (hS : (Data.list l).size + (Data.list acc).size S) :
        t ≤ (l.length + 1) * (S + 12), Eval ((Data.list l).cons (Data.list acc) :: env) revOntoProg (Data.list (l.reverse ++ acc)) t

        revOntoProg reverses xs onto acc, in time (|xs| + 1) · (S + 12) for any S dominating the total size of the two lists.

        theorem MIPRE.Cost.Prog.revProg_runs (l : List Data) :
        t ≤ (l.length + 1 + 1) * ((Data.list l).size + 1 + 12), revProg.Runs (Data.list l) (Data.list l.reverse) t

        Length in unary #

        Body of lenProg: on state cons xs acc, stop with acc if xs is empty, otherwise drop the head of xs and prepend a nil to acc. Running it to completion prepends |xs| copies of nil to acc: with acc = nil this is the length in unary, with acc a unary numeral it is addition, with acc = [true] it is the bit string of 2 ^ |xs|.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          theorem MIPRE.Cost.Prog.lenLoop_runs (l acc : List Data) (env : Env) (S : ) (hS : (Data.list l).size + (Data.list acc).size + 2 * l.length S) :
          t ≤ (l.length + 1) * (S + 13), Eval ((Data.list l).cons (Data.list acc) :: env) lenBody.loop (Data.list (List.replicate l.length Data.nil ++ acc)) t

          The loop of lenBody prepends |xs| copies of nil to acc, in time (|xs| + 1) · (S + 13) for any S dominating size xs + size acc + 2 |xs|.

          Length of a list in unary: lenProg on xs computes ofNat |xs|.

          Equations
          Instances For
            theorem MIPRE.Cost.Prog.lenProg_runs (l : List Data) :
            t ≤ (l.length + 1 + 1) * ((Data.list l).size + 1 + 2 * l.length + 13), lenProg.Runs (Data.list l) (Data.ofNat l.length) t