Version history

Submission versions

Newest first. “Current version” is the latest registered successor; drafts are identified separately.

  1. lax-67draft

    The Word RAM

  2. lax-13current versionviewing

    The Word RAM

    GitHub sourceShown on this page

Lax13.Ram

The word RAM

concepts/Lax13/Ram.lean · lax-13

definition

Loading review…

Sign in with ORCID

Community review

Flags

Each flag is tied to a public ORCID identity and explains why this concept may be incorrect.

No flags have been submitted.

    Community review

    Flag this concept

    State precisely what appears incorrect. This explanation will be public under your ORCID name.

    No source line selected.

    Concept map

    Proven claimDefinitionThis conceptRelated conceptA → B: B builds on A

    Definition

    A word RAM is a random access machine whose cells hold words: natural numbers below 2w2 ^ w, for a word length ww that is a parameter of the model. It has a memory of 2w2 ^ w cells, addressed by number, and no other storage. Input arrives on a read-only input tape and output is written on a write-only output tape. A program is a finite sequence of instructions, executed in order unless a jump instruction changes the program counter. Every instruction names the cells it works on: it sets a cell to a literal; it reads or writes a cell through the address held in another cell; it sets a cell to the sum, the difference, the product, the quotient, the bitwise conjunction or the left shift of two cells, or to the bitwise complement of one; it jumps unconditionally or if a cell is zero; it halts; or it reads the next input number into a cell or writes a cell to the output tape.

    All arithmetic is arithmetic on words: every value the machine produces is taken modulo 2w2 ^ w, and every address is taken modulo 2w2 ^ w. Subtraction is truncated at zero rather than wrapping. Division is integer division, with x/0=0x / 0 = 0.

    The machine starts with all memory cells zero, the whole input word on the input tape and the output tape empty; it halts having written the output word. The running time is the number of instructions executed, each costing one time unit.

    Lean source view on GitHub

    1import Mathlib.Data.List.Basic
    2
    3/-!
    4---
    5title: The word RAM
    6type: definition
    7---
    8A word RAM is a random access machine whose cells hold *words*: natural
    9numbers below `2 ^ w`, for a word length `w` that is a parameter of the
    10model. It has a memory of `2 ^ w` cells, addressed by number, and no
    11other storage. Input arrives on a read-only input tape and output is
    12written on a write-only output tape. A program is a finite sequence of
    13instructions, executed in order unless a jump instruction changes the
    14program counter. Every instruction names the cells it works on: it sets
    15a cell to a literal; it reads or writes a cell through the address held
    16in another cell; it sets a cell to the sum, the difference, the product,
    17the quotient, the bitwise conjunction or the left shift of two cells, or
    18to the bitwise complement of one; it jumps unconditionally or if a cell
    19is zero; it halts; or it reads the next input number into a cell or
    20writes a cell to the output tape.
    21
    22All arithmetic is arithmetic on words: every value the machine produces
    23is taken modulo `2 ^ w`, and every address is taken modulo `2 ^ w`.
    24Subtraction is truncated at zero rather than wrapping. Division is
    25integer division, with `x / 0 = 0`.
    26
    27The machine starts with all memory cells zero, the whole input word on
    28the input tape and the output tape empty; it halts having written the
    29output word. The running time is the number of instructions executed,
    30each costing one time unit.
    31
    32# Formalization notes
    33
    34This is the machine the modern analysis of algorithms is stated on. Its
    35format is that of Cook and Reckhow (*Time bounded random access
    36machines*, JCSS 7, 1973): memory cells are the only storage, an
    37instruction is `cell ← f(cells)`, literals enter through one instruction
    38and indirection through two. Its numbers are bounded rather than its
    39instruction set, which is the discipline of Fredman and Willard
    40(*Surpassing the information theoretic bound with fusion trees*, JCSS
    4147, 1993) and of Hagerup (*Sorting and searching on the word RAM*,
    42STACS 1998): cells hold `w`-bit words, `w` is large enough to address
    43the input — `w ≥ log n`, here always written as an explicit inequality
    44against `2 ^ w` at the point of use — and a word operation costs one
    45time unit because on words it is one instruction of a real machine.
    46Multiplication, division, bitwise operations and shifts are then
    47unproblematic, and this is what makes the model the one in which the
    48results of the algorithms literature are actually stated. The formats
    49in which those results are written down simulate one another with
    50constant overhead (van Emde Boas, *Machine models and simulations*,
    51Handbook of Theoretical Computer Science A, 1990, §2).
    52
    53Truncation is definitional and follows a single rule, applied
    54everywhere and with no exceptions: **every value the machine produces
    55is reduced modulo `2 ^ w` at the point of production, and every address
    56is reduced modulo `2 ^ w` at the point of use.** Values are produced
    57into memory, where `setCell` carries the reduction, and onto the output
    58tape, where `Instr.effect` writes it out; addresses are used by every
    59operand of every instruction, by the address `load` and `store` fetch
    60out of a cell, and by `setCell` when it writes. A literal is not
    61reduced where it is written down — that would be a second rule — but
    62the value it produces is, so an oversized literal is never observable
    63except through a word, and only a program's own literals can be
    64oversized in the first place, since every value it can read out of
    65memory is a word. Two consequences make the rule worth its uniformity:
    66every cell the machine can reach holds a word, by construction rather
    67than by an invariant to be proved; and the memory, although indexed by
    68all of `ℕ`, is touched only at the residues below `2 ^ w`, so it is
    69exactly the canonical `2 ^ w`-cell store. For the instructions whose
    70results cannot leave the words — truncated subtraction, division,
    71conjunction, complement — the reduction does nothing; it is written
    72anyway, because a rule without exceptions is easier to review than a
    73case distinction.
    74
    75Subtraction is natural-number monus, truncated at zero, so that a
    76comparison is `sub` followed by `jzero`. The complement is
    77`2 ^ w - 1 - m[b]`, the one value that depends on the word length other
    78than through truncation; with `and` and `shiftl` beside it, every
    79bitwise operation and both shifts take a number of instructions
    80independent of `w`. A program measures `w` itself, by counting the
    81doublings of a cell from `1` until it wraps to zero, so the model needs
    82no instruction reporting the word length and one program serves every
    83word length. The remaining standard operations are derived at constant
    84cost; with `t` and `u` cells the program spares:
    85
    86| operation | instructions | count |
    87|---|---|---|
    88| copy `a ← b` | `set t b; load a t` | 2 |
    89| `a ← b ∨ c` | `and t b c; sub t c t; add a b t` | 3 |
    90| `a ← b ⊕ c` | `and t b c; sub u c t; add u b u; sub a u t` | 4 |
    91| `a ← b ≫ c` | `set t 1; shiftl t t c; div a b t` | 3 |
    92| `a ← b mod c` | `div t b c; mul t t c; sub a b t` | 3 |
    93| if `b ≤ c` goto `l` | `sub t b c; jzero t l` | 2 |
    94| if `b < c` goto `l` | `sub t c b; jzero t l'; jump l; l':` | 3 |
    95| if `b = c` goto `l` | `sub t b c; sub u c b; add t t u; jzero t l` | 4 |
    96
    97`read` reduces the number it takes off the input tape modulo `2 ^ w`,
    98like every other value, so the machine is total in its input and
    99honesty about inputs whose entries do not fit into a word lives on the
    100statement side, in the set of admissible inputs a claim quantifies
    101over.
    102
    103Reading and writing are total: a `halt` instruction halts the machine,
    104an out-of-range program counter halts it, a read from an exhausted
    105input tape halts it, and every memory cell holds a number, so no error
    106states are needed. `Instr.effect` is the whole of the instruction
    107semantics and `step` adds only the fetch, returning `none` exactly when
    108the machine has halted, so the semantics is deterministic and total by
    109construction. `run w p t` is `t`-fold application of `step`, and it is
    110`none` as soon as the machine halts, which is what makes "halts after
    111exactly `t` steps" in `RunsTo` a statement about the *number of
    112instructions executed*: the time measure is intrinsic to the machine
    113and is not an annotation carried alongside the program. `RunsTo`
    114constrains the output tape and nothing else: memory is scratch space
    115and is left unconstrained on halting.
    116
    117The input and output tapes are what makes the machine's memory start
    118out empty, and hence what lets a program address it by fixed cell
    119numbers; an input laid out in memory instead would begin at a cell
    120number depending on the input length. A program that wants random
    121access to its input copies it into memory first, at a cost of one
    122instruction per number.
    123
    124Time is the machine's own step count, one unit per instruction, and it
    125is honest for multiplication precisely because the factors are words.
    126There is no space measure: it would be a further definition over `run`,
    127and space is in any case bounded by the `2 ^ w` cells the machine can
    128address. Randomness is absent as well; a randomized program is a
    129deterministic program that consumes a word list of random numbers,
    130which is definable downstream over this same machine, with no change to
    131the model.
    132-/
    133
    134namespace Lax13.Ram
    135
    136/-- An instruction. The first cell named is the one written, and every
    137other number naming a cell is read; `set` is the only instruction
    138carrying a literal, and `jump`, `jzero` carry a program address. -/
    139inductive Instr
    140 /-- Set cell `a` to the literal `n`. -/
    141 | set (a n : ℕ)
    142 /-- Set cell `a` to the contents of the cell whose address cell `b`
    143 holds. -/
    144 | load (a b : ℕ)
    145 /-- Set the cell whose address cell `a` holds to the contents of cell
    146 `b`. -/
    147 | store (a b : ℕ)
    148 /-- Set cell `a` to the sum of cells `b` and `c`, wrapping around
    149 modulo `2 ^ w`. -/
    150 | add (a b c : ℕ)
    151 /-- Set cell `a` to the difference of cells `b` and `c`, truncated at
    152 zero rather than wrapping around. -/
    153 | sub (a b c : ℕ)
    154 /-- Set cell `a` to the product of cells `b` and `c`, wrapping around
    155 modulo `2 ^ w`. -/
    156 | mul (a b c : ℕ)
    157 /-- Set cell `a` to the quotient of cells `b` and `c`, rounding
    158 towards zero; division by zero yields zero. -/
    159 | div (a b c : ℕ)
    160 /-- Set cell `a` to the bitwise conjunction of cells `b` and `c`. -/
    161 | and (a b c : ℕ)
    162 /-- Set cell `a` to cell `b` shifted left by the number of bits cell
    163 `c` holds, wrapping around modulo `2 ^ w`; a shift by `w` or more
    164 yields zero. -/
    165 | shiftl (a b c : ℕ)
    166 /-- Set cell `a` to the bitwise complement `2 ^ w - 1 - m[b]` of cell
    167 `b` within the word length. -/
    168 | not (a b : ℕ)
    169 /-- Continue at instruction `l`. -/
    170 | jump (l : ℕ)
    171 /-- Continue at instruction `l` if cell `a` is zero. -/
    172 | jzero (a l : ℕ)
    173 /-- Halt. -/
    174 | halt
    175 /-- Read the next number of the input tape into cell `a`, or halt if
    176 the tape is exhausted. -/
    177 | read (a : ℕ)
    178 /-- Append the contents of cell `a` to the output tape. -/
    179 | write (a : ℕ)
    180
    181/-- A program: a finite sequence of instructions, numbered from `0`. -/
    182abbrev Program : Type := List Instr
    183
    184/-- A machine state: the program counter, the contents of every memory
    185cell, the part of the input tape not yet read, and the output tape
    186written so far. Memory is the only storage there is. -/
    187structure State where
    188 /-- The number of the instruction to be executed next. -/
    189 pc : ℕ
    190 /-- The contents of the memory cells; only the cells with number below
    191 `2 ^ w` are ever addressed. -/
    192 mem : ℕ → ℕ
    193 /-- The numbers still to be read from the input tape. -/
    194 inp : List ℕ
    195 /-- The numbers written to the output tape so far. -/
    196 out : List ℕ
    197
    198/-- The memory `m` with cell `a` set to `v`, at word length `w`: the
    199address and the value written are both taken modulo `2 ^ w`. -/
    200def setCell (w : ℕ) (m : ℕ → ℕ) (a v : ℕ) : ℕ → ℕ :=
    201 fun b => if b = a % 2 ^ w then v % 2 ^ w else m b
    202
    203/-- The effect of one instruction on the state at word length `w`, or
    204`none` if it halts the machine, which a `halt` instruction and a read
    205from an exhausted input tape do. Every value produced is reduced modulo
    206`2 ^ w` and every address used is reduced modulo `2 ^ w`. -/
    207def Instr.effect (w : ℕ) : InstrState → Option State
    208 | set a n, s => some { s with pc := s.pc + 1, mem := setCell w s.mem a n }
    209 | load a b, s =>
    210 some
    211 { s with
    212 pc := s.pc + 1
    213 mem := setCell w s.mem a (s.mem (s.mem (b % 2 ^ w) % 2 ^ w)) }
    214 | store a b, s =>
    215 some
    216 { s with
    217 pc := s.pc + 1
    218 mem := setCell w s.mem (s.mem (a % 2 ^ w)) (s.mem (b % 2 ^ w)) }
    219 | add a b c, s =>
    220 some
    221 { s with
    222 pc := s.pc + 1
    223 mem := setCell w s.mem a (s.mem (b % 2 ^ w) + s.mem (c % 2 ^ w)) }
    224 | sub a b c, s =>
    225 some
    226 { s with
    227 pc := s.pc + 1
    228 mem := setCell w s.mem a (s.mem (b % 2 ^ w) - s.mem (c % 2 ^ w)) }
    229 | mul a b c, s =>
    230 some
    231 { s with
    232 pc := s.pc + 1
    233 mem := setCell w s.mem a (s.mem (b % 2 ^ w) * s.mem (c % 2 ^ w)) }
    234 | div a b c, s =>
    235 some
    236 { s with
    237 pc := s.pc + 1
    238 mem := setCell w s.mem a (s.mem (b % 2 ^ w) / s.mem (c % 2 ^ w)) }
    239 | and a b c, s =>
    240 some
    241 { s with
    242 pc := s.pc + 1
    243 mem := setCell w s.mem a (Nat.land (s.mem (b % 2 ^ w)) (s.mem (c % 2 ^ w))) }
    244 | shiftl a b c, s =>
    245 some
    246 { s with
    247 pc := s.pc + 1
    248 mem := setCell w s.mem a (s.mem (b % 2 ^ w) * 2 ^ s.mem (c % 2 ^ w)) }
    249 | not a b, s =>
    250 some
    251 { s with
    252 pc := s.pc + 1
    253 mem := setCell w s.mem a (2 ^ w - 1 - s.mem (b % 2 ^ w)) }
    254 | jump l, s => some { s with pc := l }
    255 | jzero a l, s => some { s with pc := if s.mem (a % 2 ^ w) = 0 then l else s.pc + 1 }
    256 | halt, _ => none
    257 | read a, s =>
    258 s.inp.head?.map fun v =>
    259 { s with pc := s.pc + 1, mem := setCell w s.mem a v, inp := s.inp.tail }
    260 | write a, s =>
    261 some { s with pc := s.pc + 1, out := s.out ++ [s.mem (a % 2 ^ w) % 2 ^ w] }
    262
    263/-- One step of the machine at word length `w`: fetch the instruction
    264the program counter points at and execute it. The result is `none` if
    265the machine has halted, which also happens when the program counter has
    266run past the program. -/
    267def step (w : ℕ) (p : Program) (s : State) : Option State :=
    268 p[s.pc]?.bind fun i => i.effect w s
    269
    270/-- The state after `t` steps at word length `w`, or `none` if the
    271machine halts before executing `t` instructions. -/
    272def run (w : ℕ) (p : Program) : ℕ → State → Option State
    273 | 0, s => some s
    274 | t + 1, s => (step w p s).bind (run w p t)
    275
    276/-- The initial state on input `x`: program counter zero, all memory
    277cells zero, the input word on the input tape, the output tape empty. -/
    278def initState (x : List ℕ) : State where
    279 pc := 0
    280 mem := fun _ => 0
    281 inp := x
    282 out := []
    283
    284/-- Started on input `x` at word length `w`, the machine executes
    285exactly `t` instructions and then halts, having written the word `y` to
    286its output tape. -/
    287def RunsTo (w : ℕ) (p : Program) (x y : List ℕ) (t : ℕ) : Prop :=
    288 ∃ s : State, run w p t (initState x) = some s ∧ step w p s = none ∧ s.out = y
    289
    290end Lax13.Ram
    291

    Formalization notes

    This is the machine the modern analysis of algorithms is stated on. Its format is that of Cook and Reckhow (Time bounded random access machines, JCSS 7, 1973): memory cells are the only storage, an instruction is cellf(cells)cell ← f(cells), literals enter through one instruction and indirection through two. Its numbers are bounded rather than its instruction set, which is the discipline of Fredman and Willard (Surpassing the information theoretic bound with fusion trees, JCSS 47, 1993) and of Hagerup (Sorting and searching on the word RAM, STACS 1998): cells hold ww-bit words, ww is large enough to address the input — wlognw ≥ log n, here always written as an explicit inequality against 2w2 ^ w at the point of use — and a word operation costs one time unit because on words it is one instruction of a real machine. Multiplication, division, bitwise operations and shifts are then unproblematic, and this is what makes the model the one in which the results of the algorithms literature are actually stated. The formats in which those results are written down simulate one another with constant overhead (van Emde Boas, Machine models and simulations, Handbook of Theoretical Computer Science A, 1990, §2).

    Truncation is definitional and follows a single rule, applied everywhere and with no exceptions: every value the machine produces is reduced modulo 2w2 ^ w at the point of production, and every address is reduced modulo 2w2 ^ w at the point of use. Values are produced into memory, where setCellsetCell carries the reduction, and onto the output tape, where Instr.effectInstr.effect writes it out; addresses are used by every operand of every instruction, by the address loadload and storestore fetch out of a cell, and by setCellsetCell when it writes. A literal is not reduced where it is written down — that would be a second rule — but the value it produces is, so an oversized literal is never observable except through a word, and only a program's own literals can be oversized in the first place, since every value it can read out of memory is a word. Two consequences make the rule worth its uniformity: every cell the machine can reach holds a word, by construction rather than by an invariant to be proved; and the memory, although indexed by all of N, is touched only at the residues below 2w2 ^ w, so it is exactly the canonical 2w2 ^ w-cell store. For the instructions whose results cannot leave the words — truncated subtraction, division, conjunction, complement — the reduction does nothing; it is written anyway, because a rule without exceptions is easier to review than a case distinction.

    Subtraction is natural-number monus, truncated at zero, so that a comparison is subsub followed by jzerojzero. The complement is 2w1m[b]2 ^ w - 1 - m[b], the one value that depends on the word length other than through truncation; with andand and shiftlshiftl beside it, every bitwise operation and both shifts take a number of instructions independent of ww. A program measures ww itself, by counting the doublings of a cell from 11 until it wraps to zero, so the model needs no instruction reporting the word length and one program serves every word length. The remaining standard operations are derived at constant cost; with tt and uu cells the program spares:

    operation instructions count
    copy aba ← b settb;loadatset t b; load a t 2
    abca ← b ∨ c andtbc;subtct;addabtand t b c; sub t c t; add a b t 3
    abca ← b ⊕ c andtbc;subuct;addubu;subautand t b c; sub u c t; add u b u; sub a u t 4
    abca ← b ≫ c sett1;shiftlttc;divabtset t 1; shiftl t t c; div a b t 3
    abmodca ← b mod c divtbc;multtc;subabtdiv t b c; mul t t c; sub a b t 3
    if bcb ≤ c goto ll subtbc;jzerotlsub t b c; jzero t l 2
    if b<cb < c goto ll subtcb;jzerotl;jumpl;l:sub t c b; jzero t l'; jump l; l': 3
    if b=cb = c goto ll subtbc;subucb;addttu;jzerotlsub t b c; sub u c b; add t t u; jzero t l 4

    readread reduces the number it takes off the input tape modulo 2w2 ^ w, like every other value, so the machine is total in its input and honesty about inputs whose entries do not fit into a word lives on the statement side, in the set of admissible inputs a claim quantifies over.

    Reading and writing are total: a halthalt instruction halts the machine, an out-of-range program counter halts it, a read from an exhausted input tape halts it, and every memory cell holds a number, so no error states are needed. Instr.effectInstr.effect is the whole of the instruction semantics and stepstep adds only the fetch, returning nonenone exactly when the machine has halted, so the semantics is deterministic and total by construction. runwptrun w p t is tt-fold application of stepstep, and it is nonenone as soon as the machine halts, which is what makes "halts after exactly tt steps" in RunsToRunsTo a statement about the number of instructions executed: the time measure is intrinsic to the machine and is not an annotation carried alongside the program. RunsToRunsTo constrains the output tape and nothing else: memory is scratch space and is left unconstrained on halting.

    The input and output tapes are what makes the machine's memory start out empty, and hence what lets a program address it by fixed cell numbers; an input laid out in memory instead would begin at a cell number depending on the input length. A program that wants random access to its input copies it into memory first, at a cost of one instruction per number.

    Time is the machine's own step count, one unit per instruction, and it is honest for multiplication precisely because the factors are words. There is no space measure: it would be a further definition over runrun, and space is in any case bounded by the 2w2 ^ w cells the machine can address. Randomness is absent as well; a randomized program is a deterministic program that consumes a word list of random numbers, which is definable downstream over this same machine, with no change to the model.

    Community review

    Discussion

    Ask a question or add context. Endorsements and structured flags are kept in the review panel above; your ORCID profile must share a public name.

    0 comments

    Loading discussion…