Random access machines: model and cost measures #
This file defines a Random Access Machine (RAM) — a register machine with indirect addressing — together with logarithmic-cost time and space measures. The design follows the standard successor/register RAM of Cook–Reckhow, Time bounded random access machines (JCSS 7 (1973), 354–375) and the textbook presentations of Papadimitriou (Computational Complexity, §2.6) and van Emde Boas (Machine models and simulations, Handbook of Theoretical Computer Science A, 1990). Conventions are adapted for a clean formalization where a text is silent or divergent, but the cost measure is kept faithful to the literature, because it is exactly the cost measure that determines whether the model is a sound stand-in for a Turing machine.
Why logarithmic cost (the soundness point) #
A RAM stores natural numbers of unbounded magnitude in each register. Under the
naive unit-cost measure — one time unit per instruction regardless of
operand size — a RAM can square a register repeatedly to build the number
2 ^ (2 ^ k) in O(k) steps. That number needs 2 ^ k bits to write down, so
no Turing machine can even emit it in fewer than 2 ^ k steps: unit-cost RAM
time is super-polynomially stronger than Turing time, and the two models are
not polynomially equivalent. Adopting unit cost and then comparing to Turing
machines would be a category error — the exact "reward hacking" this model is
designed to avoid. RAM.logGap_squaring in the surface file turns this into a
theorem about this very model.
The logarithmic-cost measure charges each instruction the total bit-length
of the numbers it manipulates (operand contents, computed results, and, for
indirect operands, the runtime addresses), plus a base cost of 1 so every
step costs at least one time unit. The one exception is sub, which charges its
operands but not its result; truncated subtraction never produces a number
longer than its first operand, so the result is still paid for. Under this
measure the RAM is polynomially equivalent to the multi-tape Turing machine of
Complexitylib.Models.TuringMachine; the precise
two-way simulation bounds are recorded in the surface module
Complexitylib.Models.RandomAccessMachine.
Main definitions #
RAM.Instr— the instruction set (immediate,add/sub/mul, indirectload/store, conditional/unconditional jump,halt)RAM.Cfg— a configuration: a program counter and a register fileℕ → ℕRAM.step,RAM.run— executable single step and fuel-bounded runRAM.bitlen— the length functionl(v) = Nat.size v(number of bits)RAM.Instr.logCost— the logarithmic cost of one instruction in a stateRAM.logTimeUpto,RAM.unitTimeUpto— accumulated log-cost / step countRAM.Cfg.space,RAM.spaceUpto— logarithmic-cost register footprintRAM.initCfg— input convention (length inR₀, bits inR₁ … Rₙ)RAM.Cfg.workSpace,RAM.workSpaceUpto— logarithmic-cost work space, which leaves registers still holding their input value freeRAM.Program.DecidesInTime,RAM.Program.DecidesInSpace— deciding aLanguagewith the verdict read fromR₀, mirroringTM.DecidesInTimeandTM.DecidesInSpace
Design notes #
- Register file
ℕ → ℕ: total and computable, so programs are executable witnesses (#eval-able). Only finitely many registers are ever nonzero along a run; this finite-support invariant makes the space measures well defined. - Space excludes the unmodified input:
RAM.Program.DecidesInSpaceboundsRAM.workSpaceUpto, which charges a register its address bits plus content bits only while its content differs from its initial value. The input registers are therefore free until overwritten, as the read-only input tape is forTM.DecidesInSpace, and space bounds below the input length are meaningful. This follows the literature: Cook–Reckhow keep the input on a separate read-only device, and Slot–van Emde Boas (The problem of space invariance for sequential machines, Inform. and Comput. 77 (1988), 93–122) charge the address and content bits of the registers in use. The input-inclusive footprintRAM.spaceUptoremains the measure that the structured compiler preserves exactly and the TM-to-RAM simulation reports. bitlen v = Nat.size v: the number of binary digits, withbitlen 0 = 0,bitlen 1 = 1,bitlen (2^k) = k + 1. Instruction costs add1so that each step costs≥ 1regardless of operand sizes.- Direct vs. indirect addressing: register literals named in an
instruction (
d,s,t,a) are program constants, bounded by the program size, so the cost does not separately charge for them; runtime addresses (R ainload/store) are charged viabitlen (c.regs a). This keeps the cost within a constant factor of the Cook–Reckhow measure while remaining sound: every value read, computed, or written is charged its bit-length, except the result ofsub, which is bounded by the (charged) first operand. - Out-of-range
pchalts:curInstrreadsInstr.haltwhenpcis past the program, so a program need not end inhaltand jumps may target the end.
The RAM instruction set. Register indices and jump targets are natural
numbers. add/sub/mul are three-address; sub is truncated
subtraction (Nat monus). load/store use indirect addressing — the
accessed register index is itself the content of a register — which is what
makes the machine "random access".
- imm
(d v : ℕ)
: Instr
imm d v: setR d := v(load an immediate constant). - add
(d s t : ℕ)
: Instr
add d s t: setR d := R s + R t. - sub
(d s t : ℕ)
: Instr
sub d s t: setR d := R s ∸ R t(truncated subtraction). - mul
(d s t : ℕ)
: Instr
mul d s t: setR d := R s * R t. - load
(d a : ℕ)
: Instr
load d a: indirect loadR d := R (R a). - store
(a s : ℕ)
: Instr
store a s: indirect storeR (R a) := R s. - jz
(s tgt : ℕ)
: Instr
jz s tgt: ifR s = 0jump totgt, else fall through. - jmp
(tgt : ℕ)
: Instr
jmp tgt: unconditional jump totgt. - halt : Instr
halt: stop the machine.
Instances For
Equations
- One or more equations did not get rendered due to their size.
- Complexity.RAM.instReprInstr.repr Complexity.RAM.Instr.halt prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Complexity.RAM.Instr.halt")).group prec✝
Instances For
Equations
- Complexity.RAM.instReprInstr = { reprPrec := Complexity.RAM.instReprInstr.repr }
Equations
- One or more equations did not get rendered due to their size.
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm a a_1) (Complexity.RAM.Instr.imm b b_1) = if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) (Complexity.RAM.Instr.add d_1 s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) (Complexity.RAM.Instr.sub d_1 s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) (Complexity.RAM.Instr.mul d_1 s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) (Complexity.RAM.Instr.load d_1 a) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) (Complexity.RAM.Instr.store a s) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) (Complexity.RAM.Instr.jz s tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) (Complexity.RAM.Instr.jmp tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.imm d v) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) (Complexity.RAM.Instr.imm d_1 v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) (Complexity.RAM.Instr.sub d_1 s_1 t_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) (Complexity.RAM.Instr.mul d_1 s_1 t_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) (Complexity.RAM.Instr.load d_1 a) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) (Complexity.RAM.Instr.store a s_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) (Complexity.RAM.Instr.jz s_1 tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) (Complexity.RAM.Instr.jmp tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.add d s t) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) (Complexity.RAM.Instr.imm d_1 v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) (Complexity.RAM.Instr.add d_1 s_1 t_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) (Complexity.RAM.Instr.mul d_1 s_1 t_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) (Complexity.RAM.Instr.load d_1 a) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) (Complexity.RAM.Instr.store a s_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) (Complexity.RAM.Instr.jz s_1 tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) (Complexity.RAM.Instr.jmp tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.sub d s t) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) (Complexity.RAM.Instr.imm d_1 v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) (Complexity.RAM.Instr.add d_1 s_1 t_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) (Complexity.RAM.Instr.sub d_1 s_1 t_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) (Complexity.RAM.Instr.load d_1 a) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) (Complexity.RAM.Instr.store a s_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) (Complexity.RAM.Instr.jz s_1 tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) (Complexity.RAM.Instr.jmp tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.mul d s t) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) (Complexity.RAM.Instr.imm d_1 v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) (Complexity.RAM.Instr.add d_1 s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) (Complexity.RAM.Instr.sub d_1 s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) (Complexity.RAM.Instr.mul d_1 s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) (Complexity.RAM.Instr.store a_1 s) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) (Complexity.RAM.Instr.jz s tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) (Complexity.RAM.Instr.jmp tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.load d a) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) (Complexity.RAM.Instr.imm d v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) (Complexity.RAM.Instr.add d s_1 t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) (Complexity.RAM.Instr.sub d s_1 t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) (Complexity.RAM.Instr.mul d s_1 t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) (Complexity.RAM.Instr.load d a_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) (Complexity.RAM.Instr.jz s_1 tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) (Complexity.RAM.Instr.jmp tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.store a s) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) (Complexity.RAM.Instr.imm d v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) (Complexity.RAM.Instr.add d s_1 t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) (Complexity.RAM.Instr.sub d s_1 t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) (Complexity.RAM.Instr.mul d s_1 t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) (Complexity.RAM.Instr.load d a) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) (Complexity.RAM.Instr.store a s_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz a a_1) (Complexity.RAM.Instr.jz b b_1) = if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) (Complexity.RAM.Instr.jmp tgt_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jz s tgt) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) (Complexity.RAM.Instr.imm d v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) (Complexity.RAM.Instr.add d s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) (Complexity.RAM.Instr.sub d s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) (Complexity.RAM.Instr.mul d s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) (Complexity.RAM.Instr.load d a) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) (Complexity.RAM.Instr.store a s) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) (Complexity.RAM.Instr.jz s tgt_1) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp a) (Complexity.RAM.Instr.jmp b) = if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq (Complexity.RAM.Instr.jmp tgt) Complexity.RAM.Instr.halt = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.imm d v) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.add d s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.sub d s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.mul d s t) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.load d a) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.store a s) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.jz s tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt (Complexity.RAM.Instr.jmp tgt) = isFalse ⋯
- Complexity.RAM.instDecidableEqInstr.decEq Complexity.RAM.Instr.halt Complexity.RAM.Instr.halt = isTrue ⋯
Instances For
Equations
A RAM program is a finite list of instructions, indexed by the program counter.
Equations
Instances For
A configuration is halted (for a given program) when the current instruction
is halt — including the case of a program counter past the program end.
Equations
Instances For
Equations
Execute one instruction, producing the successor configuration. halt is a
no-op here; step only applies this to a non-halted configuration.
Equations
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.imm d v) x✝ = { pc := x✝.pc + 1, regs := Function.update x✝.regs d v }
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.add d s t) x✝ = { pc := x✝.pc + 1, regs := Function.update x✝.regs d (x✝.regs s + x✝.regs t) }
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.sub d s t) x✝ = { pc := x✝.pc + 1, regs := Function.update x✝.regs d (x✝.regs s - x✝.regs t) }
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.mul d s t) x✝ = { pc := x✝.pc + 1, regs := Function.update x✝.regs d (x✝.regs s * x✝.regs t) }
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.load d a) x✝ = { pc := x✝.pc + 1, regs := Function.update x✝.regs d (x✝.regs (x✝.regs a)) }
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.store a s) x✝ = { pc := x✝.pc + 1, regs := Function.update x✝.regs (x✝.regs a) (x✝.regs s) }
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.jz s tgt) x✝ = if x✝.regs s = 0 then { pc := tgt, regs := x✝.regs } else { pc := x✝.pc + 1, regs := x✝.regs }
- Complexity.RAM.stepInstr (Complexity.RAM.Instr.jmp tgt) x✝ = { pc := tgt, regs := x✝.regs }
- Complexity.RAM.stepInstr Complexity.RAM.Instr.halt x✝ = x✝
Instances For
Step a RAM by one instruction (a no-op on a halted configuration).
Equations
Instances For
The logarithmic cost of executing instruction i in configuration c: the
base cost 1 plus the bit-length of every value the instruction reads,
computes, or writes (and, for indirect operands, the runtime address), with
one exception: sub charges only its two operands, not its result.
This is the crux of the model's soundness: every number the instruction
touches is charged its bit-length or is no longer than a charged number
(the truncated difference c.regs s - c.regs t is at most c.regs s), so
a run of total log-cost T can only manipulate numbers of bit-length at
most T. See the module docstring.
Equations
- (Complexity.RAM.Instr.imm d v).logCost c = Complexity.RAM.bitlen v + 1
- (Complexity.RAM.Instr.add d s t).logCost c = Complexity.RAM.bitlen (c.regs s) + Complexity.RAM.bitlen (c.regs t) + Complexity.RAM.bitlen (c.regs s + c.regs t) + 1
- (Complexity.RAM.Instr.sub d s t).logCost c = Complexity.RAM.bitlen (c.regs s) + Complexity.RAM.bitlen (c.regs t) + 1
- (Complexity.RAM.Instr.mul d s t).logCost c = Complexity.RAM.bitlen (c.regs s) + Complexity.RAM.bitlen (c.regs t) + Complexity.RAM.bitlen (c.regs s * c.regs t) + 1
- (Complexity.RAM.Instr.load d a).logCost c = Complexity.RAM.bitlen (c.regs a) + Complexity.RAM.bitlen (c.regs (c.regs a)) + 1
- (Complexity.RAM.Instr.store a s).logCost c = Complexity.RAM.bitlen (c.regs a) + Complexity.RAM.bitlen (c.regs s) + 1
- (Complexity.RAM.Instr.jz s tgt).logCost c = Complexity.RAM.bitlen (c.regs s) + 1
- (Complexity.RAM.Instr.jmp tgt).logCost c = 1
- Complexity.RAM.Instr.halt.logCost c = 1
Instances For
The logarithmic cost of the machine's next step.
Equations
- Complexity.RAM.stepLogCost P c = (Complexity.RAM.curInstr P c).logCost c
Instances For
Fuel-bounded run: execute up to fuel steps, stopping early once halted.
Once halted, the configuration is stationary (run_halted), so the final
configuration is independent of any fuel large enough to reach a halt.
Equations
- Complexity.RAM.run P 0 x✝ = x✝
- Complexity.RAM.run P fuel.succ x✝ = if Complexity.RAM.Halted P x✝ then x✝ else Complexity.RAM.run P fuel (Complexity.RAM.step P x✝)
Instances For
Accumulated logarithmic time over a fuel-bounded run: the sum of the per-step logarithmic costs of the non-halted steps taken.
Equations
- Complexity.RAM.logTimeUpto P 0 x✝ = 0
- Complexity.RAM.logTimeUpto P fuel.succ x✝ = if Complexity.RAM.Halted P x✝ then 0 else Complexity.RAM.stepLogCost P x✝ + Complexity.RAM.logTimeUpto P fuel (Complexity.RAM.step P x✝)
Instances For
Accumulated unit time over a fuel-bounded run: simply the number of
non-halted steps taken. Provided for contrast with logTimeUpto; the gap
between the two is exactly what makes unit cost unsound (see the surface
theorem RAM.logGap_squaring).
Equations
- Complexity.RAM.unitTimeUpto P 0 x✝ = 0
- Complexity.RAM.unitTimeUpto P fuel.succ x✝ = if Complexity.RAM.Halted P x✝ then 0 else 1 + Complexity.RAM.unitTimeUpto P fuel (Complexity.RAM.step P x✝)
Instances For
The logarithmic register footprint of a configuration: the total number
of bits needed to name and store every nonzero register — for each nonzero
register i, its address bits bitlen i plus its content bits
bitlen (regs i). Registers holding 0 are free. The finsum is finite
exactly when the register file has finite support, which is an invariant of
every run started from initCfg (run_finiteSupport).
The footprint includes the input registers. Deciding in space is measured by
Cfg.workSpace, which leaves registers still holding their input value
free; the footprint is the absolute measure used to account for compiled
code that runs from an arbitrary store.
Equations
Instances For
Peak register footprint over a fuel-bounded run: the maximum Cfg.space of
any configuration visited (including the halted one).
Equations
- Complexity.RAM.spaceUpto P 0 x✝ = x✝.space
- Complexity.RAM.spaceUpto P fuel.succ x✝ = if Complexity.RAM.Halted P x✝ then x✝.space else max x✝.space (Complexity.RAM.spaceUpto P fuel (Complexity.RAM.step P x✝))
Instances For
The initial configuration on input x: program counter 0, registers set by
initRegs.
Equations
- Complexity.RAM.initCfg x = { pc := 0, regs := Complexity.RAM.initRegs x }
Instances For
The logarithmic work space of a configuration on input x. As in
Cfg.space, a register i is charged its address bits bitlen i plus its
content bits bitlen (regs i), but only while its content differs from its
initial value initRegs x i. Registers still holding their input value —
the length register R₀ and the bit registers R₁ … R_{|x|} until they are
overwritten, and every other register while it holds 0 — are free; an
overwritten input register is charged like any other register.
The finsum is finite whenever the register file has finite support, which
holds along every run from initCfg x
(run_initCfg_workSpace_finiteSupport). See the module docstring for the
convention and its sources.
Equations
- Complexity.RAM.Cfg.workSpace x c = ∑ᶠ (i : ℕ), if c.regs i = Complexity.RAM.initRegs x i then 0 else Complexity.RAM.bitlen i + Complexity.RAM.bitlen (c.regs i)
Instances For
Peak work space over a fuel-bounded run on input x: the maximum
Cfg.workSpace x of any configuration visited (including the halted one).
Equations
- One or more equations did not get rendered due to their size.
- Complexity.RAM.workSpaceUpto P x 0 x✝ = Complexity.RAM.Cfg.workSpace x x✝
Instances For
A program halts within fuel steps on c when the fuel-bounded run
reaches a halted configuration.
Equations
- Complexity.RAM.HaltsIn P c fuel = Complexity.RAM.Halted P (Complexity.RAM.run P fuel c)
Instances For
A program halts on c when it halts within some amount of fuel.
Equations
- Complexity.RAM.Halts P c = ∃ (fuel : ℕ), Complexity.RAM.HaltsIn P c fuel
Instances For
P decides L within logarithmic time T(n): on every input x, the run
halts having spent log-time at most T |x|, with verdict R₀ = 1 when
x ∈ L and R₀ = 0 when x ∉ L. Mirrors TM.DecidesInTime.
Equations
- One or more equations did not get rendered due to their size.
Instances For
P decides L within logarithmic space S(n): on every input x, the run
halts with the correct verdict and peak work space (workSpaceUpto) at most
S |x|. Registers still holding their input value are free, so, as for
TM.DecidesInSpace, reading the input costs nothing beyond the addresses
used to reach it.
Equations
- One or more equations did not get rendered due to their size.