Documentation

Complexity.Computability.RAM.Defs

Random-access machines #

A random-access machine (RAM) is a register machine whose registers hold natural numbers of unbounded size, whose instructions do arithmetic on whole registers, and which can address a register through the contents of another (indirect addressing), so that a fixed program reaches unboundedly many registers Cook and Reckhow, Section 1. This file defines the machine, its single steps and its runs. How long a run takes depends on how instructions are charged, which is the subject of Cslib.RAM.time and its cost measures.

The model extends cslib's unlimited register machines (Cslib.URM): it uses the same register contents Cslib.URM.Regs and their read/write API, a program is again a list of instructions, a state is again a program counter with register contents, a run starts at instruction 0 with the inputs in registers 0, 1, … (Cslib.RAM.State.init), and a state is halted once its program counter is past the end of the program. The instruction set is that of Cook and Reckhow Cook and Reckhow, Table I with three changes: registers hold natural numbers rather than integers, so subtraction is truncated and the conditional jump tests for a nonzero register; there are no input and output instructions, since the inputs sit in registers as for URMs; and there is a multiplication instruction, which permits a separation between unit and logarithmic time (see Cslib.RAM.exists_mul_pow_lt_of_computesInTime_logCost). Halting and evaluation (Cslib.RAM.Halts, Cslib.RAM.HaltsWithResult, Cslib.RAM.eval) are as for URMs, with the output in register 0. Input initialization and output extraction incur no instruction cost. Consequently this is a natural-number function model, not Cook and Reckhow's charged finite-alphabet input/output convention. Complexity comparisons with string machines require explicit encoding and initial-bitlength assumptions; no such simulation is proved here.

Design notes #

Main definitions #

Main results #

References #

Instructions, programs and states #

RAM instructions, written destination first as in Cook and Reckhow's X_i ← X_j + X_k Cook and Reckhow, Table I. The register named by a direct operand is part of the instruction; the register named by an indirect operand is the contents of another register.

  • const (d v : ℕ) : Instr

    const d v sets register d to the constant v.

  • add (d i j : ℕ) : Instr

    add d i j sets register d to the sum of registers i and j.

  • sub (d i j : ℕ) : Instr

    sub d i j sets register d to the truncated difference of registers i and j.

  • mul (d i j : ℕ) : Instr

    mul d i j sets register d to the product of registers i and j.

  • load (d a : ℕ) : Instr

    load d a sets register d to the contents of the register whose index is in register a (an indirect read).

  • store (a i : ℕ) : Instr

    store a i sets the register whose index is in register a to the contents of register i (an indirect write).

  • jpos (i q : ℕ) : Instr

    jpos i q jumps to instruction q if register i is positive, and otherwise proceeds to the next instruction.

Instances For
    def Cslib.RAM.instDecidableEqInstr.decEq (x✝ x✝¹ : Instr) :
    Decidable (x✝ = x✝¹)
    Instances For
      @[instance_reducible]
      @[reducible, inline]

      A RAM program is a list of instructions, indexed by the program counter.

      Instances For

        A RAM state: a program counter (0-indexed) and register contents.

        • pc : ℕ

          The program counter: the index of the next instruction.

        • regs : URM.Regs

          The register contents.

        Instances For
          theorem Cslib.RAM.State.ext {x y : State} (pc : x.pc = y.pc) (regs : x.regs = y.regs) :
          x = y
          theorem Cslib.RAM.State.ext_iff {x y : State} :
          x = y ↔ x.pc = y.pc ∧ x.regs = y.regs

          The initial state on the given inputs: the program counter is 0, and the inputs are in registers 0, 1, …, all other registers holding 0.

          Instances For

            A state is halted for a program once its program counter is past the end of the program.

            Instances For
              @[instance_reducible]
              @[instance_reducible]
              @[simp]
              theorem Cslib.RAM.State.init_pc (inputs : List ℕ) :
              (init inputs).pc = 0

              Execution #

              The state reached by executing an instruction.

              Instances For

                One step of p from s: execute the current instruction, or stay put if s is halted.

                Instances For
                  def Cslib.RAM.run (p : Program) (n : ℕ) :

                  The state after running p from s for n steps, staying put once halted.

                  Instances For
                    inductive Cslib.RAM.Step (p : Program) :
                    State → State → Prop

                    The single-step relation of a program, as for URMs (Cslib.URM.Step): a state that is not halted steps to the result of executing its current instruction.

                    Instances For
                      @[reducible, inline]
                      abbrev Cslib.RAM.Steps (p : Program) :
                      State → State → Prop

                      Multi-step execution: the reflexive transitive closure of Step.

                      Instances For

                        Steps #

                        theorem Cslib.RAM.step_of_getElem? {p : Program} {s : State} {i : Instr} (h : p[s.pc]? = some i) :
                        step p s = i.exec s
                        theorem Cslib.RAM.step_of_isHalted {p : Program} {s : State} (h : s.isHalted p) :
                        step p s = s
                        theorem Cslib.RAM.step_step {p : Program} {s : State} (h : ¬s.isHalted p) :
                        Step p s (step p s)

                        A state that is not halted steps to step p s.

                        theorem Cslib.RAM.Step.step_eq {p : Program} {s t : State} (h : Step p s t) :
                        step p s = t
                        theorem Cslib.RAM.Step.not_isHalted {p : Program} {s t : State} (h : Step p s t) :

                        The step relation is deterministic: each state has at most one successor.

                        theorem Cslib.RAM.step_iff {p : Program} {s t : State} (h : ¬s.isHalted p) :
                        Step p s t ↔ step p s = t

                        A state is halted iff it is normal (has no successor) for the step relation.

                        Runs #

                        @[simp]
                        theorem Cslib.RAM.run_zero {p : Program} {s : State} :
                        run p 0 s = s
                        theorem Cslib.RAM.run_succ {p : Program} {s : State} {n : ℕ} :
                        run p (n + 1) s = run p n (step p s)
                        theorem Cslib.RAM.run_succ' {p : Program} {s : State} {n : ℕ} :
                        run p (n + 1) s = step p (run p n s)
                        theorem Cslib.RAM.run_add {p : Program} {s : State} {m n : ℕ} :
                        run p (m + n) s = run p n (run p m s)

                        Runs compose: running for m + n steps is running for n steps after m.

                        theorem Cslib.RAM.run_of_isHalted {p : Program} {s : State} {n : ℕ} (h : s.isHalted p) :
                        run p n s = s

                        A halted state stays put.

                        theorem Cslib.RAM.run_eq_of_le {p : Program} {s : State} {m n : ℕ} (hmn : m ≤ n) (h : (run p m s).isHalted p) :
                        run p n s = run p m s

                        Once a run has halted, running longer changes nothing.

                        theorem Cslib.RAM.steps_run {p : Program} {s : State} {n : ℕ} :
                        Steps p s (run p n s)
                        theorem Cslib.RAM.steps_iff_exists_run {p : Program} {s t : State} :
                        Steps p s t ↔ ∃ (n : ℕ), run p n s = t

                        The states reachable from s are exactly the states of the run from s.

                        Halting and evaluation #

                        The halting and evaluation API of Cslib.URM (URM/Execution.lean), for RAM programs.

                        theorem Cslib.RAM.Steps.eq_of_halts {p : Program} {s s₁ s₂ : State} (h₁ : Steps p s s₁) (hh₁ : s₁.isHalted p) (h₂ : Steps p s s₂) (hh₂ : s₂.isHalted p) :
                        s₁ = s₂

                        Two halted states reachable from the same state are equal.

                        def Cslib.RAM.Halts (p : Program) (inputs : List ℕ) :

                        A program halts on given inputs if its run from the initial state reaches a halted state.

                        Instances For
                          def Cslib.RAM.Diverges (p : Program) (inputs : List ℕ) :

                          A program diverges on given inputs if it does not halt.

                          Instances For
                            def Cslib.RAM.HaltsWithResult (p : Program) (inputs : List ℕ) (result : ℕ) :

                            A program halts on given inputs with result in the output register 0.

                            Instances For

                              Halting is normalizability for the step relation.

                              theorem Cslib.RAM.halts_iff_exists_run {p : Program} {inputs : List ℕ} :
                              Halts p inputs ↔ ∃ (n : ℕ), (run p n (State.init inputs)).isHalted p

                              A program halts exactly when its run is halted after some number of steps.

                              theorem Cslib.RAM.haltsWithResult_iff_exists_run {p : Program} {inputs : List ℕ} {result : ℕ} :
                              HaltsWithResult p inputs result ↔ ∃ (n : ℕ), (run p n (State.init inputs)).isHalted p ∧ (run p n (State.init inputs)).regs.output = result

                              A program halts with result exactly when its run is halted after some number of steps with result in register 0.

                              theorem Cslib.RAM.HaltsWithResult.toHalts {p : Program} {inputs : List ℕ} {result : ℕ} (h : HaltsWithResult p inputs result) :
                              Halts p inputs

                              A program that halts with a result halts.

                              The halted state reached from the initial state, if any: the run after the least number of steps after which it is halted.

                              Instances For
                                theorem Cslib.RAM.evalState_spec {p : Program} {inputs : List ℕ} (h : (evalState p inputs).Dom) :
                                Steps p (State.init inputs) ((evalState p inputs).get h) ∧ ((evalState p inputs).get h).isHalted p

                                The state given by evalState is reachable and halted.

                                theorem Cslib.RAM.Halts.toHaltsWithResult {p : Program} {inputs : List ℕ} (h : Halts p inputs) :
                                HaltsWithResult p inputs ((evalState p inputs).get h).regs.output

                                A program that halts halts with the output of the state given by evalState.

                                def Cslib.RAM.eval (p : Program) (inputs : List ℕ) :

                                Evaluation as a partial function: defined when the program halts, with the contents of the output register 0.

                                Instances For
                                  theorem Cslib.RAM.haltsWithResult_iff_eval {p : Program} {inputs : List ℕ} {result : ℕ} :
                                  HaltsWithResult p inputs result ↔ eval p inputs = Part.some result

                                  A program halts with result iff it evaluates to result.