Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Complexity.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,7 @@ public import Complexity.Computability.Complexity.Classes.CeqP.Time
public import Complexity.Computability.Complexity.Classes.Constructible
public import Complexity.Computability.Complexity.Classes.Constructible.Log
public import Complexity.Computability.Complexity.Classes.Constructible.TwoPow
public import Complexity.Computability.Complexity.Classes.Constructible.UnaryClock
public import Complexity.Computability.Complexity.Classes.Counting.OracleSpace
public import Complexity.Computability.Complexity.Classes.Counting.Space
public import Complexity.Computability.Complexity.Classes.CountingSimulation.Accumulate
Expand Down Expand Up @@ -1308,6 +1309,7 @@ public import Complexity.Computability.Complexity.Classes.SharpP.GapMachine
public import Complexity.Computability.Complexity.Classes.SharpP.Lowness
public import Complexity.Computability.Complexity.Classes.SharpP.Machine
public import Complexity.Computability.Complexity.Classes.SharpP.Oracle
public import Complexity.Computability.Complexity.Classes.SharpP.PaddedCount
public import Complexity.Computability.Complexity.Classes.SharpP.PolyTime
public import Complexity.Computability.Complexity.Classes.SharpP.Power
public import Complexity.Computability.Complexity.Classes.SharpP.Probability
Expand Down Expand Up @@ -1839,6 +1841,7 @@ public import Complexity.Computability.Machines.Turing.MultiTape.Counting.Guess
public import Complexity.Computability.Machines.Turing.MultiTape.Counting.Oracle.Program
public import Complexity.Computability.Machines.Turing.MultiTape.Counting.Oracle.Replay
public import Complexity.Computability.Machines.Turing.MultiTape.Counting.OutputPrefix
public import Complexity.Computability.Machines.Turing.MultiTape.Counting.PaddedClock
public import Complexity.Computability.Machines.Turing.MultiTape.Counting.Program
public import Complexity.Computability.Machines.Turing.MultiTape.Counting.Sequential
public import Complexity.Computability.Machines.Turing.MultiTape.Counting.Verdict
Expand Down Expand Up @@ -2015,6 +2018,7 @@ public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.E
public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.ExplicitBlockNetwork.Table
public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.ExplicitBlockNetwork.TablePolyTime
public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.ExtendTapes
public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.HaltedReplay
public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.InputFromTape
public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.IntervalCount
public import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.IntervalCount.PolyTime
Expand Down Expand Up @@ -2944,6 +2948,7 @@ public import Complexity.Foundations.Data.Nat.CeilDiv
public import Complexity.Foundations.Data.Nat.Choose
public import Complexity.Foundations.Data.Nat.Choose.Real
public import Complexity.Foundations.Data.Nat.Div
public import Complexity.Foundations.Data.Nat.Doubling
public import Complexity.Foundations.Data.Nat.Factorial
public import Complexity.Foundations.Data.Nat.IntermediateValue
public import Complexity.Foundations.Data.Nat.Log
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/-
Copyright (c) 2026 Samuel Schlesinger. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Samuel Schlesinger
-/

module
-- upstream: candidate

public import Complexity.Computability.Complexity.Classes.Constructible
public import Complexity.Computability.Machines.Turing.MultiTape.Plumbing.OutputToTape
import Complexity.Computability.Machines.Turing.MultiTape.Complexity.Streaming
import Complexity.Foundations.Data.Nat.Doubling
import Complexity.Computability.Machines.Turing.MultiTape.Plumbing.TransformsTapes
import Complexity.Computability.Machines.Turing.MultiTape.Run

/-!
# Unary clocks of linear length from time-constructible bounds

A time-constructible bound `T` is computed in binary within `O(T n)` steps
(`Cslib.Complexity.TimeConstructible`). Some constructions need a clock in unary instead: a run of
true cells on a work tape that a machine consumes one cell per step. Converting `T n` exactly
from binary to unary by counting down takes `O((T n + 1) ^ 2)` steps
(`Turing.MultiTapeTM.ComputableInO.natToUnary`), which is too slow for linear clocks.

Rounding up to a power of two avoids the conversion. The binary word of `T n` has
`Nat.size (T n)` digits, and doubling a unary counter once per digit writes
`c * 2 ^ Nat.size (T n)` cells. The `i`-th doubling costs `O(c * 2 ^ i)`, so the doublings cost
`O(c * 2 ^ Nat.size (T n)) = O(T n + 1)` together. The rounded clock lies between
`c * (T n + 1)` and `c * (2 * T n + 1)` (`Nat.two_pow_size_le`).

`Cslib.Complexity.TimeConstructible.exists_prepare_unaryClock` packages this as one deterministic
machine that writes the clock on its last work tape within `O(T n)` steps, leaving every other
work tape blank, its input head at the start and nothing emitted. This mirrors the polynomial
budget of `MultiTape.Plumbing.PrepareClock`.

## Main results

* `Cslib.Complexity.TimeConstructible.exists_prepare_unaryClock`: a unary clock of
`c * 2 ^ Nat.size (T n)` cells within `O(T n)` steps.
-/

public section

namespace Turing.MultiTapeTM.ComputableTidilyInO

/-- The geometric sum of powers of two below `2 ^ n`. -/
private theorem sum_range_two_pow_lt (n : ℕ) : ∑ i ∈ Finset.range n, 2 ^ i < 2 ^ n := by
induction n with
| zero => simp
| succ n ih =>
rw [Finset.sum_range_succ, pow_succ]
omega

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Keep this tidy realization inside the proof/kernel rather than exporting a new public ComputableTidilyInO theorem from a Classes module. mul_two_pow_length is a semantic arithmetic-computability result, and this new file is not in the exact-path raw-machine allowlist. The no-public-tidy rule applies to its type even though the final preparation theorem is plain. A private tidy helper can support the preparation proof; expose a plain ComputableInO statement if this arithmetic API is public, preferably in the lower native quantitative module.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fixer-claude-e6cf7b0d-count: ComputableTidilyInO.mul_two_pow_length is now private to UnaryClock.lean and gone from the module docs. The public surface is the plain TimeConstructible.exists_prepare_unaryClock. The local tidy ratchet (scripts/check_tidy_surface.py) matches the baseline. Fixed in fc10e7f.

/-- **`c * 2 ^ l.length` in unary in linear time.** A streaming fold doubles a unary counter once
per bit of `l`. Round `i` costs `O(c * 2 ^ i)`, so the rounds cost `O(c * 2 ^ l.length)` in total,
plus `O(l.length)` for the scan. The tidy realization is private to this file; the public result
is the plain preparation theorem below. -/
private theorem mul_two_pow_length (c : ℕ) :
ComputableTidilyInO (fun l : List Bool => c * 2 ^ l.length) encBits encUnary
(fun l => c * 2 ^ l.length + l.length) fun l => c * 2 ^ l.length + l.length := by
obtain ⟨c₀, hstep, -⟩ := ((ComputableInDegree.unaryAdd (ComputableInDegree.fst encUnary encBool)
(ComputableInDegree.fst encUnary encBool) le_rfl le_rfl).inO_one).tidy
have hstate (l : List Bool) (i : ℕ) (hi : i ≤ l.length) :
(encUnary ((l.take i).foldl (fun m _ => m + m) c)).length = c * 2 ^ i := by
rw [List.foldl_add_self_eq_mul_two_pow, encUnary_apply, List.length_replicate, List.length_take,
Nat.min_eq_left hi]
obtain ⟨K, hK⟩ := ComputableTidilyInTimeAndSpace.foldl_bits_stream_sum (enc := encUnary)
(step := fun m (_ : Bool) => m + m) c hstep
(R := fun _ i => (5 * c₀ + 4) * (c * 2 ^ i + 1))
(Q := fun l => c₀ * (2 * (c * 2 ^ l.length) + 3))
(B := fun l => c * 2 ^ l.length)
(fun l i hi => by
have h₁ := hstate l i hi.le
have h₂ := hstate l (i + 1) hi
simp only [length_encPair, encBool_apply, List.length_singleton, h₁, h₂, pow_succ]
nlinarith)
(fun l i hi => by
have h₁ := hstate l i hi.le
have hpow : c * 2 ^ i ≤ c * 2 ^ l.length :=
Nat.mul_le_mul_left c (Nat.pow_le_pow_right (by norm_num) hi.le)
simp only [length_encPair, encBool_apply, List.length_singleton, h₁]
nlinarith)
(fun l i hi => by
rw [hstate l i hi]
exact Nat.mul_le_mul_left c (Nat.pow_le_pow_right (by norm_num) hi))
refine of_bounds (hK.of_enc_eq (g := fun l : List Bool => c * 2 ^ l.length)
fun l => by rw [List.foldl_add_self_eq_mul_two_pow])
(K * (5 * c₀ + 5) + K * (3 * c₀ + 3) + 1) (fun l => ?_) (fun l => ?_) fun l => ?_
· have hsum := sum_range_two_pow_lt l.length
have hs : ∑ i ∈ Finset.range l.length, (5 * c₀ + 4) * (c * 2 ^ i + 1) ≤
(5 * c₀ + 4) * (c * 2 ^ l.length + l.length) := by
rw [← Finset.mul_sum, Finset.sum_add_distrib, ← Finset.mul_sum, Finset.sum_const,
Finset.card_range, smul_eq_mul, mul_one]
exact Nat.mul_le_mul_left _ (Nat.add_le_add_right (Nat.mul_le_mul_left c hsum.le) _)
have h₁ : ∑ i ∈ Finset.range l.length, (5 * c₀ + 4) * (c * 2 ^ i + 1) + c * 2 ^ l.length + 1
≤ (5 * c₀ + 5) * (c * 2 ^ l.length + l.length + 1) := by
have e : (5 * c₀ + 5) * (c * 2 ^ l.length + l.length + 1) =
(5 * c₀ + 4) * (c * 2 ^ l.length + l.length) + (c * 2 ^ l.length + l.length) +
(5 * c₀ + 5) := by ring
rw [e]
omega
calc K * (∑ i ∈ Finset.range l.length, (5 * c₀ + 4) * (c * 2 ^ i + 1) + c * 2 ^ l.length + 1)
≤ K * ((5 * c₀ + 5) * (c * 2 ^ l.length + l.length + 1)) := Nat.mul_le_mul_left K h₁
_ = K * (5 * c₀ + 5) * (c * 2 ^ l.length + l.length + 1) := by ring
_ ≤ _ := Nat.mul_le_mul_right _ (by omega)
· have h₁ : c₀ * (2 * (c * 2 ^ l.length) + 3) + c * 2 ^ l.length + 1 ≤
(3 * c₀ + 3) * (c * 2 ^ l.length + l.length + 1) := by
have e : (3 * c₀ + 3) * (c * 2 ^ l.length + l.length + 1) =
c₀ * (2 * (c * 2 ^ l.length) + 3) + c₀ * (c * 2 ^ l.length) + 3 * c₀ * l.length +
3 * (c * 2 ^ l.length + l.length + 1) := by ring
rw [e]
omega
calc K * (c₀ * (2 * (c * 2 ^ l.length) + 3) + c * 2 ^ l.length + 1)
≤ K * ((3 * c₀ + 3) * (c * 2 ^ l.length + l.length + 1)) := Nat.mul_le_mul_left K h₁
_ = K * (3 * c₀ + 3) * (c * 2 ^ l.length + l.length + 1) := by ring
_ ≤ _ := Nat.mul_le_mul_right _ (by omega)
· simp only [encUnary_apply, List.length_replicate]
calc c * 2 ^ l.length ≤ 1 * (c * 2 ^ l.length + l.length + 1) := by omega
_ ≤ _ := Nat.mul_le_mul_right _ (by omega)

end Turing.MultiTapeTM.ComputableTidilyInO

namespace Cslib.Complexity

open Turing Turing.MultiTapeTM

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Reuse and rehome the existing binary-size bound. Machines/Turing/MultiTape/Complexity/LogSpace/CounterProgram/Unary.lean:158 already has private two_pow_size_le with this exact statement. Make one general Nat lemma public in a small Foundations Nat/Size topic module and update both clients, without an alias. This file also re-proves the doubling-fold fact already private in Quantitative.lean:689; generalize/share that fact when extracting the arithmetic helper instead of retaining parallel proofs.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fixer-claude-e6cf7b0d-count: there is a new Foundations/Data/Nat/Doubling.lean with Nat.two_pow_size_le and List.foldl_add_self_eq_mul_two_pow. UnaryClock, PaddedCount and LogSpace/CounterProgram/Unary (whose private copy is removed) use Nat.two_pow_size_le. Quantitative.lean's private foldl_double is now a one-line specialization of the shared fold lemma, and UnaryClock uses the shared lemma directly. No aliases. Fixed in fc10e7f.

/-- **A unary clock of linear length.** For a time-constructible `T` and a constant `c`, one
deterministic machine with finitely many states writes `c * 2 ^ Nat.size (T n)` true cells on its
last work tape within `C * T n + C` steps, on every input of length `n`. It halts with every other
work tape blank, all heads at their starting cells and nothing emitted. The clock has between
`c * (T n + 1)` and `c * (2 * T n + 1)` cells (`Nat.lt_size_self`, `Nat.two_pow_size_le`). -/
theorem TimeConstructible.exists_prepare_unaryClock {T : ℕ → ℕ} (hT : TimeConstructible T)
(c : ℕ) :
∃ (r : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeTM (r + 1) Bool State)
(C : ℕ), ∀ input,
machine.runFrom (machine.initCfg input) (C * T input.length + C) =
wordsCfg input none (Function.update (fun _ => []) (Fin.last r)
(List.replicate (c * 2 ^ Nat.size (T input.length)) true)) [] := by
have hbits : ComputableTidilyInO (fun x : List Bool => encNat (T x.length)) encBits encBits
(fun x => T x.length) fun x => T x.length :=
hT.computableInO.tidy.of_enc_eq fun _ => rfl
have hclock := ((ComputableTidilyInO.mul_two_pow_length c).comp hbits).of_enc_eq
(g := fun x : List Bool => List.replicate (c * 2 ^ Nat.size (T x.length)) true)
(encOut := encBits) fun x => by
simp [encUnary_apply, encNat_apply, Nat.size_eq_bits_len]
have hdigits (m : ℕ) : (encNat m).length = Nat.size m := by
rw [encNat_apply, Nat.size_eq_bits_len]
have hlinear (x : List Bool) : T x.length + (c * 2 ^ (encNat (T x.length)).length +
(encNat (T x.length)).length) ≤ (2 * c + 2) * (T x.length + 1) := by
have h₁ := Nat.mul_le_mul_left c (Nat.two_pow_size_le (T x.length))
have h₂ : Nat.size (T x.length) ≤ T x.length := Nat.size_le.mpr Nat.lt_two_pow_self
rw [hdigits]
have e : (2 * c + 2) * (T x.length + 1) = c * (2 * T x.length + 1) + c +
2 * (T x.length + 1) := by ring
rw [e]
omega
obtain ⟨c₁, ⟨r, State, hfinite, machine, hmachine⟩, -⟩ := hclock.mono (2 * c + 2)
(T' := fun x => T x.length) (S' := fun x => T x.length) hlinear hlinear
refine ⟨r, State ⊕ RewindWorkState, inferInstance, machine.outputToWord, c₁ + 2 * c + 2,
fun input => ?_⟩
have hbound : c₁ * (T input.length + 1) +
(List.replicate (c * 2 ^ Nat.size (T input.length)) true).length + 2 ≤
(c₁ + 2 * c + 2) * T input.length + (c₁ + 2 * c + 2) := by
have h₁ := Nat.mul_le_mul_left c (Nat.two_pow_size_le (T input.length))
rw [List.length_replicate]
have e : (c₁ + 2 * c + 2) * T input.length + (c₁ + 2 * c + 2) =
c₁ * (T input.length + 1) + c * (2 * T input.length + 1) + c + 2 * T input.length + 2 := by
ring
rw [e]
omega
have hwrite := (hmachine input).outputToWord.mono hbound le_rfl
obtain ⟨_, _, hrun, ⟨rfl, rfl⟩, _⟩ :=
transformsTapes_iff_runFrom.mp hwrite input (fun _ => []) [] ⟨rfl, rfl⟩
simpa only [initCfg_eq_wordsCfg, encBits_apply, List.nil_append] using hrun

end Cslib.Complexity
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ public import Complexity.Computability.Complexity.Classes.CeqP.Time
public import Complexity.Computability.Complexity.Classes.CountingSimulation.Separation
public import Complexity.Computability.Complexity.Classes.ModP.Time
import Complexity.Computability.Complexity.Classes.FunctionTime.Decide
import Complexity.Computability.Complexity.Classes.SharpP.PaddedCount
import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Basic
import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Membership
import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary
import Complexity.Computability.Machines.Turing.MultiTape.Internal.PolyTimeBinaryDivision

/-!
Expand All @@ -37,9 +39,14 @@ the containments and strict containments of `Cslib.Complexity.ParityTIME`,
`Cslib.Complexity.ModTIME` (for every fixed `k`) and `Cslib.Complexity.CeqTIME`. The bounds are on
time only; no polynomial workspace bound is claimed for these classes.

`NTIME`, `BPTIME` and `PPTIME` reduce in this library to counts of padded fair-coin strings
(`Cslib.Complexity.exists_acceptCount_of_mem_NTIME`), not to terminal-path counts, so they are not
derived here. Their strict containments in `DTIME[2 ^ T]` are in `CountingSimulation.Separation`.
`NTIME`, `BPTIME` and `PPTIME` are such classes too. The library reduces them to padded fair-coin
counts (`Cslib.Complexity.exists_acceptCount_of_mem_NTIME`), and padded counts at a linear clock
are `SharpTIME enc T` functions (`Cslib.Complexity.exists_clock_acceptCount_mem_SharpTIME`).
So `NTIME[T]` is a positivity test of one count, and `PPTIME[T]` and `BPTIME[T]` compare a count
`f` with the count `g = 2 ^ τ` of all coin strings by `g < 2 * f`
(`Cslib.Complexity.exists_mem_SharpTIME_of_mem_NTIME`,
`Cslib.Complexity.exists_mem_SharpTIME_of_mem_PPTIME`). Their strict containments in
`DTIME[2 ^ T]` are instances of the same separation.

## Main results

Expand All @@ -52,6 +59,8 @@ derived here. Their strict containments in `DTIME[2 ^ T]` are in `CountingSimula
`CeqTIME_subset_iUnion_DTIME_two_pow_div_sqrt_log_two`: the containments.
* `ParityTIME_ssubset_DTIME_two_pow`, `ModTIME_ssubset_DTIME_two_pow`,
`CeqTIME_ssubset_DTIME_two_pow`: the strict containments in `DTIME[2 ^ T]`.
* `NTIME_ssubset_DTIME_two_pow`, `BPTIME_ssubset_DTIME_two_pow`, `PPTIME_ssubset_DTIME_two_pow`:
the strict containments of nondeterministic, bounded-error and majority time.

## References

Expand Down Expand Up @@ -194,4 +203,52 @@ theorem CeqTIME_ssubset_DTIME_two_pow (hT : TimeConstructible T) (hTn : ∀ n, m
CeqTIME encBits T ⊂ DTIME encBits fun n => 2 ^ T n :=
ssubset_DTIME_two_pow_of_forall_mem_SharpTIME hT hTn fun _ => CeqTIME_forall_mem_SharpTIME

/-! ### Nondeterministic, bounded-error and majority time -/

private theorem computableInPolyTime_pos :
ComputableInPolyTime (fun p : ℕ × ℕ => decide (0 < p.1)) (encPair encNat encNat) encBool :=
ComputableInPolyTime.binary_lt' (ComputableInPolyTime.const 0)
(ComputableInPolyTime.fst encNat encNat)

private theorem computableInPolyTime_lt_two_mul :
ComputableInPolyTime (fun p : ℕ × ℕ => decide (p.2 < 2 * p.1)) (encPair encNat encNat)
encBool :=
ComputableInPolyTime.binary_lt' (ComputableInPolyTime.snd encNat encNat)
(ComputableInPolyTime.binary_mul' (ComputableInPolyTime.const 2)
(ComputableInPolyTime.fst encNat encNat))

/-- `NTIME[T]` problems are decided by tests of counts in `SharpTIME enc T`. -/
private theorem NTIME_forall_mem_SharpTIME (hT : TimeConstructible T) {A : Set α}
(hA : A ∈ NTIME enc T) :
∃ f ∈ SharpTIME enc T, ∃ g ∈ SharpTIME enc T, ∃ rule : ℕ × ℕ → Bool,
ComputableInPolyTime rule (encPair encNat encNat) encBool ∧
∀ x, x ∈ A ↔ rule (f x, g x) = true := by
obtain ⟨f, hf, hA⟩ := exists_mem_SharpTIME_of_mem_NTIME hT hA
exact ⟨f, hf, f, hf, _, computableInPolyTime_pos, fun x => by simp [hA x]⟩

/-- `PPTIME[T]` problems are decided by tests of counts in `SharpTIME enc T`. -/
private theorem PPTIME_forall_mem_SharpTIME (hT : TimeConstructible T) {A : Set α}
(hA : A ∈ PPTIME enc T) :
∃ f ∈ SharpTIME enc T, ∃ g ∈ SharpTIME enc T, ∃ rule : ℕ × ℕ → Bool,
ComputableInPolyTime rule (encPair encNat encNat) encBool ∧
∀ x, x ∈ A ↔ rule (f x, g x) = true := by
obtain ⟨f, hf, g, hg, hA⟩ := exists_mem_SharpTIME_of_mem_PPTIME hT hA
exact ⟨f, hf, g, hg, _, computableInPolyTime_lt_two_mul, fun x => by simp [hA x]⟩

/-- **`NTIME[T] ⊊ DTIME[2 ^ T]`** for time-constructible `T` with `max n 2 ≤ T n`. -/
theorem NTIME_ssubset_DTIME_two_pow (hT : TimeConstructible T) (hTn : ∀ n, max n 2 ≤ T n) :
NTIME encBits T ⊂ DTIME encBits fun n => 2 ^ T n :=
ssubset_DTIME_two_pow_of_forall_mem_SharpTIME hT hTn fun _ => NTIME_forall_mem_SharpTIME hT

/-- **`BPTIME[T] ⊊ DTIME[2 ^ T]`** for time-constructible `T` with `max n 2 ≤ T n`. -/
theorem BPTIME_ssubset_DTIME_two_pow (hT : TimeConstructible T) (hTn : ∀ n, max n 2 ≤ T n) :
BPTIME encBits T ⊂ DTIME encBits fun n => 2 ^ T n :=
ssubset_DTIME_two_pow_of_forall_mem_SharpTIME hT hTn fun _ hA =>
PPTIME_forall_mem_SharpTIME hT (BPTIME_subset_PPTIME hA)

/-- **`PPTIME[T] ⊊ DTIME[2 ^ T]`** for time-constructible `T` with `max n 2 ≤ T n`. -/
theorem PPTIME_ssubset_DTIME_two_pow (hT : TimeConstructible T) (hTn : ∀ n, max n 2 ≤ T n) :
PPTIME encBits T ⊂ DTIME encBits fun n => 2 ^ T n :=
ssubset_DTIME_two_pow_of_forall_mem_SharpTIME hT hTn fun _ => PPTIME_forall_mem_SharpTIME hT

end Cslib.Complexity.CountingSimulation
Loading
Loading