Documentation

DescriptiveComplexity.Problems.Machine.HaltHard.Input

The input chain: getting the instance into the machine #

Turing.ToPartrec.Code.exists_code gives codes for fixed-arity functions only, so the machine cannot be started on the variable-length bit table of the instance. The continuation stack solves this: since a comp frame applies its code to the value below it, a chain of comp frames applies a fixed code once per frame – one frame per bit (DescriptiveComplexity.HaltHard.inputChain). Each bit frame pushes its bit (Turing.ToPartrec.Code.zero', or the three-node DescriptiveComplexity.HaltHard.pushOne), the next frame folds it into the accumulator (2·acc + b, by a code exists_code supplies), and the last frame runs the semi-decision procedure on the folded number and the universe size.

The number the chain folds is the flattened relation table of the instance read back one binary digit at a time (DescriptiveComplexity.HaltHard.structOfBits, with DescriptiveComplexity.HaltHard.structOfBits_flatten the roundtrip): a FirstOrder.Language.FinStruct is a size and a table, so decoding owes only digit arithmetic, and it is primitive recursive (DescriptiveComplexity.HaltHard.primrec_structOfBits) – which is what lets the Part.assert trick of orderedReduction_codehalt run behind Nat.Partrec'.part_iff₂. The bits enter the chain most significant first, i.e. the flattened table reversed (DescriptiveComplexity.HaltHard.foldl_two_reverse).

The chain is pure comp frames, so its frame region is a run of bare headers (DescriptiveComplexity.HaltHard.frameSeg_inputChain), and its evaluation is total until the final procedure (DescriptiveComplexity.HaltHard.inputChain_dom_iff).

Bits, numbers and flattened tables #

The number whose binary digits are the listed bits, least significant first.

Equations
Instances For
    Dependency graph
    Dependency graph
    theorem DescriptiveComplexity.HaltHard.foldl_two_reverse (l : List Bool) (acc : ) :
    List.foldl (fun (a : ) (b : Bool) => 2 * a + b.toNat) acc l.reverse = acc * 2 ^ l.length + natOfBits l

    Folding bits most significant first computes natOfBits of their reversal.

    Dependency graph
    theorem DescriptiveComplexity.HaltHard.flatten_getD {α : Type} (d : α) (l : List (List α)) (i : ) :
    i < l.length∀ {t : }, t < (l.getD i []).lengthl.flatten.getD ((List.map List.length (List.take i l)).sum + t) d = (l.getD i []).getD t d

    Reading a flattened list of rows at a prefix-sum offset reads inside the row.

    Dependency graph
    theorem DescriptiveComplexity.HaltHard.range_map_getD {α : Type} (l : List α) (d : α) :
    List.map (fun (t : ) => l.getD t d) (List.range l.length) = l

    Reading every position of a list back through getD is the list.

    Dependency graph

    Decoding a number into a structure #

    The offset of the row of symbol i inside the flattened table, over a universe of size c.

    Equations
    Instances For
      Dependency graph
      theorem DescriptiveComplexity.HaltHard.offB_eq_sum {L : FirstOrder.Language} (V : L.FinVocab) (c i : ) :
      i V.numSymsoffB V c i = (List.map (fun (i' : Fin V.numSyms) => c ^ V.arity i') (List.take i (List.finRange V.numSyms))).sum

      The offsets are the prefix sums of the row lengths.

      Dependency graph

      Decoding a number into a concrete structure: the universe has size k + 1, and the relation tables read the binary digits of N, row by row at the offsets of DescriptiveComplexity.HaltHard.offB.

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

        Reading a Boolean digit back.

        Dependency graph

        The roundtrip: decoding the number of the flattened table of a well-shaped concrete structure gives the structure back.

        Dependency graph

        The tables of FirstOrder.Language.FinStruct.ofEquiv are well-shaped: one row per symbol.

        Dependency graph

        The rows of FirstOrder.Language.FinStruct.ofEquiv have the lengths the offsets expect.

        Dependency graph

        Decoding the folded table of an instance gives the instance's concrete presentation.

        Dependency graph

        The decoder is primitive recursive #

        Dependency graph

        Powers of two are primitive recursive in the exponent.

        Dependency graph

        The decoder is primitive recursive, as a function of the pair – what the Part.assert code needs.

        Dependency graph

        The pushed bits, and the fold #

        Dependency graph
        Dependency graph
        Dependency graph
        Dependency graph

        The fold specification: 2·acc + b, of the vector [b, acc, n].

        Equations
        Instances For
          Dependency graph

          The fold code: replace the pushed bit and the accumulator by their fold, keep the rest of the value.

          Equations
          Instances For
            Dependency graph
            theorem DescriptiveComplexity.HaltHard.eval_foldCode (cF : Turing.ToPartrec.Code) (hF : ∀ (v : List.Vector 3), cF.eval v = pure <$> foldSpec v) (b acc n : ) :
            (foldCode cF).eval [b, acc, n] = pure [2 * acc + b, n]
            Dependency graph

            The chain #

            The global code the machine simulates: a container for the two bit pushes, the fold, and the semi-decision procedure. It is never dispatched at its root – only the positions of its four components are.

            Equations
            Instances For
              Dependency graph
              Dependency graph
              Dependency graph
              Dependency graph

              The position of the fold in the container.

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

                The position of the semi-decision procedure in the container.

                Equations
                Instances For
                  Dependency graph
                  Dependency graph
                  Dependency graph
                  Dependency graph
                  Dependency graph
                  Dependency graph

                  The input chain: one comp frame pushing each bit, one folding it in, and a last frame running the procedure.

                  Equations
                  Instances For
                    Dependency graph

                    Evaluating a pending composition is composing the evaluations.

                    Dependency graph

                    The frame region of the chain: a run of bare comp headers.

                    Dependency graph
                    theorem DescriptiveComplexity.HaltHard.cont_eval_inputChain (cF : Turing.ToPartrec.Code) (hF : ∀ (v : List.Vector 3), cF.eval v = pure <$> foldSpec v) (cP : Turing.ToPartrec.Code) (bits : List Bool) (acc n : ) :
                    (inputChain cF cP bits).toCont.eval [acc, n] = cP.eval [List.foldl (fun (a : ) (b : Bool) => 2 * a + b.toNat) acc bits, n]

                    Evaluating the chain folds the bits and hands the result to the procedure.

                    Dependency graph

                    The procedure, and the whole chain #

                    The two codes of the chain exist: a fold code, and a code whose halting on the folded number and the size decides the problem.

                    Dependency graph
                    theorem DescriptiveComplexity.HaltHard.inputChain_dom_iff {L : FirstOrder.Language} {V : L.FinVocab} (P : DecisionProblem L) [L.IsRelational] {cF cP : Turing.ToPartrec.Code} (hF : ∀ (v : List.Vector 3), cF.eval v = pure <$> foldSpec v) (hP : ∀ (N n : ), (cP.eval [N, n]).Dom P.toPred V (structOfBits V (n - 1) N)) (bits : List Bool) (n : ) :
                    ((inputChain cF cP bits.reverse).toCont.eval [0, n]).Dom P.toPred V (structOfBits V (n - 1) (natOfBits bits))

                    What the chain decides: started on [0, n] under the chain of the reversed flattened table, the machine's abstract evaluation terminates exactly when the decoded instance is a yes-instance.

                    Dependency graph