Documentation

Complexitylib.Classes.Containments.Internal.BlockMember

Searching a block-aligned string for a block #

⚠️ Unreviewed by Bolton

A search that keeps its visited set as a run of fixed-width records must be able to ask whether a record is already there. This file supplies that test as a polynomial-time function: one scan, one block per step, accumulating a flag.

The scan is written as an iteration rather than a recursion, because that is the shape Cobham.iterate_mem_FP consumes — the state is a packed pair (pair u f) rest, and one step compares u against the leading block of rest and drops it.

Main definitions #

Main results #

The scan, on the unpacked state #

One step of a scan that folds a per-record test into a flag. A remainder shorter than one record is a dead end, so the state stands still.

Equations
Instances For
    theorem Complexity.anyStepPair_flag (R : List Bool) {f : List BoolList Bool} (hf : ∀ (z : List Bool), f z = [true] f z = [false]) {s : List Bool × List Bool} (hs : s.1 = [true] s.1 = [false]) (n : ) :
    ((anyStepPair R f)^[n] s).1 = [true] ((anyStepPair R f)^[n] s).1 = [false]

    The flag component of a scan is a flag.

    The remainder never grows.

    theorem Complexity.blockAt_drop (R z : List Bool) (i : ) :
    blockAt R (List.drop R.length z) i = blockAt R z (i + 1)

    Dropping one record shifts the record index.

    theorem Complexity.anyStepPair_flag_eq_true_iff (R : List Bool) {f : List BoolList Bool} (hf : ∀ (z : List Bool), f z = [true] f z = [false]) (s : List Bool × List Bool) (hs : s.1 = [true] s.1 = [false]) (n : ) :
    ((anyStepPair R f)^[n] s).1 = [true] s.1 = [true] i < n, i * R.length + R.length s.2.length f (blockAt R s.2 i) = [true]

    A scan fires exactly when the test fires on one of the records.

    One step of the membership scan: compare u against the leading record.

    Equations
    Instances For
      theorem Complexity.scanStep_flag (R u : List Bool) {s : List Bool × List Bool} (hs : s.1 = [true] s.1 = [false]) (n : ) :
      ((scanStep R u)^[n] s).1 = [true] ((scanStep R u)^[n] s).1 = [false]
      theorem Complexity.scanStep_flag_eq_true_iff (R u : List Bool) (s : List Bool × List Bool) (hs : s.1 = [true] s.1 = [false]) (n : ) :
      ((scanStep R u)^[n] s).1 = [true] s.1 = [true] i < n, i * R.length + R.length s.2.length blockAt R s.2 i = u

      The scan finds a record exactly when one matches.

      The scan, packed #

      def Complexity.memPack (R u f rest : List Bool) :

      The packed scan state: the ruler, then the sought block, the flag and the remaining string. Everything the step needs travels inside the state, which is what Cobham.iterate_mem_FP iterates.

      Equations
      Instances For
        @[simp]
        theorem Complexity.memPack_length (R u f rest : List Bool) :
        (memPack R u f rest).length = 2 * R.length + 2 * (2 * u.length + f.length + 2) + rest.length + 4

        One step of the scan on the packed state.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          theorem Complexity.memStep_pack (R u f rest : List Bool) :
          memStep (memPack R u f rest) = memPack R u (scanStep R u (f, rest)).1 (scanStep R u (f, rest)).2

          The packed step is the unpacked step.

          theorem Complexity.memStep_iterate (R u : List Bool) (s : List Bool × List Bool) (n : ) :
          memStep^[n] (memPack R u s.1 s.2) = memPack R u ((scanStep R u)^[n] s).1 ((scanStep R u)^[n] s).2

          The packed iteration is the unpacked one.

          The verdict #

          Does the block u occur in the block-aligned string V?

          Equations
          Instances For
            theorem Complexity.memFlag_eq_true_iff (R u V : List Bool) (hR : 0 < R.length) :
            memFlag R u V = [true] ∃ (i : ), i * R.length + R.length V.length blockAt R V i = u

            The scan decides membership.

            The scan is polynomial-time #

            theorem Complexity.memStep_iterate_length_le (R u : List Bool) (s : List Bool × List Bool) (hf : s.1 = [true] s.1 = [false]) (n : ) :
            (memStep^[n] (memPack R u s.1 s.2)).length (memPack R u s.1 s.2).length

            The scan's state never grows.

            theorem Complexity.memFlagFn_mem_FP {Rf uf Vf : List BoolList Bool} (hR : Rf FP) (hu : uf FP) (hV : Vf FP) :
            (fun (z : List Bool) => memFlag (Rf z) (uf z) (Vf z)) FP

            The membership scan is polynomial-time.