Skip to content

feat(MultiTapeTM): the identity is computable in linear time and zero space - #885

Open
crei wants to merge 1 commit into
leanprover:mainfrom
crei:identity_complexity
Open

feat(MultiTapeTM): the identity is computable in linear time and zero space#885
crei wants to merge 1 commit into
leanprover:mainfrom
crei:identity_complexity

Conversation

@crei

@crei crei commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

As a combinator, this might not look like a useful lemma, but it will together with some more results: It for example allows us to copy from one tape to another.

@crei
crei force-pushed the identity_complexity branch from a5c82fc to a584a76 Compare September 8, 2026 18:09

@BoltonBailey BoltonBailey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this seems like a good addition. My only feedback is that it looked like the proofs could be golfed a bit (I asked Claude and it indeed came up with some proofs that look shorter and cleaner to me, attached below if you want to use them).

Code

/-- Over an input symbol, the copy machine emits it and moves right. -/
lemma step_scan {n : ℕ} (hn : n < input.length) (out : List Symbol) :
    copy.step (cfg input (some ()) ⟨n + 1, by omega⟩ out) =
      cfg input (some ()) ⟨n + 2, by omega⟩ (out ++ [input[n]]) := by
  rw [step, inputSymbolInner n (by simp only [cfg]; omega) hn]
  refine cfg_ext rfl ?_ rfl
  simp only [Action.apply]
  exact moveInputPos_pos_of_ne_right _ (by simp [cfg]; omega)

/-- On the blank at the right end of the input, the copy machine halts in place. -/
lemma step_halt (out : List Symbol) :
    copy.step (cfg input (some ()) ⟨input.length + 1, by omega⟩ out) =
      cfg input none ⟨input.length + 1, by omega⟩ out := by
  rw [step, inputSymbol_eq_none_of_boundary (Or.inr rfl)]
  exact cfg_ext rfl (by simp [cfg, copy, Action.apply]) (by simp [cfg, copy, Action.apply])

/-- After `n ≤ input.length` steps, the copy machine has copied the first `n` input symbols to the
output and its head is over the `n`-th cell of the input. -/
lemma runFrom_scan (n : ℕ) (hn : n ≤ input.length) :
    copy.runFrom (copy.initCfg input) n =
      cfg input (some ()) ⟨n + 1, by omega⟩ (input.take n) := by
  induction n with
  | zero => exact cfg_ext rfl rfl rfl
  | succ n ih =>
    rw [runFrom_succ_eq_step', ih (by omega), step_scan (by omega), List.take_add_one,
      List.getElem?_eq_getElem (by omega), Option.toList_some]

/-- The complete run: after `input.length + 1` steps the copy machine has halted with the input
copied to the output. -/
lemma runFrom_full (input : List Symbol) :
    copy.runFrom (copy.initCfg input) (input.length + 1) =
      cfg input none ⟨input.length + 1, by omega⟩ input := by
  rw [runFrom_succ_eq_step', runFrom_scan input.length le_rfl, List.take_length, step_halt]

/-- The copy machine outputs its input unchanged, in `input.length + 1` steps and zero space. -/
theorem computesInTimeAndSpace (input : List Symbol) :
    ComputesInTimeAndSpace copy input input (input.length + 1) 0 := by
  refine ⟨?_, ?_, copy.spaceUsed_zero_tapes_eq_zero _ _ rfl⟩ <;> rw [runFrom_full] <;> rfl

end Copy

variable {α : Type*}

/-- The identity function is computable in one step per input symbol and zero space. -/
public theorem computableInTimeAndSpace_id {enc : α ↪ List Bool} :
    ComputableInTimeAndSpace (id : α → α) enc enc
      (fun a => (enc a).length + 1) (fun _ => 0) :=
  ⟨0, Unit, inferInstance, copy, fun a =>
    ⟨_, le_rfl, _, le_rfl, Copy.computesInTimeAndSpace (enc a)⟩⟩

end Turing.MultiTapeTM

position and the output written so far. There are no work tapes. `input` is explicit because it is
inferable only through the expected type: the head position is written as an anonymous
constructor, which pins nothing. -/
def cfg (input : List Symbol) (q : Option Unit) (p : Fin (input.length + 2))

@barni120400 barni120400 Sep 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using a more concise definition of the cfg:

def cfg (input : List Symbol) (q : Option Unit) (n : ℕ) : Cfg 0 Symbol Unit input := ⟨q, ⟨min n input.length + 1, by omega⟩, fun _ _ => none, fun _ => 0, input.take n⟩

the rest of the lemmas also benefit from it


/-- With no work tapes, configurations are equal as soon as the state, the input position and the
output agree. -/
lemma cfg_ext {c₁ c₂ : Cfg 0 Symbol Unit input} (hstate : c₁.state = c₂.state)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a general lemma, now specific for Unit. Is there a better place for this lemma?

Comment on lines +70 to +72
copy.step (cfg input (some ()) ⟨input.length + 1, by omega⟩ out) =
cfg input none ⟨input.length + 1, by omega⟩ out := by
have hsym : (cfg input (some ()) ⟨input.length + 1, by omega⟩ out).inputSymbol =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
copy.step (cfg input (some ()) ⟨input.length + 1, by omega⟩ out) =
cfg input none ⟨input.length + 1, by omega⟩ out := by
have hsym : (cfg input (some ()) ⟨input.length + 1, by omega⟩ out).inputSymbol =
copy.step (cfg input (some ()) (Fin.last _) out) =
cfg input none (Fin.last _) out := by
have hsym : (cfg input (some ()) (Fin.last _) out).inputSymbol =

Comment on lines +97 to +98
cfg input none ⟨input.length + 1, by omega⟩ input := by
rw [runFrom_succ_eq_step', runFrom_scan input.length le_rfl, List.take_length, step_halt]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cfg input none ⟨input.length + 1, by omega⟩ input := by
rw [runFrom_succ_eq_step', runFrom_scan input.length le_rfl, List.take_length, step_halt]
cfg input none (Fin.last _) input := by
rw [runFrom_succ_eq_step', runFrom_scan input.length le_rfl, List.take_length]
exact step_halt input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants