|
| 1 | +/- |
| 2 | +Copyright (c) 2026 Samuel Schlesinger. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Samuel Schlesinger |
| 5 | +-/ |
| 6 | + |
| 7 | +module |
| 8 | + |
| 9 | +public import Cslib.Computability.Complexity.Classes.Time |
| 10 | + |
| 11 | +@[expose] public section |
| 12 | + |
| 13 | +/-! |
| 14 | +# Space Complexity Classes |
| 15 | +
|
| 16 | +This file defines space-bounded computation and the complexity class **PSPACE**. |
| 17 | +
|
| 18 | +## Main Definitions |
| 19 | +
|
| 20 | +* `OutputsWithinSpace` — TM outputs on input using at most `s` additional work cells |
| 21 | +* `SpaceBoundedComputable f s` — `f` is computable within space `s` |
| 22 | +* `PSPACE` — languages decidable in polynomial space |
| 23 | +
|
| 24 | +## Main Results |
| 25 | +
|
| 26 | +* `P_subset_PSPACE` — P ⊆ PSPACE |
| 27 | +
|
| 28 | +## References |
| 29 | +
|
| 30 | +* [S. Arora, B. Barak, *Computational Complexity: A Modern Approach*][AroraB2009] |
| 31 | +-/ |
| 32 | + |
| 33 | +open Turing SingleTapeTM Polynomial Relation |
| 34 | + |
| 35 | +variable {Symbol : Type} |
| 36 | + |
| 37 | +namespace Cslib.Complexity |
| 38 | + |
| 39 | +/-- The work space used by a configuration on input `l`: total tape space |
| 40 | +minus the initial input footprint `max 1 l.length`. -/ |
| 41 | +def Cfg.work_space_used (tm : SingleTapeTM Symbol) (l : List Symbol) (cfg : tm.Cfg) : ℕ := |
| 42 | + SingleTapeTM.Cfg.space_used tm cfg - max 1 l.length |
| 43 | + |
| 44 | +/-- A TM `tm` **outputs** `l'` on input `l` using at most `s` additional work cells |
| 45 | +throughout the computation. This combines the time-based reachability |
| 46 | +with a space bound: every configuration along the computation path |
| 47 | +uses at most `s` work space beyond the initial input footprint. -/ |
| 48 | +def OutputsWithinSpace (tm : SingleTapeTM Symbol) |
| 49 | + (l l' : List Symbol) (s : ℕ) : Prop := |
| 50 | + ∃ t : ℕ, tm.OutputsWithinTime l l' t ∧ |
| 51 | + ∀ cfg : tm.Cfg, |
| 52 | + ReflTransGen tm.TransitionRelation (tm.initCfg l) cfg → |
| 53 | + Cfg.work_space_used tm l cfg ≤ s |
| 54 | + |
| 55 | +/-- A function `f` is **space-bounded computable** with space bound `s` |
| 56 | +if there exists a TM computing `f` that uses at most `s(|x|)` additional |
| 57 | +work cells on input `x`. -/ |
| 58 | +structure SpaceBoundedComputable |
| 59 | + (f : List Symbol → List Symbol) (s : ℕ → ℕ) where |
| 60 | + /-- The underlying Turing machine -/ |
| 61 | + tm : SingleTapeTM Symbol |
| 62 | + /-- Proof that the machine computes `f` within space `s` -/ |
| 63 | + outputsInSpace : ∀ a, |
| 64 | + OutputsWithinSpace tm a (f a) (s a.length) |
| 65 | + |
| 66 | +/-- **PSPACE** is the class of languages decidable by a Turing machine |
| 67 | +using polynomial work space. -/ |
| 68 | +def PSPACE : Set (Set (List Symbol)) := |
| 69 | + { L | ∃ f : List Symbol → List Symbol, |
| 70 | + ∃ p : Polynomial ℕ, |
| 71 | + Nonempty (SpaceBoundedComputable f (fun n => p.eval n)) ∧ |
| 72 | + Decides f L } |
| 73 | + |
| 74 | +-- TODO: Define L (LOGSPACE) using multi-tape Turing machines with a |
| 75 | +-- read-only input tape. The single-tape model allows overwriting input |
| 76 | +-- cells, giving O(n) writable space instead of O(log n). |
| 77 | + |
| 78 | +/-- Any configuration reachable during a halting computation has its space |
| 79 | +bounded by the initial space plus the halting time. -/ |
| 80 | +private lemma space_bounded_of_time_bounded (tm : SingleTapeTM Symbol) |
| 81 | + (l l' : List Symbol) (t : ℕ) |
| 82 | + (htime : tm.OutputsWithinTime l l' t) |
| 83 | + (cfg : tm.Cfg) |
| 84 | + (hreach : ReflTransGen tm.TransitionRelation (tm.initCfg l) cfg) : |
| 85 | + Cfg.space_used tm cfg ≤ max 1 l.length + t := by |
| 86 | + -- Convert ReflTransGen to RelatesInSteps. |
| 87 | + obtain ⟨m, hm⟩ := ReflTransGen.relatesInSteps hreach |
| 88 | + -- Extract the halting computation. |
| 89 | + obtain ⟨t', ht'_le, ht'⟩ := htime |
| 90 | + -- `haltCfg` has no successors. |
| 91 | + have hhalt : ∀ cfg', ¬tm.TransitionRelation (tm.haltCfg l') cfg' := |
| 92 | + fun cfg' => no_step_from_halt tm _ cfg' rfl |
| 93 | + -- By determinism, m ≤ t' ≤ t. |
| 94 | + have hm_le := reachable_steps_le_halting_steps tm ht' hhalt hm |
| 95 | + -- Space grows by at most 1 per step. |
| 96 | + have hspace := RelatesInSteps.apply_le_apply_add hm (Cfg.space_used tm) |
| 97 | + fun a b hstep => Cfg.space_used_step a b (Option.mem_def.mp hstep) |
| 98 | + rw [Cfg.space_used_initCfg] at hspace |
| 99 | + omega |
| 100 | + |
| 101 | +/-- Any configuration reachable during a halting computation uses at most `t` |
| 102 | +work cells beyond the initial input footprint. -/ |
| 103 | +private lemma work_space_bounded_of_time_bounded (tm : SingleTapeTM Symbol) |
| 104 | + (l l' : List Symbol) (t : ℕ) |
| 105 | + (htime : tm.OutputsWithinTime l l' t) |
| 106 | + (cfg : tm.Cfg) |
| 107 | + (hreach : ReflTransGen tm.TransitionRelation (tm.initCfg l) cfg) : |
| 108 | + Cfg.work_space_used tm l cfg ≤ t := by |
| 109 | + have htotal := space_bounded_of_time_bounded tm l l' t htime cfg hreach |
| 110 | + apply (Nat.sub_le_iff_le_add).2 |
| 111 | + simpa [Cfg.work_space_used, Nat.add_comm, Nat.add_left_comm, |
| 112 | + Nat.add_assoc] using htotal |
| 113 | + |
| 114 | +/-- **P ⊆ PSPACE**: every language decidable in polynomial time is also |
| 115 | +decidable in polynomial space. |
| 116 | +
|
| 117 | +A TM running in time `t` can use at most `t` additional work cells |
| 118 | +beyond the initial input footprint (at most one new cell per step). |
| 119 | +So a polynomial time bound gives a polynomial work-space bound. -/ |
| 120 | +public theorem P_subset_PSPACE : |
| 121 | + P (Symbol := Symbol) ⊆ PSPACE := by |
| 122 | + intro L ⟨f, ⟨hf⟩, hDecides⟩ |
| 123 | + refine ⟨f, hf.poly, ⟨{ |
| 124 | + tm := hf.tm |
| 125 | + outputsInSpace := fun a => |
| 126 | + ⟨hf.time_bound a.length, hf.outputsFunInTime a, fun cfg hreach => |
| 127 | + le_trans |
| 128 | + (work_space_bounded_of_time_bounded hf.tm a (f a) (hf.time_bound a.length) |
| 129 | + (hf.outputsFunInTime a) cfg hreach) |
| 130 | + (hf.bounds a.length)⟩ |
| 131 | + }⟩, hDecides⟩ |
| 132 | + |
| 133 | +end Cslib.Complexity |
0 commit comments