Skip to content
Closed
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
2 changes: 2 additions & 0 deletions Complexitylib/Classes.lean
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ import Complexitylib.Classes.L
import Complexitylib.Classes.Exponential
import Complexitylib.Classes.DTISP
import Complexitylib.Classes.Containments
import Complexitylib.Classes.BitEncodable
import Complexitylib.Classes.PPTComputable
61 changes: 61 additions & 0 deletions Complexitylib/Classes/BitEncodable.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Complexitylib.Classes.Pairing

/-!
# Bit-string encoding typeclass

`BitEncodable α` provides a specification-level mapping between a type `α` and `List Bool`,
Comment thread
jkatz2 marked this conversation as resolved.
used to state that a Turing machine's bit-string I/O corresponds to a Lean function operating
on abstract types. The encoding carries **no computational obligation** — it is purely a
correspondence used in the *statements* of PPT predicates, not in any executed code.

## Main definitions

- `BitEncodable` — typeclass with `encode : α → List Bool`, `decode : List Bool → α`,
Comment thread
jkatz2 marked this conversation as resolved.
and a roundtrip proof
- Instances for `Unit`, `List Bool`, `Prod`, `Option`
-/

/-- Specification-level encoding of a type as bit strings.
Used to relate Turing machine I/O to Lean functions on abstract types.
The `decode` function is total: it returns a default value for invalid inputs.
Only the roundtrip property `decode (encode a) = a` is required. -/
class BitEncodable (α : Type) where
/-- Encode a value as a bit string. -/
encode : α → List Bool
/-- Decode a bit string to a value. Returns a default for invalid inputs. -/
decode : List Bool → α
/-- Decoding an encoded value recovers the original. -/
roundtrip : ∀ a, decode (encode a) = a

namespace BitEncodable

instance unit : BitEncodable Unit where
encode _ := []
decode _ := ()
roundtrip _ := rfl

instance listBool : BitEncodable (List Bool) where
encode := id
decode := id
roundtrip _ := rfl

/-- Encode `Option (List Bool)` as a bit string: `none ↦ [false]`,
`some x ↦ true :: x`. -/
instance optionListBool : BitEncodable (Option (List Bool)) where
encode
| none => [false]
| some x => true :: x
decode
| [] => none

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.

why do you need this case?

| false :: _ => none
| true :: x => some x
roundtrip a := by cases a <;> simp

instance prod [BitEncodable α] [BitEncodable β] : BitEncodable (α × β) where
encode := fun (a, b) => pair (BitEncodable.encode a) (BitEncodable.encode b)
decode := fun bits =>
let (l, r) := unpair bits
(BitEncodable.decode l, BitEncodable.decode r)
roundtrip := fun (a, b) => by simp [unpair_pair, BitEncodable.roundtrip]

end BitEncodable
33 changes: 33 additions & 0 deletions Complexitylib/Classes/PPTComputable.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Complexitylib.Models.TuringMachine
import Complexitylib.Asymptotics
import Mathlib.Probability.ProbabilityMassFunction.Basic

/-!
# PPT-computable randomized functions

This file defines `PPTComputable`, a predicate asserting that a randomized function
`List Bool → PMF (List Bool)` is computable by a probabilistic polynomial-time
Turing machine. This bridges the gap between Lean-level probabilistic functions
(using `PMF`) and the NTM computation model (using `outputCount`).

## Main definitions

- `PPTComputable` — a randomized function is PPT-computable if there exists a PPT NTM

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.

Should be "TM" not "NTM"

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The way we define PTMs here is as NTMs with certain properties. That said, maybe we should change the PTM definition to be a PTM which gets spawned with a worktape with a bunch of random bits on it.

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.

Yeah, I think defining a PTM as an NTM is non-standard; defining it as a TM with an extra random tape is better.

whose output distribution matches the function on all inputs
-/

open Complexity

/-- A randomized function `f : List Bool → PMF (List Bool)` is **PPT-computable**
if there exists a PPT NTM whose output distribution matches `f` on all inputs.

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.

Same comment as above

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Same answer.


The output distribution of the NTM with time bound `T` is given by
`outputCount x T y / 2^T`, which must equal `(f x) y` for all inputs `x`
and outputs `y`. The time bound `T` must be polynomial: `T =O (· ^ d)`
for some degree `d`. -/
def PPTComputable (f : List Bool → PMF (List Bool)) : Prop :=
∃ (k : ℕ) (tm : NTM k) (T : ℕ → ℕ) (d : ℕ),

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.

I am unsure how you define NTM k with time bound T. Do you require that it consume a random tape of length exactly T?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

noncomputable def acceptProb (tm : NTM n) (x : List Bool) (T : ℕ) : ℚ :=
might give you an idea of what's going on.

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.

If you re-define PTMs then I guess this will also change,

T =O (· ^ d) ∧
tm.AllPathsHaltIn T ∧
∀ x y,
(↑(tm.outputCount x (T x.length) y) : ENNReal) / ↑(2 ^ (T x.length)) = (f x) y
28 changes: 26 additions & 2 deletions Complexitylib/Classes/Pairing.lean
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,38 @@ search-problem classes.
def pair (x y : List Bool) : List Bool :=

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.

I'm not sure I follow why you need pair/unpair, rather than defining BitEncodable on products of bitstrings

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fair.

(x.flatMap fun b => [b, b]) ++ [false, true] ++ y

private theorem pair_nil_eq (y : List Bool) :
@[simp]
theorem pair_nil_eq (y : List Bool) :
pair [] y = false :: true :: y := by
simp [pair]

private theorem pair_cons_eq (b : Bool) (x y : List Bool) :
@[simp]
theorem pair_cons_eq (b : Bool) (x y : List Bool) :
pair (b :: x) y = b :: b :: pair x y := by
simp [pair, List.append_assoc]

/-- Decode a paired binary string back into two components.
Left inverse of `pair`: `unpair (pair x y) = (x, y)`.
Returns `([], [])` for strings not in the image of `pair`. -/
def unpair : List Bool → List Bool × List Bool
| false :: false :: rest =>
let (x, y) := unpair rest
(false :: x, y)
| true :: true :: rest =>
let (x, y) := unpair rest
(true :: x, y)
| false :: true :: rest => ([], rest)
| _ => ([], [])

/-- `unpair` is a left inverse of `pair`. -/
@[simp]
theorem unpair_pair (x y : List Bool) : unpair (pair x y) = (x, y) := by
induction x with
| nil => rfl
| cons b x' ih =>
rw [pair_cons_eq]
cases b <;> simp only [unpair, ih]

/-- `pair` is injective: if `pair x₁ y₁ = pair x₂ y₂` then `x₁ = x₂` and `y₁ = y₂`. -/
theorem pair_injective {x₁ x₂ : List Bool} {y₁ y₂ : List Bool}
(h : pair x₁ y₁ = pair x₂ y₂) : x₁ = x₂ ∧ y₁ = y₂ := by
Expand Down
Loading