Imports
Polynomial runtime of the unary-length to binary encoder
noncomputable sectionnamespace CLRS.Chapter34.Turing.BinaryNat.Encoderopen PolyBuildertheorem outputSteps_le (bits : List Bool) :
outputSteps bits ≤ 2 * bits.length + 3 := by
by_cases hbits : bits = []
· simp [outputSteps, hbits]
· simp [outputSteps, hbits]
theorem processSteps_le (bits input : List Bool) :
processSteps bits input ≤
input.length * (4 * (bits.length + input.length) + 4) +
2 * (bits.length + input.length) + 4 := by
induction input generalizing bits with
| nil =>
have hout := outputSteps_le bits
simp only [processSteps, List.length_nil, Nat.add_zero,
Nat.zero_mul, Nat.zero_add]
omega
| cons symbol rest ih =>
let nextBits := incrementBits bits
have hnextLength : nextBits.length + rest.length ≤
bits.length + (symbol :: rest).length := by
dsimp [nextBits]
have hinc := incrementBits_length_le bits
calc
(incrementBits bits).length + rest.length ≤
(bits.length + 1) + rest.length :=
Nat.add_le_add_right hinc rest.length
_ = bits.length + (symbol :: rest).length := by simp; omega
have htail := ih nextBits
let currentSize := bits.length + (symbol :: rest).length
let nextSize := nextBits.length + rest.length
have hfactor : 4 * nextSize + 4 ≤ 4 * currentSize + 4 := by
exact Nat.add_le_add_right
(Nat.mul_le_mul_left 4 (by
simpa [nextSize, currentSize] using hnextLength)) 4
have hproduct :
rest.length * (4 * nextSize + 4) ≤
rest.length * (4 * currentSize + 4) :=
Nat.mul_le_mul_left rest.length hfactor
have htail' : processSteps nextBits rest ≤
rest.length * (4 * currentSize + 4) +
2 * currentSize + 4 := by
change processSteps nextBits rest ≤
rest.length * (4 * nextSize + 4) + 2 * nextSize + 4 at htail
have hdouble : 2 * nextSize ≤ 2 * currentSize :=
Nat.mul_le_mul_left 2 (by
simpa [nextSize, currentSize] using hnextLength)
exact htail.trans
(Nat.add_le_add (Nat.add_le_add hproduct hdouble) le_rfl)
have hcarry := carrySteps_le bits []
simp only [List.length_nil, Nat.mul_zero, Nat.add_zero] at hcarry
have hhead : carrySteps bits [] + 1 ≤ 4 * currentSize + 4 := by
have hsize : bits.length ≤ currentSize := by
simp [currentSize]
omega
rw [processSteps]
have hadd := Nat.add_le_add htail' hhead
calc
processSteps nextBits rest + carrySteps bits [] + 1 =
processSteps nextBits rest + (carrySteps bits [] + 1) := by omega
_ ≤ (rest.length * (4 * currentSize + 4) +
2 * currentSize + 4) + (4 * currentSize + 4) := hadd
_ = (symbol :: rest).length *
(4 * (bits.length + (symbol :: rest).length) + 4) +
2 * (bits.length + (symbol :: rest).length) + 4 := by
simp only [List.length_cons]
dsimp [currentSize]
ringExact runtime of the complete encoder.
def encoderSteps (input : List Bool) : Nat :=
processSteps [] inputtheorem encoderSteps_le (input : List Bool) :
encoderSteps input ≤
4 * input.length * input.length + 6 * input.length + 4 := by
have h := processSteps_le [] input
simp only [encoderSteps, List.length_nil, Nat.zero_add] at h ⊢
nlinariththeorem builderOutputs :
BuilderOutputs program
(fun input : List Bool =>
CLRS.Chapter34.encodeBinaryNat input.length)
encoderSteps := by
intro input
exact ⟨by simpa [encoderSteps] using run input⟩theorem outputs :
Outputs program
(fun input : List Bool =>
CLRS.Chapter34.encodeBinaryNat input.length)
encoderSteps :=
Outputs.of_builder_run builderOutputsnoncomputable def polyBound : PolyBound encoderSteps where
polynomial :=
4 * Polynomial.X * Polynomial.X + 6 * Polynomial.X + 4
bound input := by
have h := encoderSteps_le input
simpa [Polynomial.eval_add, Polynomial.eval_mul,
Polynomial.eval_X] using hA genuine fixed TM2 converts a unary count (the length of an arbitrary Boolean input word) to its canonical compact binary representation.
noncomputable def computableInPolyTime :
_root_.Turing.TM2ComputableInPolyTime id id
(fun input : List Bool =>
CLRS.Chapter34.encodeBinaryNat input.length) :=
ComputableInPolyTime program
(fun input : List Bool =>
CLRS.Chapter34.encodeBinaryNat input.length)
encoderSteps outputs polyBoundend CLRS.Chapter34.Turing.BinaryNat.Encoder